@@ -1385,22 +1385,23 @@ These can be used as types in annotations. They all support subscription using
1385
1385
.. versionadded :: 3.9
1386
1386
1387
1387
1388
- .. data :: TypeGuard
1388
+ .. data :: TypeIs
1389
1389
1390
- Special typing construct for marking user-defined type guard functions.
1390
+ Special typing construct for marking user-defined type predicate functions.
1391
1391
1392
- ``TypeGuard `` can be used to annotate the return type of a user-defined
1393
- type guard function. ``TypeGuard `` only accepts a single type argument.
1394
- At runtime, functions marked this way should return a boolean.
1392
+ ``TypeIs `` can be used to annotate the return type of a user-defined
1393
+ type predicate function. ``TypeIs `` only accepts a single type argument.
1394
+ At runtime, functions marked this way should return a boolean and take at
1395
+ least one positional argument.
1395
1396
1396
- ``TypeGuard `` aims to benefit *type narrowing * -- a technique used by static
1397
+ ``TypeIs `` aims to benefit *type narrowing * -- a technique used by static
1397
1398
type checkers to determine a more precise type of an expression within a
1398
1399
program's code flow. Usually type narrowing is done by analyzing
1399
1400
conditional code flow and applying the narrowing to a block of code. The
1400
- conditional expression here is sometimes referred to as a "type guard "::
1401
+ conditional expression here is sometimes referred to as a "type predicate "::
1401
1402
1402
1403
def is_str(val: str | float):
1403
- # "isinstance" type guard
1404
+ # "isinstance" type predicate
1404
1405
if isinstance(val, str):
1405
1406
# Type of ``val`` is narrowed to ``str``
1406
1407
...
@@ -1409,8 +1410,73 @@ These can be used as types in annotations. They all support subscription using
1409
1410
...
1410
1411
1411
1412
Sometimes it would be convenient to use a user-defined boolean function
1412
- as a type guard. Such a function should use ``TypeGuard[...] `` as its
1413
- return type to alert static type checkers to this intention.
1413
+ as a type predicate. Such a function should use ``TypeIs[...] `` or
1414
+ :data: `TypeGuard ` as its return type to alert static type checkers to
1415
+ this intention. ``TypeIs `` usually has more intuitive behavior than
1416
+ ``TypeGuard ``, but it cannot be used when the input and output types
1417
+ are incompatible (e.g., ``list[object] `` to ``list[int] ``) or when the
1418
+ function does not return ``True `` for all instances of the narrowed type.
1419
+
1420
+ Using ``-> TypeIs[NarrowedType] `` tells the static type checker that for a given
1421
+ function:
1422
+
1423
+ 1. The return value is a boolean.
1424
+ 2. If the return value is ``True ``, the type of its argument
1425
+ is the intersection of the argument's original type and ``NarrowedType ``.
1426
+ 3. If the return value is ``False ``, the type of its argument
1427
+ is narrowed to exclude ``NarrowedType ``.
1428
+
1429
+ For example::
1430
+
1431
+ from typing import assert_type, final, TypeIs
1432
+
1433
+ class Parent: pass
1434
+ class Child(Parent): pass
1435
+ @final
1436
+ class Unrelated: pass
1437
+
1438
+ def is_parent(val: object) -> TypeIs[Parent]:
1439
+ return isinstance(val, Parent)
1440
+
1441
+ def run(arg: Child | Unrelated):
1442
+ if is_parent(arg):
1443
+ # Type of ``arg`` is narrowed to the intersection
1444
+ # of ``Parent`` and ``Child``, which is equivalent to
1445
+ # ``Child``.
1446
+ assert_type(arg, Child)
1447
+ else:
1448
+ # Type of ``arg`` is narrowed to exclude ``Parent``,
1449
+ # so only ``Unrelated`` is left.
1450
+ assert_type(arg, Unrelated)
1451
+
1452
+ The type inside ``TypeIs `` must be consistent with the type of the
1453
+ function's argument; if it is not, static type checkers will raise
1454
+ an error. An incorrectly written ``TypeIs `` function can lead to
1455
+ unsound behavior in the type system; it is the user's responsibility
1456
+ to write such functions in a type-safe manner.
1457
+
1458
+ If a ``TypeIs `` function is a class or instance method, then the type in
1459
+ ``TypeIs `` maps to the type of the second parameter after ``cls `` or
1460
+ ``self ``.
1461
+
1462
+ In short, the form ``def foo(arg: TypeA) -> TypeIs[TypeB]: ... ``,
1463
+ means that if ``foo(arg) `` returns ``True ``, then ``arg `` is an instance
1464
+ of ``TypeB ``, and if it returns ``False ``, it is not an instance of ``TypeB ``.
1465
+
1466
+ ``TypeIs `` also works with type variables. For more information, see
1467
+ :pep: `742 ` (Narrowing types with ``TypeIs ``).
1468
+
1469
+ .. versionadded :: 3.13
1470
+
1471
+
1472
+ .. data :: TypeGuard
1473
+
1474
+ Special typing construct for marking user-defined type predicate functions.
1475
+
1476
+ Type predicate functions are user-defined functions that return whether their
1477
+ argument is an instance of a particular type.
1478
+ ``TypeGuard `` works similarly to :data: `TypeIs `, but has subtly different
1479
+ effects on type checking behavior (see below).
1414
1480
1415
1481
Using ``-> TypeGuard `` tells the static type checker that for a given
1416
1482
function:
@@ -1419,6 +1485,8 @@ These can be used as types in annotations. They all support subscription using
1419
1485
2. If the return value is ``True ``, the type of its argument
1420
1486
is the type inside ``TypeGuard ``.
1421
1487
1488
+ ``TypeGuard `` also works with type variables. See :pep: `647 ` for more details.
1489
+
1422
1490
For example::
1423
1491
1424
1492
def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
@@ -1433,23 +1501,19 @@ These can be used as types in annotations. They all support subscription using
1433
1501
# Type of ``val`` remains as ``list[object]``.
1434
1502
print("Not a list of strings!")
1435
1503
1436
- If ``is_str_list `` is a class or instance method, then the type in
1437
- ``TypeGuard `` maps to the type of the second parameter after ``cls `` or
1438
- ``self ``.
1439
-
1440
- In short, the form ``def foo(arg: TypeA) -> TypeGuard[TypeB]: ... ``,
1441
- means that if ``foo(arg) `` returns ``True ``, then ``arg `` narrows from
1442
- ``TypeA `` to ``TypeB ``.
1443
-
1444
- .. note ::
1445
-
1446
- ``TypeB `` need not be a narrower form of ``TypeA `` -- it can even be a
1447
- wider form. The main reason is to allow for things like
1448
- narrowing ``list[object] `` to ``list[str] `` even though the latter
1449
- is not a subtype of the former, since ``list `` is invariant.
1450
- The responsibility of writing type-safe type guards is left to the user.
1451
-
1452
- ``TypeGuard `` also works with type variables. See :pep: `647 ` for more details.
1504
+ ``TypeIs `` and ``TypeGuard `` differ in the following ways:
1505
+
1506
+ * ``TypeIs `` requires the narrowed type to be a subtype of the input type, while
1507
+ ``TypeGuard `` does not. The main reason is to allow for things like
1508
+ narrowing ``list[object] `` to ``list[str] `` even though the latter
1509
+ is not a subtype of the former, since ``list `` is invariant.
1510
+ * When a ``TypeGuard `` function returns ``True ``, type checkers narrow the type of the
1511
+ variable to exactly the ``TypeGuard `` type. When a ``TypeIs `` function returns ``True ``,
1512
+ type checkers can infer a more precise type combining the previously known type of the
1513
+ variable with the ``TypeIs `` type. (Technically, this is known as an intersection type.)
1514
+ * When a ``TypeGuard `` function returns ``False ``, type checkers cannot narrow the type of
1515
+ the variable at all. When a ``TypeIs `` function returns ``False ``, type checkers can narrow
1516
+ the type of the variable to exclude the ``TypeIs `` type.
1453
1517
1454
1518
.. versionadded :: 3.10
1455
1519
0 commit comments