'How to access the type of an attribute in a TypedDict?

Given a TypedDict, how can you access/use the type of one of its attributes?

For example:

class Shape(TypedDict):
  kind: Literal['square', 'circle']
  x: int
  y: int

KindOfShape: TypeAlias = Shape.kind # does not work - how do I do this?

kind_1: KindOfShape = 'circle'
kind_2: KindOfShape = 'spongebob' # I want this to error

Is this possible?



Solution 1:[1]

Is this possible?

No. There are 2 syntactic errors that can be summed up in 1 single sentence of PEP 589:

PEP 589 – TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys

[Class-based Syntax]

  1. Methods are not allowed, since
  2. the runtime type of a TypedDict object will always be just dict (it is never a subclass of dict).
  1. The first syntax impossibility in the example is:

     Shape.kind # does not work - how do I do this?
    

    You don't. That's using attribute access X.Y, but PEP 589 is clear that the TypedDict is a dictionary, so you'll have to use key-value dictionary access using Shape['kind'] syntax

  2. The TypedDict type hint is strict in its syntax and doesn't allow adding any methods on the declaration (or metaclass) so there's no Data Model hack that would allow using dotted attribute access syntax.

    So the right way to do this would be as follows:

    from typing import TypedDict, Literal, TypeAlias
    
    
    KindOfShape: TypeAlias = Literal['square', 'circle']
    
    
    class Shape(TypedDict):
        kind: KindOfShape
        x: int
        y: int
    
    
    kind_1: KindOfShape = 'circle'
    kind_2: KindOfShape = 'spongebob' # I want this to error
    

    Mypy gives the exact error you want:

    your module.py:14: error: Incompatible types in assignment (expression has type "Literal['spongebob']", variable has type "Union[Literal['square'], Literal['circle']]")
    Found 1 error in 1 file (checked 1 source file)
    

An argument can be made:

In my case, there are a large number of attributes; giving each their own named type would make the code less readable.

Not necessarily, you can (and often should) throw all the type hints into a stub file. It's meant to separate the static part from the run-time part. Granted, you have the extra work of writing the type hints but the whole point of using TypeAlias is code reuse, so you'll get the extra work back from writing separate definitions.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 bad_coder