Since Python 3.11, as per PEP 655, what you need is NotRequired:

class _trending(TypedDict):
    allStores: NotRequired[bool]
    category: str
    date: str
    average: List[int]

notice that you shouldn't use Optional in TypedDict, and only use (Not)Required

if you want to use TypedDict with Pydantic, you could refer this article

Answer from S_SmJaE on Stack Overflow
🌐
Python
peps.python.org › pep-0655
PEP 655 – Marking individual TypedDict items as required or potentially-missing | peps.python.org
This PEP introduces two new notations: Required[], which can be used on individual items of a TypedDict to mark them as required, and NotRequired[], which can be used on individual items to mark them as potentially-missing.
🌐
Python
typing.python.org › en › latest › spec › typeddict.html
Typed dictionaries — typing documentation
If the NotRequired qualifier is present, the item is non-required. If the total argument of the TypedDict definition is False, the item is non-required.
🌐
Python.org
discuss.python.org › peps
PEP 655: Required[] and NotRequired[] for TypedDict - PEPs - Discussions on Python.org
February 20, 2022 - This PEP enhances TypedDict - an existing kind of type annotation for describing dictionaries with a known set of named keys - with the ability to directly mark individual keys as Required[] or as NotRequired[], rather than requiring the indirect use of inheritance plus a total=False attribute to achieve the same result.
Top answer
1 of 2
117

Since Python 3.11, as per PEP 655, what you need is NotRequired:

class _trending(TypedDict):
    allStores: NotRequired[bool]
    category: str
    date: str
    average: List[int]

notice that you shouldn't use Optional in TypedDict, and only use (Not)Required

if you want to use TypedDict with Pydantic, you could refer this article

2 of 2
18

I used this question as duplicate target, but noticed that another option is missing here.

If you don't like NotRequired (for example, if you have many required and many optional keys and don't want to repeat NotRequired many times) or don't want to bother with typing_extensions (rare case), you can tweak totality.

The following definitions of Main* are equivalent:

import sys
# You may also pick one without version check, of course
if sys.version_info < (3, 11):
    from typing_extensions import TypedDict, Required, NotRequired
else:
    from typing import TypedDict, Required, NotRequired


class Main1(TypedDict):
    foo: int
    bar: str
    baz: NotRequired[int]
    qux: NotRequired[str]


class Main2(TypedDict, total=False):
    foo: Required[int]
    bar: Required[str]
    baz: int
    qux: str


class _Main3(TypedDict):
    foo: int
    bar: str

class Main3(_Main3, total=False):
    baz: int
    qux: str


class _Main4(TypedDict, total=False):
    baz: int
    qux: str
    
class Main4(_Main4):
    foo: int
    bar: str

Here's PEP explanation of totality:

The totality flag only applies to items defined in the body of the TypedDict definition. Inherited items won’t be affected, and instead use totality of the TypedDict type where they were defined. This makes it possible to have a combination of required and non-required keys in a single TypedDict type.

Here's example of checking with definitions above:

Main1(foo=1, bar='bar', baz=2, qux='qux')
Main1(foo=1, bar='bar', baz=2)
Main1(foo=1, bar='bar')
Main1(foo=1, baz=2, qux='qux')  # E: Missing key "bar" for TypedDict "Main1"  [typeddict-item]
Main1(foo=1, bar='bar', who=None)  # E: Extra key "who" for TypedDict "Main1"  [typeddict-item]

Main2(foo=1, bar='bar', baz=2, qux='qux')
Main2(foo=1, bar='bar', baz=2)
Main2(foo=1, bar='bar')
Main2(foo=1, baz=2, qux='qux')  # E: Missing key "bar" for TypedDict "Main2"  [typeddict-item]
Main2(foo=1, bar='bar', who=None)  # E: Extra key "who" for TypedDict "Main2"  [typeddict-item]

Main3(foo=1, bar='bar', baz=2, qux='qux')
Main3(foo=1, bar='bar', baz=2)
Main3(foo=1, bar='bar')
Main3(foo=1, baz=2, qux='qux')  # E: Missing key "bar" for TypedDict "Main3"  [typeddict-item]
Main3(foo=1, bar='bar', who=None)  # E: Extra key "who" for TypedDict "Main3"  [typeddict-item]

Main4(foo=1, bar='bar', baz=2, qux='qux')
Main4(foo=1, bar='bar', baz=2)
Main4(foo=1, bar='bar')
Main4(foo=1, baz=2, qux='qux')  # E: Missing key "bar" for TypedDict "Main4"  [typeddict-item]
Main4(foo=1, bar='bar', who=None)  # E: Extra key "who" for TypedDict "Main4"  [typeddict-item]

You can fiddle with this in playground

🌐
Mypy
mypy.readthedocs.io › en › stable › typed_dict.html
TypedDict - mypy 1.19.1 documentation
A TypedDict with a mix of required and non-required keys, such as Movie above, will only be compatible with another TypedDict if all required keys in the other TypedDict are required keys in the first TypedDict, and all non-required keys of the other TypedDict are also non-required keys in the first TypedDict. You can use typing.ReadOnly, introduced in Python 3.13, or typing_extensions.ReadOnly to mark TypedDict items as read-only (PEP 705):
🌐
GitHub
github.com › python › typing › issues › 1454
Allow use of `Required` and `NotRequired` to make an existing typed dict total or optional · Issue #1454 · python/typing
August 28, 2023 - topic: featureDiscussions about new features for Python's type annotationsDiscussions about new features for Python's type annotations ... I think the ability of indicating that a typed dict requires all keys or that all are optional would be very useful. For example to allow defining default values for a particular dict or to return a dict that has been completely assigned from a function ... class A(TypedDict): a: int b: int ADefault = {'a': 1, 'b': 42} def optionalA(v: NotRequired[A]) -> A: return ADefault | v optionalA({'a': 11}) # ok since all keys of NotRequired[A] are optional class X(TypedDict, total=False): x: str y: str XDefault: X = {"x": "xv", "y": "yv"} def withXDefault(v: X) -> Required[X]: return XDefault | v withXDefault({"x": "foo"})["y"] # ok since all keys of Required[X] are required
Published   Aug 28, 2023
🌐
GitHub
github.com › python › typing › discussions › 1516
Required/NotRequired and inheritance · python/typing · Discussion #1516
In my previous post, I forgot about TypedDict definitions that extend multiple other TypedDict definitions. If we go with option 2 or 3, it should also apply to the multiple inheritance case. from typing import NotRequired, Required, TypedDict class A1(TypedDict): a: NotRequired[str] class A2(TypedDict): a: Required[str] class B(A1, A2): # Should generate an error ...
Author   python
🌐
GitHub
github.com › robotframework › robotframework › issues › 5115
`NotRequired` and `Required` not properly handled with Python < 3.11 in `TypedDict` conversion · Issue #5115 · robotframework/robotframework
April 17, 2024 - Hi All, I have a few classes that use the NotRequired notation from typing_extensions_4.8.0 and python 3.9.13 class Signal(TypedDict): Network: str Signal: str class WriteSignal(Signal): Value: str Interval: NotRequired[int] This worked ...
Published   Apr 17, 2024
Find elsewhere
🌐
Python.org
discuss.python.org › typing
Extending a `TypedDict` with non-required fields - Typing - Discussions on Python.org
November 23, 2024 - Hello. There is something in the assignment rules involving TypedDicts inheritance that I don’t understand, or that mypy gets wrong. Assume the following TypedDict declarations: class A(typing.TypedDict, total=False): a: int class B(typing.TypedDict, total=False): a: int b: int As expected, this is valid code: a: A = {'a': 1} b: B = {'a': 1} However, unexpectedly for me, this is not: a: A = {'a': 1} b: B = a At the same time: b: B = {'a': 1, 'b': 2} a: A = b is considered va...
🌐
JetBrains
youtrack.jetbrains.com › issue › PY-53611 › Support-PEP-655-typing.Required-typing.NotRequired-for-TypedDicts
Support PEP 655 typing.Required/typing.NotRequired for ...
{{ (>_<) }} This version of your browser is not supported. Try upgrading to the latest stable version. Something went seriously wrong
🌐
GitHub
github.com › python › mypy › issues › 19932
`TypedDict` with `total=False` and `NotRequired` still throws an error when instantiated without all fields · Issue #19932 · python/mypy
September 26, 2025 - In this example, all fields (b and a) are not required, the field a (which is the problem here) is not required by both wrapping it in NotRequired and having its class be annotated with total=False: from typing import TypedDict, NotRequired class Bar(TypedDict, total=False): b: str class Foo(Bar, TypedDict, total=False): a: NotRequired[int] g = Bar() f = Foo(**g)
Published   Sep 26, 2025
🌐
Python
peps.python.org › pep-0705
PEP 705 – TypedDict: Read-only items | peps.python.org
All non-specified items in a TypedDict implicitly have value type ReadOnly[NotRequired[object]].
🌐
GitHub
github.com › python › mypy › issues › 17329
Accessing a `NotRequired` field in a `TypedDict` does not error · Issue #17329 · python/mypy
June 4, 2024 - Bug Report Accessing a NotRequired field in a TypedDict does not result in an error. To Reproduce from typing import NotRequired, TypedDict TypeDef = TypedDict( "TypeDef", { "Field": NotRequired[str], }, ) sample = TypeDef() val: str = s...
Published   Jun 04, 2024
🌐
GitHub
github.com › microsoft › pyright › issues › 8375
Regression: typing.NotRequired not working in typing.TypedDict · Issue #8375 · microsoft/pyright
February 23, 2024 - Describe the bug typing.NotRequired no longer seem to be allowed in typing.TypedDict. The same seems to be true for typing.Required when total=False. Code or Screenshots This is an example from the standard library docs (https://docs.python.org/3/library/typing.html#typing.TypedDict).
Published   Jul 11, 2024
🌐
JetBrains
youtrack.jetbrains.com › issue › PY-58129 › False-Positives-with-NotRequired-in-Generic-TypedDict
False Positives with NotRequired in Generic TypedDict
{{ (>_<) }} This version of your browser is not supported. Try upgrading to the latest stable version. Something went seriously wrong
🌐
GitHub
github.com › python › mypy › issues › 12094
Disallow x["foo"] for NotRequired TypedDict access · Issue #12094 · python/mypy
December 13, 2021 - We have lots of code which makes use of TypedDict with optional parameters, and one of the most common coding errors is to call dict_value["param"]. Because these are not required keys, a sound type checker should disallow this access and instead require dict_value.get("param").
Published   Jan 28, 2022
🌐
Python
peps.python.org › pep-0692
PEP 692 – Using TypedDict for more precise **kwargs typing | peps.python.org
This behaviour can be overridden by setting the dictionary’s total parameter as False. Moreover, PEP 655 introduced new type qualifiers - typing.Required and typing.NotRequired - that enable specifying whether a particular key is required or not: