Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit21d46ed

Browse files
Chelsea DurazoJukkaL
Chelsea Durazo
authored andcommitted
documentation for TypeIs (#17821)
Fixes#17156.As requested in the issue, added documentation for the desired behaviourof TypeIs.
1 parentc692943 commit21d46ed

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed

‎docs/source/type_narrowing.rst‎

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,169 @@ or rewrite the function to be slightly more verbose:
389389
elif bisnotNone:
390390
return b
391391
return C()
392+
393+
394+
.. _typeis:
395+
396+
TypeIs
397+
------
398+
399+
Mypy supports TypeIs (:pep:`742`).
400+
401+
A `TypeIs narrowing function<https://typing.readthedocs.io/en/latest/spec/narrowing.html#typeis>`_
402+
allows you to define custom type checks that can narrow the type of a variable
403+
in `both the if and else <https://docs.python.org/3.13/library/typing.html#typing.TypeIs>_`
404+
branches of a conditional, similar to how the built-in isinstance() function works.
405+
406+
TypeIs is new in Python 3.13 — for use in older Python versions, use the backport
407+
from `typing_extensions <https://typing-extensions.readthedocs.io/en/latest/>_`
408+
409+
Consider the following example using TypeIs:
410+
411+
..code-block::python
412+
413+
from typingimport TypeIs
414+
415+
defis_str(x:object) -> TypeIs[str]:
416+
returnisinstance(x,str)
417+
418+
defprocess(x:int|str) ->None:
419+
if is_str(x):
420+
reveal_type(x)# Revealed type is 'str'
421+
print(x.upper())# Valid: x is str
422+
else:
423+
reveal_type(x)# Revealed type is 'int'
424+
print(x+1)# Valid: x is int
425+
426+
In this example, the function is_str is a type narrowing function
427+
that returns TypeIs[str]. When used in an if statement, x is narrowed
428+
to str in the if branch and to int in the else branch.
429+
430+
Key points:
431+
432+
433+
- The function must accept at least one positional argument.
434+
435+
- The return type is annotated as ``TypeIs[T]``, where ``T`` is the type you
436+
want to narrow to.
437+
438+
- The function must return a ``bool`` value.
439+
440+
- In the ``if`` branch (when the function returns ``True``), the type of the
441+
argument is narrowed to the intersection of its original type and ``T``.
442+
443+
- In the ``else`` branch (when the function returns ``False``), the type of
444+
the argument is narrowed to the intersection of its original type and the
445+
complement of ``T``.
446+
447+
448+
TypeIs vs TypeGuard
449+
~~~~~~~~~~~~~~~~~~~
450+
451+
While both TypeIs and TypeGuard allow you to define custom type narrowing
452+
functions, they differ in important ways:
453+
454+
- **Type narrowing behavior**: TypeIs narrows the type in both the if and else branches,
455+
whereas TypeGuard narrows only in the if branch.
456+
457+
- **Compatibility requirement**: TypeIs requires that the narrowed type T be
458+
compatible with the input type of the function. TypeGuard does not have this restriction.
459+
460+
- **Type inference**: With TypeIs, the type checker may infer a more precise type by
461+
combining existing type information with T.
462+
463+
Here's an example demonstrating the behavior with TypeGuard:
464+
465+
..code-block::python
466+
467+
from typingimport TypeGuard, reveal_type
468+
469+
defis_str(x:object) -> TypeGuard[str]:
470+
returnisinstance(x,str)
471+
472+
defprocess(x:int|str) ->None:
473+
if is_str(x):
474+
reveal_type(x)# Revealed type is "builtins.str"
475+
print(x.upper())# ok: x is str
476+
else:
477+
reveal_type(x)# Revealed type is "Union[builtins.int, builtins.str]"
478+
print(x+1)# ERROR: Unsupported operand types for + ("str" and "int") [operator]
479+
480+
Generic TypeIs
481+
~~~~~~~~~~~~~~
482+
483+
``TypeIs`` functions can also work with generic types:
484+
485+
..code-block::python
486+
487+
from typingimport TypeVar, TypeIs
488+
489+
T= TypeVar('T')
490+
491+
defis_two_element_tuple(val: tuple[T,...]) -> TypeIs[tuple[T, T]]:
492+
returnlen(val)==2
493+
494+
defprocess(names: tuple[str,...]) ->None:
495+
if is_two_element_tuple(names):
496+
reveal_type(names)# Revealed type is 'tuple[str, str]'
497+
else:
498+
reveal_type(names)# Revealed type is 'tuple[str, ...]'
499+
500+
501+
TypeIs with Additional Parameters
502+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
503+
TypeIs functions can accept additional parameters beyond the first.
504+
The type narrowing applies only to the first argument.
505+
506+
..code-block::python
507+
508+
from typingimport Any, TypeVar, reveal_type, TypeIs
509+
510+
T= TypeVar('T')
511+
512+
defis_instance_of(val: Any,typ: type[T]) -> TypeIs[T]:
513+
returnisinstance(val, typ)
514+
515+
defprocess(x: Any) ->None:
516+
if is_instance_of(x,int):
517+
reveal_type(x)# Revealed type is 'int'
518+
print(x+1)# ok
519+
else:
520+
reveal_type(x)# Revealed type is 'Any'
521+
522+
TypeIs in Methods
523+
~~~~~~~~~~~~~~~~~
524+
525+
A method can also serve as a ``TypeIs`` function. Note that in instance or
526+
class methods, the type narrowing applies to the second parameter
527+
(after ``self`` or ``cls``).
528+
529+
..code-block::python
530+
531+
classValidator:
532+
defis_valid(self,instance:object) -> TypeIs[str]:
533+
returnisinstance(instance,str)
534+
535+
defprocess(self,to_validate:object) ->None:
536+
if Validator().is_valid(to_validate):
537+
reveal_type(to_validate)# Revealed type is 'str'
538+
print(to_validate.upper())# ok: to_validate is str
539+
540+
541+
Assignment Expressions with TypeIs
542+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
543+
544+
You can use the assignment expression operator ``:=`` with ``TypeIs`` to create a new variable and narrow its type simultaneously.
545+
546+
..code-block::python
547+
548+
from typingimport TypeIs, reveal_type
549+
550+
defis_float(x:object) -> TypeIs[float]:
551+
returnisinstance(x,float)
552+
553+
defmain(a:object) ->None:
554+
if is_float(x:= a):
555+
reveal_type(x)# Revealed type is 'float'
556+
# x is narrowed to float in this block
557+
print(x+1.0)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp