TypedDict doesn't expose its keys as a distinct type, nor is there really a good way to define such a type.

Not recommended

Some people use typing.Literal, but that is intended for, well, literals. Use key: Literal["first_name", "last_name", "age"] allows c.set_info("first_name", "bob"), but not k = "first_name"; c.set_info(k, "bob"), because k is not a literal. I don't recommend doing this, but I felt it needed to be addressed.

Better

Another alternative would be to explicitly define a separate enumerate type and use its members, rather than raw keys, as arguments.

class CustomerKey(enum.StrEnum):
    FIRST_NAME = "first_name"
    LAST_NAME = "last_name"
    AGE = "age"

# This could (somewhat awkwardly) also be defined as
#
#   CustomerKey = enum.StrEnum(dict(zip(map(str.upper, UserType.__annotation__),
#                                       UserType.__annotation__)))
#
# to avoid repetition of the exact keys.


class Customer:
    ...

    def set_info(key: CustomerKey, val: Any):     
        self._userInfo[key] = val

Better still

This is assuming you don't have a good reason to store the attributes separately, and only use the TypedDict as the argument to a class method, for example,

@dataclasses.dataclass
class Customer:
    first_name: str
    last_name: str
    age: int

    @classmethod
    def from_dict(cls, d: UserType):
        return cls(**d)

Best (hypothetical)

Don't read too much into what follows. I'm mostly thinking out loud about ways that TypeDict could expose the information it contains as type hints.

In an ideal world, the keys of a TypedDict would themselves form a type. Then perhaps you could write something like

class Customer:
    ...

    def set_info(key: UserType.keys, val: Any):
        ...

Even better, there would also be a way to tied the value assigned to key to a type that could be used to annotate val, so that if key == "first_name", then val must have type `str. I imagine this would require some mix of dependent types (where types can depend on value), singleton types (where for every value there is an associated type that contains only that value) and generics. Something vaguely like

    def set_info(key: UserType.keys, val: UserType[key])
Answer from chepner on Stack Overflow
🌐
Python
peps.python.org › pep-0589
PEP 589 – TypedDict: Type Hints for Dictionaries with a Fixed Set of Keys | peps.python.org
March 20, 2019 - It doesn’t properly support the ... constructor typing.TypedDict to support the use case where a dictionary object has a specific set of string keys, each with a value of a specific type....
🌐
Python
typing.python.org › en › latest › spec › typeddict.html
Typed dictionaries — typing documentation
TypedDict types can define any number of items, which are string keys associated with values of a specified type. For example, a TypedDict may contain the item a: str, indicating that the key a must map to a value of type str.
Discussions

Python - TypedDict type hint keys - Stack Overflow
I have 2 classes. One that inherits TypedDict class in which I have set of keys that should accept certain type of data: class UserType(TypeDict): first_name: str last_name: str age: int In More on stackoverflow.com
🌐 stackoverflow.com
Interesting use cases for a TypedDict
This is a blog from the guy who created it: https://dafoster.net/projects/typeddict/ From the description it seems like TypedDict is more about parsing and converting JSON, similar to Pydantic. Doesn’t seem like he has the same use cases as NamedTuple and Dataclass. Those objects seem to be more concerned with making it easier to define methods like str, eq, and the various operators to save you the trouble. More on reddit.com
🌐 r/Python
2
7
September 26, 2022
How do I type hint a function using TypedDict that mutates a dictionary in Python? - Stack Overflow
I am defining a function that takes a dictionary as an input, and does some operations on it that creates a new key/value pair and modifies one existing value's type. I have a TypedDict for both the More on stackoverflow.com
🌐 stackoverflow.com
TypedDict type is not giving any error despite using extra keys and using different datatype for a d
Typed dicts are just normal dicts at runtime More on reddit.com
🌐 r/Python
7
6
April 22, 2025
🌐
Mypy
mypy.readthedocs.io › en › stable › typed_dict.html
TypedDict - mypy 1.19.1 documentation
Python programs often use dictionaries with string keys to represent objects. TypedDict lets you give precise types for dictionaries that represent objects with a fixed schema, such as {'id': 1, 'items': ['x']}.
🌐
DEV Community
dev.to › ankitmalikg › what-is-typeddict-in-python-4k3d
What is "TypedDict" in Python - DEV Community
May 3, 2025 - TypedDict allows you to define the expected structure of dictionary objects — including the type of each key-value pair — while still using the familiar dictionary syntax.
🌐
Medium
medium.com › @commbigo › python-typing-typeddict-d0a82ac6688d
Python typing — TypedDict
December 28, 2023 - The Python typing package offers a variety of useful types, including int, float, str, list, and dict. For instance, consider the code snippet below. It is evident that the ‘greeting’ function only accepts a string input, excluding dictionaries or integers. def greeting(info: str) -> void: print(f"hello {info}") The subject under discussion pertains to the application of TypedDict in Python 3.8.
Top answer
1 of 2
2

TypedDict doesn't expose its keys as a distinct type, nor is there really a good way to define such a type.

Not recommended

Some people use typing.Literal, but that is intended for, well, literals. Use key: Literal["first_name", "last_name", "age"] allows c.set_info("first_name", "bob"), but not k = "first_name"; c.set_info(k, "bob"), because k is not a literal. I don't recommend doing this, but I felt it needed to be addressed.

Better

Another alternative would be to explicitly define a separate enumerate type and use its members, rather than raw keys, as arguments.

class CustomerKey(enum.StrEnum):
    FIRST_NAME = "first_name"
    LAST_NAME = "last_name"
    AGE = "age"

# This could (somewhat awkwardly) also be defined as
#
#   CustomerKey = enum.StrEnum(dict(zip(map(str.upper, UserType.__annotation__),
#                                       UserType.__annotation__)))
#
# to avoid repetition of the exact keys.


class Customer:
    ...

    def set_info(key: CustomerKey, val: Any):     
        self._userInfo[key] = val

Better still

This is assuming you don't have a good reason to store the attributes separately, and only use the TypedDict as the argument to a class method, for example,

@dataclasses.dataclass
class Customer:
    first_name: str
    last_name: str
    age: int

    @classmethod
    def from_dict(cls, d: UserType):
        return cls(**d)

Best (hypothetical)

Don't read too much into what follows. I'm mostly thinking out loud about ways that TypeDict could expose the information it contains as type hints.

In an ideal world, the keys of a TypedDict would themselves form a type. Then perhaps you could write something like

class Customer:
    ...

    def set_info(key: UserType.keys, val: Any):
        ...

Even better, there would also be a way to tied the value assigned to key to a type that could be used to annotate val, so that if key == "first_name", then val must have type `str. I imagine this would require some mix of dependent types (where types can depend on value), singleton types (where for every value there is an associated type that contains only that value) and generics. Something vaguely like

    def set_info(key: UserType.keys, val: UserType[key])
2 of 2
0

For certain use cases a certain amount of redundancy is still required to work with the type-checking systems in python... In particular, dependent types and the ability to specify types aren't handled as well as typescript, say, but that's because the types sort of "exist" in a way that forces the python typing crowd to make certain assumptions about the way types are formed.

Anyways, very close to what you might be looking for is something like:

from typing import TypedDict, Unpack


class PartialUserType(TypedDict, total=False):
    age: int
    first_name: str
    last_name: str


class Customer:
    def __init__(self):
        self._userInfo: PartialUserType= {
            "first_name": "John",
            "last_name": "John",
            "age": 27,
        }

    def set_info(self, **kwargs: Unpack[PartialUserType]):
        self._userInfo |= kwargs

Which results in editor help like so:

The main drawback to this approach is that the PartialUserType will now also consider the following valid instances:

x: PartialUserType= {}
y: PartialUserType= {'age': 0}
z: PartialUserType= {'first_name': '', 'last_name': ''}

Unfortunately inheritance does not allow us to flip that flag in a useful way, so the only way to get the behavior of both the UserTypes is to explicitly write them both. One idea is to use code generation, the basic idea shown below:

from typing import TypedDict, Unpack


class UserType(TypedDict):
    age: int
    first_name: str
    last_name: str

if __name__ == '__main__':
  with open('./partial_types_generated.py', 'w') as f:
    print("# THE CONTENT IN THIS FILE HAS BEEN GENERATED, NOT NOT MODIFY BY HAND!", file=f)
    # do whatever imports you may need
    print("from typing import TypedDict", file=f)
    print("\n# partial types\n", file=f)
    for typed_dict in [
        # Gather up all the dicts you want partials for
        UserType,
    ]:
        name = f"Partial{typed_dict.__name__}"
        annotations = {k: v.__name__ for k, v in typed_dict.__annotations__.items()}
        
        print(f"{name} = TypedDict('{name}', {annotations}, total=False)", file=f)

