Typed dictionaries

(Originally specified inPEP 589, with later additions:RequiredandNotRequired inPEP 655, use withUnpack inPEP 692,ReadOnly inPEP 705, andclosed=True andextra_items= inPEP 728.)

A TypedDict type representsdict objects that contain only keys oftypestr. There are restrictions on which string keys are valid, andwhich values can be associated with each key. Values thatinhabit aTypedDict type must be instances ofdict itself, not a subclass.

TypedDict types can define any number ofitems, which are stringkeys associated with values of a specified type. For example,a TypedDict may contain the itema:str, indicating that the keyamust map to a value of typestr. Items may be eitherrequired,meaning they must be present in every instance of the TypedDict type, ornon-required, meaning they may be omitted, but if they are present,they must be of the type specified in the TypedDict definition. By default,all items in a TypedDict are mutable, but itemsmay also be marked asread-only, indicating that they may not bemodified.

In addition to explicitly specified items, TypedDicts may allow additionalitems. By default, TypedDicts areopen, meaning they may contain anunknown set of additional items. They may also be marked asclosed,in which case they may not contain any keys beyond those explicitly specified.As a third option, they may be defined withextra items of a specific type.In this case, there may be any number of additional items present at runtime, buttheir values must be of the specified type. Extra items may or may not beread-only. Thus, a TypedDict may be open, closed, or have extra items;we refer to this property as theopenness of the TypedDict. For many purposes,an open TypedDict is equivalent to a TypedDict with read-only extra items oftypeobject, but certain behaviors differ; for example, theTypedDict constructor of open TypedDicts does notallow unrecognized keys.

A TypedDict is astructural type: independent TypedDict types may beassignable to each other based on their structure, even if they do notshare a common base class. For example, two TypedDict types that contain the sameitems areequivalent. Nevertheless, TypedDict types may inherit from otherTypedDict types to share common items. TypedDict types may also be generic.

Syntax

This section outlines the syntax for creating TypedDict types. There are twosyntaxes: the class-based syntax and the functional syntax.

Class-based Syntax

A TypedDict type can be defined using the class definition syntax withtyping.TypedDict as a direct or indirect base class:

fromtypingimportTypedDictclassMovie(TypedDict):name:stryear:int

Movie is a TypedDict type with two items:'name' (with typestr) and'year' (with typeint).

A TypedDict can also be created through inheritance from one or moreother TypedDict types:

classBookBasedMovie(Movie):based_on:str

This creates a TypedDict typeBookBasedMovie with three items:'name' (typestr),'year' (typeint), and'based_on' (typestr).SeeInheritance for more details.

A generic TypedDict can be created by inheriting fromGeneric with a listof type parameters:

fromtypingimportGeneric,TypeVarT=TypeVar('T')classResponse(TypedDict,Generic[T]):status:intpayload:T

Or, in Python 3.12 and newer, by using the native syntax for generic classes:

fromtypingimportTypedDictclassResponse[T](TypedDict):status:intpayload:T

It is invalid to specify a base class other thanTypedDict,Generic,or another TypedDict type in a class-based TypedDict definition.It is also invalid to specify a custom metaclass.

A TypedDict definition may also contain the following keyword argumentsin the class definition:

  • total: a boolean literal (True orFalse) indicating whetherall items arerequired (True, the default) ornon-required(False). This affects only items defined in this class, not in anybase classes, and it does not affect any items that use an explicitRequired[] orNotRequired[] qualifier. The value must be exactlyTrue orFalse; other expressions are not allowed.

  • closed: a boolean literal (True orFalse) indicating whetherthe TypedDict isclosed (True) oropen (False).The latter is the default, except when inheriting from another TypedDict thatis not open (seeInheritance), or when theextra_itemsargument is also used.As withtotal, the value must be exactlyTrue orFalse. It is an errorto use this argument together withextra_items=.

  • extra_items: indicates that the TypedDict hasextra items. The argumentmust be aannotation expression specifying the type of the extra items.Thetype qualifierReadOnly[] may be used to indicate that the extra items areread-only. Other type qualifiers are not allowed. If the extra items typeisNever, no extra items are allowed, so this is equivalent toclosed=True.

The body of the class definition defines theitems of the TypedDict type.It may also contain a docstring orpass statements (primarily to allow the creation ofan empty TypedDict). No other statements are allowed, and type checkers should report anerror if any are present. Type comments are not supported for creating TypedDict items.

