I am trying to create a few functions which will return values of different TypedDict types. Most of fields in them will be same so I want to generate base dictionary with same function in all cases. However I am getting stumped by typing this correctly.
My idea was to create base type Parent
and inherit from it, adding only NotRequired
fields.
from typing_extensions import NotRequired, TypedDict
class Parent(TypedDict):
parent_field: str
class Child(Parent):
child_field: NotRequired[bool | None]
def create_parent() -> Parent:
return {"parent_field": "example"}
child: Child = create_parent()
# Error:
# Expression of type "Parent" cannot be assigned to declared type "Child"
# "child_field" is missing from "Type[Parent]"
However this fails since field child_field
is missing, even though its type is NotRequired
. Why it fails and how to evade this problem?
EDIT: I am using pylance (so pyright) for typechecking.
mypy
(playground) gives similar error message:
Incompatible types in assignment (expression has type "Parent", variable has type "Child") [assignment]
This question is explained in PEP589 explicitly. Let me quote:
A
TypedDict
typeA
with no keyx
is not consistent with aTypedDict
type with a non-required keyx
, since at runtime the keyx
could be present and have an incompatible type (which may not be visible throughA
due to structural subtyping). Example:
class A(TypedDict, total=False):
x: int
y: int
class B(TypedDict, total=False):
x: int
class C(TypedDict, total=False):
x: int
y: str
def f(a: A) -> None:
a['y'] = 1
def g(b: B) -> None:
f(b) # Type check error: 'B' incompatible with 'A'
c: C = {'x': 0, 'y': 'foo'}
g(c)
c['y'] + 'bar' # Runtime error: int + str
So, your Parent
class is not assignable to variable of type Child
, and pylance
points it out.