mypy
mypy copied to clipboard
Support for Partial types
Feature
File t.py
:
from typing_extensions import TypedDict
class Foo(TypedDict):
x:int
y:int
foo: Partial[Foo] = {'x': 1}
# reveal_type(foo) -> TypedDict('t.Foo?', {'x'?: builtins.int, 'y'?: builtins.int})
Pitch
For some uses cases, e.g. processing PATCH requests on a web server, we usually want to allow a partial version of the original model. Currently this must be done manually, and that can be a bit error prone since one may forget to update the partial model. The Partial
type annotation would transform the original type into its optional version.
Related to: https://github.com/python/mypy/issues/4128 Note: Examples taken from https://stackoverflow.com/questions/69091758/python-typehint-subsetpartial-of-an-typeddict
"Partial types" already means something else within mypy, so it may not be the best name.
I would like to second this idea. Partial (or any other more convenient name) could also be applied to dataclasses and other record-like classes, like pydantic. Partials are very useful to express updates/patches of pre-existing types.
I think the naming needs to be discussed separately.
I find it very useful for representing existing types of updates/patches. Here are some cases.
Case.1 It can be very tedious when the number of arguments is large. When the number of arguments is small, there is no problem because it can be written as follows.
def foo_setter(arg: LibraryFoo, x: int | None = None, y = int | None = None):
...
However, when the number of arguments becomes very large, it becomes tiresome.
Case.2 The scope of the modification can be kept small and type-safe.
Then, when z is added to the library, it is resistant to change and its sphere of influence is closed to business_logic.py
.
Increases maintainability even with more arguments.
# Library code someone made this code
from typing import TypedDict
from final_class import final
@final
class LibraryFoo(TypedDict): # We cannot inherit/replace it
x: int
y: int
# -----------
# Application code
from typing import Unpack
# application_utility.py
def foo_setter(arg: LibraryFoo, **kwargs: Unpack[LibraryFoo]):
for k in kwargs:
arg[k] = kwargs[k]
# business_logic.py
vec = {'x': 0, 'y': 0}
foo_setter(vec, x=1) # Error: Argument missing for parameter "y" Pylance(reportGeneralTypeIssues)
print(vec)
foo_setter(vec, y=2) # Error: Argument missing for parameter "x" Pylance(reportGeneralTypeIssues)
print(vec)
foo_setter(vec, x=10
It would be very nice and type safe if we could write the following.
def foo_setter(arg: LibraryFoo, **kwargs: Partial[Unpack[LibraryFoo]]): ...
foo_setter(vec, x=1)
and foo_setter(vec, y=2)
will no longer be errors.
Made a thread at Python Discussions: https://discuss.python.org/t/introduce-partial-for-typeddict/45176/11 Aggregating all links in one place.