An item definition takes the form of an attribute annotation,key:T.key isan identifier and corresponds to the string key of the item, andT is anannotation expression specifying the type of the item value. This annotationexpression contains atype expression, optionally qualified with one of thetype qualifiersRequired,NotRequired, orReadOnly.These type qualifiers may be nested arbitrarily or wrapped inAnnotated[]. It isan error to use bothRequired andNotRequired in the same item definition.An item isread-only if and only if theReadOnly qualifier is used.

To determine whether an item isrequired ornon-required, the followingprocedure is used:

  • If theRequired qualifier is present, the item is required.

  • If theNotRequired qualifier is present, the item is non-required.

  • If thetotal argument of the TypedDict definition isFalse, the item is non-required.

  • Else, the item is required.

It is valid to useRequired[] andNotRequired[] even foritems where it is redundant, to enable additional explicitness if desired.Note that the value oftotal only affects items defined in the current class body,not in any base classes. Thus, inheritance can be used to create a TypedDict that mixesrequired and non-required items without usingRequired[] orNotRequired[].

The following example demonstrates some of these rules:

fromtypingimportTypedDict,NotRequired,Required,ReadOnly,AnnotatedclassMovie(TypedDict):name:str# required, not read-onlyyear:int# required, not read-onlydirector:NotRequired[str]# non-required, not read-onlyrating:NotRequired[ReadOnly[float]]# non-required, read-onlyinvalid:Required[NotRequired[int]]# type checker error: both Required and NotRequired usedclassPartialMovie(TypedDict,total=False):name:str# non-required, not read-onlyyear:Required[int]# required, not read-onlyscore:ReadOnly[float]# non-required, read-only

Functional syntax

In addition to the class-based syntax, TypedDict types can be createdusing an alternative functional syntax. This syntax allows definingitems with keys that are not valid Python identifiers, and it is compatiblewith older Python versions such as 3.5 and 2.7 that don’t support thevariable definition syntax introduced inPEP 526. On the other hand, this syntaxdoes not support inheritance.

The functional syntax resembles the traditional syntax for defining named tuples:

fromtypingimportTypedDictMovie=TypedDict('Movie',{'name':str,'year':int})

The syntax comprises a call toTypedDict(), the result of which must be immediatelyassigned to a variable with the same name as the first argument toTypedDict().

The call toTypedDict() must have two positional arguments. The first is a stringliteral specifying the name of the TypedDict type. The second is a dictionary specifyingtheitems of the TypedDict. It must be a dictionary display expression,not a variable or other expression that evaluates to a dictionary at runtime.The keys of the dictionary must be string literals and the values must beannotation expressions following the same rules asthe class-based syntax (i.e., the qualifiersRequired,NotRequired, andReadOnly are allowed). In addition to the two positional arguments,total,closed, andextra_items keyword arguments are also supported, with the samesemantics as in the class-based syntax.

Using TypedDict Types

Here is an example of how the typeMovie can be used:

movie:Movie={'name':'Blade Runner','year':1982}

An explicitMovie type annotation is generally needed, asotherwise an ordinary dictionary type could be assumed by a typechecker, for backwards compatibility. When a type checker can inferthat a constructed dictionary object should be a TypedDict, anexplicit annotation can be omitted. A typical example is a dictionaryobject as a function argument. In this example, a type checker isexpected to infer that the dictionary argument should be understood asa TypedDict:

defrecord_movie(movie:Movie)->None:...record_movie({'name':'Blade Runner','year':1982})

Another example where a type checker should treat a dictionary displayas a TypedDict is in an assignment to a variable with a previouslydeclared TypedDict type:

movie:Movie...movie={'name':'Blade Runner','year':1982}

Operations onmovie can be checked by a static type checker:

movie['director']='Ridley Scott'# Error: invalid key 'director'movie['year']='1982'# Error: invalid value type ("int" expected)

The code below should be rejected, since'title' is not a validkey, and the'name' key is missing:

movie2:Movie={'title':'Blade Runner','year':1982}

The created TypedDict type object is not a real class object. Hereare the only uses of the type a type checker is expected to allow:

  • It can be used intype expressions torepresent the TypedDict type.

  • It can be used as a callable object with keyword argumentscorresponding to the TypedDict items; seeThe TypedDict constructor.

  • It can be used as a base class, but only when defining a derivedTypedDict (seeabove).

In particular, TypedDict type objects cannot be used inisinstance() tests such asisinstance(d,Movie). This isconsistent with howisinstance() is not supported forother type forms such aslist[str].

The TypedDict constructor

TypedDict types are callable at runtime and can be used as a constructorto create values that conform to the TypedDict type. The constructortakes only keyword arguments, corresponding to the items of the TypedDict.Example:

m=Movie(name='Blade Runner',year=1982)

When called, the TypedDict type object returns an ordinarydictionary object at runtime:

print(type(m))# <class 'dict'>

Everyrequired item must be provided as a keyword argument.Non-requireditems may be omitted. Whether an item is read-only has no effect on theconstructor.

Closed and open TypedDicts allow no additional items beyond those explicitlydefined, but TypedDicts with extra items allow arbitrary keyword arguments,which must be of the specified type. Example:

fromtypingimportTypedDict,ReadOnlyclassMovieWithExtras(TypedDict,extra_items=ReadOnly[int|str]):name:stryear:intm1=MovieWithExtras(name='Blade Runner',year=1982)# OKm2=MovieWithExtras(name='The Godfather',year=1972,director='Francis Ford Coppola',rating=9)# OKm3=MovieWithExtras(name='Inception',year=2010,budget=160.0)# Type check error: budget must be int or str

Initialization from dictionary literals

Type checkers should also allow initializing a value of TypedDict type froma dictionary literal:

m:Movie={'name':'Blade Runner','year':1982}# OK

Or from a call todict() with keyword arguments:

m:Movie=dict(name='Blade Runner',year=1982)# OK

In these cases, extra keys should not be allowed unless the TypedDictis defined to allowextra items. In this example, thedirector key is not defined inMovie and is expected to generate an error from a type checker:

m:Movie=dict(name='Alien',year=1979,director='Ridley Scott')# error: Unexpected key 'director'

If a TypedDict has extra items, extra keys are allowed, provided their valuematches the extra items type:

classExtraMovie(TypedDict,extra_items=bool):name:stra:ExtraMovie={"name":"Blade Runner","novel_adaptation":True}# OKb:ExtraMovie={"name":"Blade Runner","year":1982,# Not OK. 'int' is not assignable to 'bool'}

Here,extra_items=bool specifies that items other than'name'have a value type ofbool and are non-required.

Inheritance

As discussed underClass-based Syntax, TypedDict typescan inherit from one or more other TypedDict types. In this case theTypedDict base class should not be included. Example:

classBookBasedMovie(Movie):based_on:str

NowBookBasedMovie has keysname,year, andbased_on. It isequivalent to this definition, since TypedDict types arestructural types:

classBookBasedMovie(TypedDict):name:stryear:intbased_on:str

Overriding items

Under limited circumstances, subclasses may redeclare items defined in a superclass witha different type or different qualifiers. Redeclaring an item with the same type and qualifiersis always allowed, although it is redundant.

If an item is mutable in a superclass, it must remain mutable in the subclass. Similarly,mutable items that arerequired in a superclass must remain required in the subclass,and mutablenon-required items in the superclass must remain non-required in the subclass.However, if the superclass item isread-only, a superclass item that is non-requiredmay be overridden with a required item in the subclass. A read-only item in a superclassmay be redeclared as mutable (that is, without theReadOnly qualifier) in a subclass.These rules are necessary for type safety.

If an item is read-only in the superclass, the subclass may redeclare it with a different typethat isassignable to the superclass type. Otherwise, changing the type of an item is not allowed.Example:

classX(TypedDict):x:stry:ReadOnly[int]z:intclassY(X):x:int# Type check error: cannot overwrite TypedDict field "x"y:bool# OK: bool is assignable to int, and a mutable item can override a read-only onez:bool# Type check error: key is mutable, so subclass type must be consistent with superclass

Openness

The openness of a TypedDict (whether it isopen,closed, or hasextra items)is inherited from its superclass by default:

classClosedBase(TypedDict,closed=True):name:strclassClosedChild(ClosedBase):# also closedpassclassExtraItemsBase(TypedDict,extra_items=int|None):name:strclassExtraItemsChild(ExtraItemsBase):# also has extra_items=int | Nonepass

However, subclasses may also explicitly use theclosed andextra_items argumentsto change the openness of the TypedDict, but in some cases this yields a type checker error:

  • If the base class is open, all possible states are allowed in the subclass: it may remain open,it may be closed (withclosed=True), or it may have extra items (withextra_items=...).

  • If the base class is closed, any child classes must also be closed.

  • If the base class has extra items, but they are not read-only, the child class must also allowthe same extra items.

  • If the base class has read-only extra items, the child class may be closed,or it may redeclare its extra items with a type that isassignable to the base class type.Child classes may also have mutable extra items if the base class has read-only extra items.

