Skip to content

Cannot combine special types in alternative TypedDict syntax #20401

@alicederyn

Description

@alicederyn

Bug Report

mypy is raising an internal error when attempting to combine special types in a TypedDict using the alternative functional syntax.

To Reproduce

from typing import NotRequired, TypedDict
from typing_extensions import ReadOnly

Foo = TypedDict("Foo", {
    "required-field-with-hyphens": ReadOnly[int],
    "optional-field-with-hyphens": NotRequired[ReadOnly[int]],
})

value: Foo = {"required-field-with-hyphens": 1, "optional-field-with-hyphens": 2}

Playground

Expected Behavior

This should pass type-checking. PEP-705 states that

  • The alternative functional syntax for TypedDict also supports the new type qualifier
  • ReadOnly can be used with Required, NotRequired and Annotated, in any nesting order

Actual Behavior

Running this specific snippet with mypy in Python 3.12, I get:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "mypy/checkexpr.py", line 6044, in accept
  File "mypy/types.py", line 3677, in get_proper_type
TypeError: mypy.types.ProperType object expected; got mypy.types.ReadOnlyType

It passes if the second field is removed, so this is just combining special types which is causing the problem; ReadOnly inside the functional syntax by itself is working fine. Additionally, it works fine if using the class-based syntax (though obviously I can't do that as there are hyphens). I can work around the issue by using total=False and inheritance, so it's not a critical blocker,

Additionally, if I remove the last line (value: Foo = ...) from the code, when I run mypy locally, I get the following internal error:

  File "mypy/main.py", line 127, in main
  File "mypy/main.py", line 211, in run_build
  File "mypy/build.py", line 215, in build
  File "mypy/build.py", line 294, in _build
  File "mypy/build.py", line 2945, in dispatch
  File "mypy/build.py", line 3336, in process_graph
  File "mypy/build.py", line 918, in wait_for_done
  File "mypy/build.py", line 3502, in process_stale_scc
  File "mypy/build.py", line 2501, in write_cache
  File "mypy/build.py", line 1601, in write_cache
  File "mypy/nodes.py", line 425, in serialize
  File "mypy/nodes.py", line 4742, in serialize
  File "mypy/nodes.py", line 4631, in serialize
  File "mypy/nodes.py", line 3916, in serialize
  File "mypy/types.py", line 3031, in serialize
  File "mypy/types.py", line 310, in serialize
    if (coro.__class__ is CoroutineType or
NotImplementedError: Cannot serialize ReadOnlyType instance

I can't reproduce this on the playground (I assume because the cache path is disabled).

Your Environment

  • Mypy version used: 1.19.0
  • Python version used: 3.12

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions