@@ -46,7 +46,7 @@ this gap by adding type manipulation facilities that
4646are better able to keep up with dynamic Python code.
4747
4848There is demand for this. In the analysis of the
49- responses to Meta's 2025 Typed Python Survey [ #survey ]_ , the first
49+ responses to Meta's ` 2025 Typed Python Survey < #survey _>`__ , the first
5050entry on the list of "Most Requested Features" was:
5151
5252 **Missing Features From TypeScript and Other Languages **: Many respondents
@@ -150,13 +150,13 @@ Even further, an IDE could offer code completion for
150150all arguments of the ``db.select() `` call (matching the
151151actual database column names), recursively.
152152
153- (Example code for implementing this :ref: `below <qb-impl >`.)
153+ (Example code for implementing this :ref: `below <pep827- qb-impl >`.)
154154
155155
156156Automatically deriving FastAPI CRUD models
157157------------------------------------------
158158
159- In the `FastAPI tutorial <#fastapi-tutorial _>`_, they show how to
159+ The `FastAPI tutorial <#fastapi-tutorial _>`_, shows how to
160160build CRUD endpoints for a simple ``Hero `` type. At its heart is a
161161series of class definitions used both to define the database interface
162162and to perform validation and filtering of the data in the endpoint::
@@ -261,7 +261,7 @@ based on the attributes of an object. The most well-known example of
261261this is generating ``__init__ `` methods for dataclasses,
262262which we present a simplified example of.
263263
264- This kind of pattern is widespread enough that :pep: `PEP 681 < 681 > `
264+ This kind of pattern is widespread enough that :pep: `681 `
265265was created to represent a lowest-common denominator subset of what
266266existing libraries do.
267267
@@ -279,7 +279,7 @@ typing. The situation was substantially improved by the introduction of
279279``ParamSpec `` in :pep: `612 `, but a number of patterns remain
280280unsupported:
281281
282- * Adding/removing/modifying a keyword parameter
282+ * Adding/removing/modifying a keyword parameter.
283283* Adding/removing/modifying a variable number of parameters. (Though
284284 ``TypeVarTuple `` is close to being able to support adding and
285285 removing, if multiple unpackings were to be allowed, and Pyre
@@ -312,7 +312,7 @@ Here ``BaseTypedDict`` is defined as::
312312 class BaseTypedDict(typing.TypedDict):
313313 pass
314314
315- But any TypedDict would be allowed there.
315+ But any :class: ` ~typing. TypedDict` would be allowed there.
316316
317317Then, if we had a call like::
318318
@@ -325,9 +325,9 @@ the type inferred for ``K`` would be something like::
325325 TypedDict({'x': int, 'y': list[str]})
326326
327327This is basically a combination of
328- "PEP 692 – Using TypedDict for more precise ``**kwargs `` typing"
328+ :pep: ` 692 ` " Using TypedDict for more precise ``**kwargs `` typing"
329329and the behavior of ``Unpack `` for ``*args ``
330- from "PEP 646 – Variadic Generics".
330+ from :pep: ` 646 ` " Variadic Generics".
331331
332332When inferring types here, the type checker should **infer literal
333333types when possible **. This means inferring literal types for
@@ -340,7 +340,6 @@ have its type inferred as ``Never``, to indicate that it was not
340340provided. (This can only be done for read-only items, since non
341341read-only items are invariant.)
342342
343-
344343This is potentially moderately useful on its own but is being done to
345344support processing ``**kwargs `` with type level computation.
346345
@@ -563,8 +562,8 @@ Boolean operators
563562* ``IsAssignable[T, S] ``: Returns a boolean literal type indicating whether
564563 ``T `` is assignable to ``S ``.
565564
566- That is, it is a "consistent subtype". This is subtyping extended
567- to gradual types.
565+ That is, it is a "consistent subtype". This is subtyping extended
566+ to gradual types.
568567
569568* ``IsEquivalent[T, S] ``:
570569 Equivalent to ``IsAssignable[T, S] and IsAssignable[S, T] ``.
@@ -595,24 +594,19 @@ Basic operators
595594 will be packed in a tuple, and a ``... `` will become
596595 ``SpecialFormEllipsis ``.
597596
598-
599597* ``GetArgs[T, Base] ``: returns a tuple containing all of the type
600598 arguments of ``T `` when interpreted as ``Base ``, or ``Never `` if it
601599 cannot be.
602600
603-
604601* ``GetMemberType[T, S: Literal[str]] ``: Extract the type of the
605602 member named ``S `` from the class ``T ``.
606603
607-
608604* ``Length[T: tuple] `` - Gets the length of a tuple as an int literal
609605 (or ``Literal[None] `` if it is unbounded)
610606
611-
612607* ``Slice[S: tuple, Start: Literal[int | None], End: Literal[int | None]] ``:
613608 Slices a tuple type.
614609
615-
616610* ``GetSpecialAttr[T, Attr: Literal[str]] ``: Extracts the value
617611 of the special attribute named ``Attr `` from the class ``T ``. Valid
618612 attributes are ``__name__ ``, ``__module__ ``, and ``__qualname__ ``.
@@ -670,7 +664,7 @@ Methods are returned as callables using the new ``Param`` based
670664extended callables, and carrying the ``ClassVar ``
671665qualifier. ``staticmethod `` and ``classmethod `` will return
672666``staticmethod `` and ``classmethod `` types, which are subscriptable as
673- of 3.14.
667+ of Python 3.14.
674668
675669All of the operators in this section are :ref: `lifted over union types
676670<lifting>`.
@@ -694,7 +688,7 @@ InitField
694688'''''''''
695689
696690We want to be able to support transforming types based on
697- dataclasses/attrs/pydantic style field descriptors. In order to do
691+ dataclasses/attrs/Pydantic- style field descriptors. In order to do
698692that, we need to be able to consume operations like calls to ``Field ``.
699693
700694Our strategy for this is to introduce a new type
@@ -911,7 +905,7 @@ as a literal type--all of these mechanisms lean very heavily on literal types.
911905 ]:
912906 raise NotImplementedError
913907
914- ConvertField is our first type helper, and it is a conditional type
908+ `` ConvertField `` is our first type helper, and it is a conditional type
915909alias, which decides between two types based on a (limited)
916910subtype-ish check.
917911
@@ -972,9 +966,7 @@ Automatically deriving FastAPI CRUD models
972966------------------------------------------
973967
974968We have a more `fully-worked example <#fastapi-test _>`_ in our test
975- suite, but here is a possible implementation of just ``Public ``
976-
977- ::
969+ suite, but here is a possible implementation of just ``Public ``::
978970
979971 # Extract the default type from an Init field.
980972 # If it is a Field, then we try pulling out the "default" field,
@@ -1096,7 +1088,7 @@ arrays, such as::
10961088The example in that PEP shows how ``TypeVarTuple `` can be used to
10971089make sure that both sides of an arithmetic operation have matching
10981090shapes. Most multi-dimensional array libraries, however, also support
1099- broadcasting [ #broadcasting ]_ , which allows the mixing of differently
1091+ ` broadcasting < #broadcasting _>`__ , which allows the mixing of differently
11001092shaped data. With this PEP, we can define a ``Broadcast[A, B] `` type
11011093alias, and then use it as a return type::
11021094
@@ -1207,13 +1199,13 @@ which wouldn't be any simpler.)
12071199
12081200We are proposing a fully new extended callable syntax because:
12091201 1. The ``mypy_extensions `` functions are full no-ops, and we need
1210- real runtime objects
1202+ real runtime objects.
12111203 2. They use parentheses and not brackets, which really goes against
12121204 the philosophy here.
12131205 3. We can make an API that more nicely matches what we are going to
12141206 do for inspecting members (we could introduce extended callables that
12151207 closely mimic the ``mypy_extensions `` version though, if something new
1216- is a non-starter)
1208+ is a non-starter).
12171209
12181210.. _generic-callable-rationale :
12191211
@@ -1250,7 +1242,6 @@ functions with explicit generic annotations. For old-style generics,
12501242we'll probably have to try to evaluate it and then raise an error when
12511243we encounter a variable.)
12521244
1253-
12541245The reason we suggest restricting the use of ``GenericCallable `` to
12551246the type argument of ``Member `` is because impredicative
12561247polymorphism (where you can instantiate type variables with other
@@ -1259,7 +1250,6 @@ positions deep inside function types) are cans of worms when combined
12591250with type inference [#undecidable ]_. While it would be nice to support,
12601251we don't want to open that can of worms now.
12611252
1262-
12631253The unbound type variable tuple is so that bounds and defaults and
12641254``TypeVarTuple ``-ness can be specified, though maybe we want to come
12651255up with a new approach.
@@ -1329,10 +1319,10 @@ and APIs they introduce.
13291319Reference Implementation
13301320========================
13311321
1332- There is a demo of a runtime evaluator [ #runtime ]_ , which is
1322+ There is a ` demo of a runtime evaluator < #runtime _>`__ , which is
13331323also where this PEP draft currently lives.
13341324
1335- There is an in-progress proof-of-concept implementation in mypy [ #ref-impl ]_ .
1325+ There is an in-progress ` proof-of-concept implementation < #ref-impl _>`__ in mypy .
13361326
13371327It can type check the ORM, FastAPI-style model derivation, and
13381328NumPy-style broadcasting examples.
@@ -1529,7 +1519,7 @@ behavior of lifting the conditional over unions.
15291519Replace ``IsAssignable `` with something weaker than "assignable to" checking
15301520----------------------------------------------------------------------------
15311521
1532- Full python typing assignability checking is not fully implementable
1522+ Full Python typing assignability checking is not fully implementable
15331523at runtime (in particular, even if all the typeshed types for the
15341524stdlib were made available, checking against protocols will often not
15351525be possible, because class attributes may be inferred and have no visible
@@ -1636,7 +1626,7 @@ It would require a well-defined and safe-to-run subset of the language
16361626typecheckers. Subsets like this have been defined in other systems
16371627(see `Starlark <#starlark _>`_, the configuration language for Bazel),
16381628but it's still a lot of surface area, and programmers would need to
1639- keep in mind the boundaries of it .
1629+ keep in mind its boundaries.
16401630
16411631Additionally there would need to be a clear specification of how types
16421632are represented in the "mini-plugin" functions, as well as defining
@@ -1674,7 +1664,7 @@ machinery.
16741664 treated as having some type like ``tuple[Member[KeyOf[T], object,
16751665 str, ..., ...], ...] ``
16761666* ``GetMemberType[T, S: KeyOf[T]] `` - but this isn't supported yet.
1677- TS supports it.
1667+ TypeScript supports it.
16781668* We would also need to do context sensitive type bound inference
16791669
16801670
@@ -1731,12 +1721,9 @@ for all unicode!).
17311721It would definitely be possible to take just slicing and
17321722concatenation, also.
17331723
1734-
17351724* ``Slice[S: Literal[str], Start: Literal[int | None], End: Literal[int | None]] ``:
17361725 Also support slicing string types. (Currently tuples are supported.)
1737-
17381726* ``Concat[S1: Literal[str], S2: Literal[str]] ``: concatenate two strings
1739-
17401727* ``Uppercase[S: Literal[str]] ``: uppercase a string literal
17411728* ``Lowercase[S: Literal[str]] ``: lowercase a string literal
17421729* ``Capitalize[S: Literal[str]] ``: capitalize a string literal
@@ -1824,20 +1811,20 @@ substantial influence on this proposal!
18241811Footnotes
18251812=========
18261813
1814+ .. _#broadcasting : https://numpy.org/doc/stable/user/basics.broadcasting.html
18271815.. _#fastapi : https://fastapi.tiangolo.com/
18281816.. _#pydantic : https://docs.pydantic.dev/latest/
18291817.. _#fastapi-tutorial : https://fastapi.tiangolo.com/tutorial/sql-databases/#heroupdate-the-data-model-to-update-a-hero
18301818.. _#fastapi-test : https://github.com/vercel/python-typemap/blob/main/tests/test_fastapilike_2.py
18311819.. _#prisma : https://www.prisma.io/
18321820.. _#prisma-example : https://github.com/prisma/prisma-examples/tree/latest/orm/express
18331821.. _#qb-test : https://github.com/vercel/python-typemap/blob/main/tests/test_qblike_2.py
1822+ .. _#ref-impl : https://github.com/msullivan/mypy/tree/typemap
1823+ .. _#runtime : https://github.com/vercel/python-typemap
18341824.. _#starlark : https://starlark-lang.org/
1825+ .. _#survey : https://engineering.fb.com/2025/12/22/developer-tools/python-typing-survey-2025-code-quality-flexibility-typing-adoption/
18351826.. _#ast_format : https://imogenbits-peps.readthedocs.io/en/ast_format/pep-9999/
18361827
1837- .. [#broadcasting ] http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
1838- .. [#ref-impl ] https://github.com/msullivan/mypy/tree/typemap
1839- .. [#runtime ] https://github.com/vercel/python-typemap/
1840- .. [#survey ] https://engineering.fb.com/2025/12/22/developer-tools/python-typing-survey-2025-code-quality-flexibility-typing-adoption/
18411828.. [#undecidable ]
18421829
18431830 * "Partial polymorphic type inference is undecidable" by Hans Boehm: https://dl.acm.org/doi/10.1109/SFCS.1985.44
0 commit comments