This script gives the file:

# THE CONTENT IN THIS FILE HAS BEEN GENERATED, NOT NOT MODIFY BY HAND!
from typing import TypedDict

# partial types

PartialUserType = TypedDict('PartialUserType', {'age': 'int', 'first_name': 'str', 'last_name': 'str'}, total=False)

Find elsewhere
🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
1 week ago - A special typing construct to mark an item of a TypedDict as read-only.
🌐
Mouse Vs Python
blog.pythonlibrary.org › home › python 201 – all about the typeddict
Python 201 - All About the TypedDict - Mouse Vs Python
June 17, 2025 - Python has supported the concept of type hinting for quite a while now. However, unlike other programming languages, Python does not enforce type hints. You must use an external tool, such as Mypy, for that. In this tutorial, you will learn all about TypedDict, a special way of adding type hinting to Heterogeneous dictionaries.
🌐
Dafoster
dafoster.net › projects › typeddict
TypedDict | Structured Dicts for Python | DaFoster
A TypedDict is a new kind of type recognized by Python typecheckers such as mypy.
🌐
Adam Johnson
adamj.eu › tech › 2021 › 05 › 10 › python-type-hints-how-to-use-typeddict
Python type hints: How to Use TypedDict - Adam Johnson
May 10, 2021 - On older versions of Python you can install it from typing-extensions. ... from typing import TypedDict class SalesSummary(TypedDict): sales: int country: str product_codes: list[str] def get_sales_summary() -> SalesSummary: """Return summary for yesterday’s sales.""" return { "sales": 1_000, "country": "UK", "product_codes": ["SUYDT"], }
🌐
YouTube
youtube.com › indently
"TypedDict" In Python Is Actually AWESOME! - YouTube
TypedDict in Python is actually awesome! In this video I will cover quickly how you can use it in your projects.▶ Become job-ready with Python:https://www.in...
Published   July 3, 2023
Views   29K
🌐
Medium
medium.com › @dipan.saha › simplifying-python-explaining-complex-concepts-for-beginners-day-1-6eb1c8166cad
Python — Understanding Advanced Concepts with Ease: Day 1 (TypedDict & Inheritance) | by Dipan Saha | Medium
January 30, 2024 - So, TypedDict is like having a dictionary with a rulebook. You define the rules (the labels and their types), and then you create your dictionary according to those rules. This helps you catch mistakes early on because Python will check that you're following the rules you set when you create or modify your TypedDict.
🌐
GitHub
github.com › python › typing › discussions › 1391
Feedback: experimental syntax for inlined TypedDict · python/typing · Discussion #1391
If we end up extending what inline TypedDicts can do (e.g. @final, total=..., inheritance etc), we don't have to worry about impact of sharing the symbol with dict collections. The goal of PEP 585 was making sure that users of untyped Python could do the intuitive thing of putting the types they already used in their annotations, instead of having a parallel set of types — not necessarily to reduce imports.
Author   python
🌐
Python
peps.python.org › pep-0655
PEP 655 – Marking individual TypedDict items as required or potentially-missing | peps.python.org
PEP 589 defines notation for declaring a TypedDict with all required keys and notation for defining a TypedDict with all potentially-missing keys, however it does not provide a mechanism to declare some keys as required and others as potentially-missing...
🌐
PyPI
pypi.org › project › typeddict
typeddict
JavaScript is disabled in your browser. Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
Python
peps.python.org › pep-0705
PEP 705 – TypedDict: Read-only items | peps.python.org
PEP 589 defines the structural type TypedDict for dictionaries with a fixed set of keys. As TypedDict is a mutable type, it is difficult to correctly annotate methods which accept read-only parameters in a way that doesn’t prevent valid inputs.
🌐
TestDriven.io
testdriven.io › tips › 08999dd1-a90f-4790-a732-e821874caf82
Tips and Tricks - Python Type Hints - typing.TypedDict | TestDriven.io
Python (>=3.8) tip: You can subclass TypedDict to create a type for dictionaries with fixed keys. Static type checking will report an error when there are extra or missing keys.
🌐
Python
peps.python.org › pep-0728
PEP 728 – TypedDict with Typed Extra Items | peps.python.org
September 12, 2023 - This PEP adds two class parameters, closed and extra_items to type the extra items on a TypedDict. This addresses the need to define closed TypedDict types or to type a subset of keys that might appear in a dict while permitting additional items of a sp...