For example:

classExtraItemsRO(TypedDict,extra_items=ReadOnly[int|str]):name:strclassClosedChild(ExtraItemsRO,closed=True):# OKpass# OK, str is assignable to int | str, and mutable extra items can override read-only onesclassNarrowerChild(ExtraItemsRO,extra_items=str):pass

When a TypedDict has extra items, this effectively defines the value type of any unnameditems accepted to the TypedDict and marks them as non-required. Thus, there are somerestrictions on the items that can be added in subclasses. For each itemadded in a subclass of a class with extra items of typeT, the following rules must be followed:

  • Ifextra_items is read-only

    • The item can be either required or non-required

    • The item’s value type must beassignable toT

  • Ifextra_items is not read-only

    • The item must be non-required

    • The item’s value type must beconsistent withT

For example:

classMovieBase(TypedDict,extra_items=int|None):name:strclassMovieRequiredYear(MovieBase):# Not OK. Required key 'year' is not known to 'MovieBase'year:int|NoneclassMovieNotRequiredYear(MovieBase):# Not OK. 'int | None' is not consistent with 'int'year:NotRequired[int]classMovieWithYear(MovieBase):# OKyear:NotRequired[int|None]classBookBase(TypedDict,extra_items=ReadOnly[int|str]):title:strclassBook(BookBase,extra_items=str):# OKyear:int# OK, since extra_items is read-only

Multiple inheritance

TypedDict types may use multiple inheritance to inherit items from multiplebase classes. Here is an example:

classX(TypedDict):x:intclassY(TypedDict):y:strclassXYZ(X,Y):z:bool

The TypedDictXYZ has three items:x (typeint),y(typestr), andz (typebool).

Multiple inheritance does not allow conflicting types for the same item:

classX(TypedDict):x:intclassY(TypedDict):x:strclassXYZ(X,Y):# Type check error: cannot overwrite TypedDict field "x" while mergingxyz:bool

Subtyping and assignability

Because TypedDict types arestructural types, a TypedDictT1 isassignable to anotherTypedDict typeT2 if the two are structurally compatible, meaning that all operations thatare allowed onT2 are also allowed onT1. For similar reasons, TypedDict types aregenerally not assignable to any specialization ofdict orMapping, other thanMapping[str,object],though certainclosed TypedDicts and TypedDicts withextra items may be assignableto these types.

The rest of this section discusses thesubtyping rules for TypedDict in more detail.As with any type, the rules forassignability can be derived from the subtypingrules using thematerialization procedure. Generally, this means that where“equivalent” is mentioned below, theconsistency relation can be used insteadwhen implementing assignability, and where “subtyping” between elements of aTypedDict is mentioned, assignability can be used instead when implementing assignability between TypedDicts.

Subtyping between TypedDict types

A TypedDict typeB is asubtype of a TypedDict typeA ifand only if all of the conditions below are satisfied. For the purposes of these conditions,anopen TypedDict is treated as if it had read-onlyextra items of typeobject.

The conditions are as follows:

  • For each item inA:

    • If it is required inA:

      • It must also be required inB.

      • If it is read-only inA, the item type inB must be a subtype of the item type inA.(Forassignability between two TypedDicts, the first item must insteadbe assignable to the second.)

      • If it is mutable inA, it must also be mutable inB, and the item type inB must beequivalent to the item type inA. (It follows that for assignability, the two item typesmust beconsistent.)

    • If it is non-required inA:

      • If it is read-only inA:

        • IfB has an item with the same key, its item type must be a subtype of the item type inA.

        • Else:

          • IfB is closed, the check succeeds.

          • IfB has extra items, the extra items type must be a subtype of the item type inA.

      • If it is mutable inA:

        • IfB has an item with the same key, it must also be mutable and non-required, and its item type must beequivalent to the item type inA.

        • Else:

          • IfB is closed, the check fails.

          • IfB has extra items, the extra items type must not be read-only and mustbeequivalent to the item type inA.

  • IfA is closed,B must also be closed, and it must not contain any items that are not present inA.

  • IfA has read-only extra items,B must either be closed or also have extra items, and the extra items type inBmust be a subtype of the extra items type inA. Additionally, for any items inB that are not present inA,the item type must be a subtype of the extra items type inA.

  • IfA has mutable extra items,B must also have mutable extra items, and the extra items type inBmust beequivalent to the extra items type inA. Additionally, for any items inB that are not present inA,the item type must beequivalent to the extra items type inA.

