What is the idiomatic way of reusing key/values of TypedDict when total=False and True is needed? #2151
-
|
Hi! I construct a dictionary in several steps, and during that time I only want to guarantee that it doesn't have invalid key names or value types (total=False)). Once the dictionary is constructed, I want to guarantee that it contains all the keys with the valid value types (total=True). What is the idiomatic way to reuse the same key name/value type definition? Should I use the functional syntax and make two calls with the same dictionary specifying keys and values? If I understand correctly, inheritance is not an option. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
You are correct, inheritance is not a supported way just like there is no switch from not required -> required. We lack a way to define a TypedDict partially. Currently you have to define your TypedDict twice, once for each totality.
Neither mypy not pyright allow dict variables and expect a literal dict for the functional syntax. TL;DR: There is currently no supported way to reuse the key: value definitions and change between total <-> not total. You have two literally define both cases. For completion, there is a possibility of a generic Code sample in pyright playground from typing import TypedDict, Never, TypeAlias
from typing_extensions import Sentinel
MISSING = Sentinel("MISSING")
# Aliases for clarity
AllKeysPresent: TypeAlias = Never
MaybeMissingValues: TypeAlias = MISSING
# Never as constraint can be omitted, likewise total=True
class LockeableDict[T: (MaybeMissingValues, AllKeysPresent)](TypedDict, total=True):
# Define all keys with T
foo: int | T
PartialDict = LockeableDict[MaybeMissingValues]
FinalDict = LockeableDict[AllKeysPresent]
A: PartialDict = {"foo": MISSING} # all keys required
# make sure no missing keys
# ...
B: FinalDict = A # <-- need to cast
reveal_type(A["foo"]) # int | MISSING
reveal_type(B["foo"]) # int
A["bar"] = 2 # error |
Beta Was this translation helpful? Give feedback.
You are correct, inheritance is not a supported way just like there is no switch from not required -> required. We lack a way to define a TypedDict partially.
Currently you have to define your TypedDict twice, once for each totality.
Functional vs. class definition does not make much of a difference. From you question I assume that you want to reuse a dict variable, e.g.
Def = {"foo": int}andTypedDict("DefTotal", Def, total=True), while this would allow you to easily keep both dict types in sync it is not required for type-checkers to accept it (per PEP 589):Neither mypy not pyright allow dict variables and e…