The intuition behind these rules is that any operation that is valid onA must also be valid and safe onB.For example, any key access onA that is guaranteed to succeed (because the item is required) must also succeed onB,and any mutating operation (such as setting or deleting a key) that is allowed onA must also be allowed onB.

An example where mutability is relevant:

classA(TypedDict):x:int|NoneclassB(TypedDict):x:intdeff(a:A)->None:a['x']=Noneb:B={'x':0}f(b)# Type check error: 'B' not assignable to 'A'b['x']+1# Runtime error: None + 1

Subtyping withMapping

A TypedDict type is asubtype of a type of the formMapping[str,VT]when all value types of the items in the TypedDictare subtypes ofVT. For the purpose of this rule, anopen TypedDict is consideredto have read-onlyextra items of typeobject.

For example:

classMovieExtraStr(TypedDict,extra_items=str):name:strextra_str:MovieExtraStr={"name":"Blade Runner","summary":""}str_mapping:Mapping[str,str]=extra_str# OKclassMovieExtraInt(TypedDict,extra_items=int):name:strextra_int:MovieExtraInt={"name":"Blade Runner","year":1982}int_mapping:Mapping[str,int]=extra_int# Not OK. 'int | str' is not assignable with 'int'int_str_mapping:Mapping[str,int|str]=extra_int# OK

As a consequence, every TypedDict type isassignable toMapping[str,object].

Subtyping withdict

Generally, TypedDict types are not subtypes of any specialization ofdict[...] type, sincedictionary types allow destructive operations, includingclear(). Theyalso allow arbitrary keys to be set, which would compromise type safety.

However, a TypedDict withextra items may be a subtype ofdict[str,VT],provided certain conditions are met, because it introduces sufficient restrictionsfor this subtyping relation to be safe.A TypedDict type is a subtype ofdict[str,VT] if the following conditions are met:

  • The TypedDict type has mutableextra items of a type that isequivalent toVT.

  • All items on the TypedDict satisfy the following conditions:

    • The value type of the item isequivalent toVT.

    • The item is not read-only.

    • The item is not required.

For example:

classIntDict(TypedDict,extra_items=int):passclassIntDictWithNum(IntDict):num:NotRequired[int]deff(x:IntDict)->None:v:dict[str,int]=x# OKv.clear()# OKnot_required_num_dict:IntDictWithNum={"num":1,"bar":2}regular_dict:dict[str,int]=not_required_num_dict# OKf(not_required_num_dict)# OK

In this case, some methods that are otherwise unavailable on a TypedDict are allowed,with signatures matchingdict[str,VT](e.g.:__setitem__(self,key:str,value:VT)->None):

not_required_num_dict.clear()# OKreveal_type(not_required_num_dict.popitem())# OK. Revealed type is 'tuple[str, int]'deff(not_required_num_dict:IntDictWithNum,key:str):not_required_num_dict[key]=42# OKdelnot_required_num_dict[key]# OK

On the other hand,dict[str,VT] is not assignable to any TypedDict type,because such a type includes instances of subclasses ofdict:

classCustomDict(dict[str,int]):passdeff(might_not_be_a_builtin_dict:dict[str,int]):int_dict:IntDict=might_not_be_a_builtin_dict# Not OKnot_a_builtin_dict=CustomDict({"num":1})f(not_a_builtin_dict)

Supported and Unsupported Operations

Type checkers should support restricted forms of mostdictoperations on TypedDict objects. The guiding principle is thatoperations not involvingAny types should be rejected by typecheckers if they may violate runtime type safety. Here are some ofthe most important type safety violations to prevent:

  1. A required key is missing.

  2. A value has an invalid type.

  3. A key that is not defined in the TypedDict type is added.

  4. Read-only items are modified or deleted.

Items that areread-only may not be mutated (added, modified, or removed):

fromtypingimportReadOnlyclassBand(TypedDict):name:strmembers:ReadOnly[list[str]]blur:Band={"name":"blur","members":[]}blur["name"]="Blur"# OK: "name" is not read-onlyblur["members"]=["Damon Albarn"]# Type check error: "members" is read-onlyblur["members"].append("Damon Albarn")# OK: list is mutable

The exact type checking rules are up to each type checker to decide.In some cases potentially unsafe operations may be accepted if thealternative is to generate false positive errors for idiomatic code.Sometimes, operations onclosed TypedDicts or TypedDicts withextra items are safe even if they would be unsafe onopen TypedDicts, so type checker behavior may depend on theopenness of the TypedDict.

Allowed keys

Many operations on TypedDict objects involve specifying a dictionary key.Examples include accessing an item withd['key'] or setting an item withd['key']=value.

A key that is not a literal should generally be rejected, since itsvalue is unknown during type checking, and thus can cause some of theabove violations. This involves both destructive operations such as settingan item and read-only operations such as subscription expressions.

The use of a key that is not known to exist should be reported as an error,even if this wouldn’t necessarily generate a runtime type error. These areoften mistakes, and these may insert values with an invalid type ifstructuralassignability hides the types ofcertain items. For example,d['x']=1 should generate a type check errorif'x' is not a valid key ford (which is assumed to be a TypedDicttype), unlessd has mutableextra items of a compatible type.

Type checkers should allowfinal names withstring values to be used instead of string literals in operations onTypedDict objects. For example, this is valid:

YEAR:Final='year'm:Movie={'name':'Alien','year':1979}years_since_epoch=m[YEAR]-1970

Similarly, an expression with a suitableliteral typecan be used instead of a literal value:

defget_value(movie:Movie,key:Literal['year','name'])->int|str:returnmovie[key]

Specific operations

This section discusses some specific operations in more detail.

  • As an exception to the general rule around non-literal keys,d.get(e) andeindshould be allowed for TypedDict objects, for an arbitrary expressione with typestr. The motivation is that these are safe andcan be useful for introspecting TypedDict objects. The static typeofd.get(e) should be the union of all possible item types indif the string value ofe cannot be determined statically.(This simplifies toobject ifd isopen.)

  • clear() is not safe onopen TypedDicts since it could remove required items, some of whichmay not be directly visible because ofstructuralassignability. However, this method is safe onclosed TypedDicts and TypedDicts withextra items ifthere are no required or read-only items and there cannot be any subclasses with requiredor read-only items.

  • popitem() is similarly unsafe on many TypedDicts, evenif all known items arenon-required.

  • delobj['key'] should be rejected unless'key' is anon-required, mutable key.

  • Type checkers may allow reading an item usingd['x'] even ifthe key'x' is not required, instead of requiring the use ofd.get('x') or an explicit'x'ind check. The rationale isthat tracking the existence of keys is difficult to implement in fullgenerality, and that disallowing this could require many changes toexisting code.Similarly, type checkers may allow indexed accesseswith arbitrary str keys when a TypedDict isclosed or hasextra items.For example:

    defbar(movie:MovieExtraInt,key:str)->None:reveal_type(movie[key])# Revealed type is 'str | int'
  • The return types of theitems() andvalues() methods can be determinedfrom the union of all item types in the TypedDict (which would includeobjectforopen TypedDicts). Therefore, type checkers should infer more precisetypes for TypedDicts that are not open:

    fromtypingimportTypedDictclassMovieExtraInt(TypedDict,extra_items=int):name:strdeffoo(movie:MovieExtraInt)->None:reveal_type(movie.items())# Revealed type is 'dict_items[str, str | int]'reveal_type(movie.values())# Revealed type is 'dict_values[str, str | int]'
  • Theupdate() method should not allow mutating a read-only item.Therefore, type checkers should error if aTypedDict with a read-only item is updated with another TypedDict that declaresthat item:

    classA(TypedDict):x:ReadOnly[int]y:inta1:A={"x":1,"y":2}a2:A={"x":3,"y":4}a1.update(a2)# Type check error: "x" is read-only in A

    Unless the declared value is of bottom type (Never):

    classB(TypedDict):x:NotRequired[typing.Never]y:ReadOnly[int]defupdate_a(a:A,b:B)->None:a.update(b)# Accepted by type checker: "x" cannot be set on b

    Note: Nothing will ever match theNever type, so an item annotated with it must be absent.

Backwards Compatibility

To retain backwards compatibility, type checkers should not infer aTypedDict type unless it is sufficiently clear that this is desired bythe programmer. When unsure, an ordinary dictionary type should beinferred. Otherwise existing code that type checks without errors maystart generating errors once TypedDict support is added to the typechecker, since TypedDict types are more restrictive than dictionarytypes. In particular, they aren’t subtypes of dictionary types.