Skip to content

More precise return types form TypedDict.get #19896

@randolf-scholz

Description

@randolf-scholz

https://mypy-play.net/?mypy=latest&python=3.12&gist=2af067d4175540de3e8fbda389983bed

from typing import TypedDict, Required, NotRequired

class D(TypedDict):
    x: Required[int]
    y: NotRequired[int]

def test(d: D, s: str) -> None:
    reveal_type(d.get("x"))     # int | None        
    reveal_type(d.get("x", 1))  # int    
    reveal_type(d.get("x", s))  # int | str

    reveal_type(d.get("y"))     # int | None 
    reveal_type(d.get("y", 1))  # int
    reveal_type(d.get("y", s))  # int | str

Both d.get("x") and d.get("x", s) could give the more precise int: Since the key "x' is required, the default is irrelevant. This is how pyright handles it as well.

Moreover, it would be nice if reveal_type(d.get) would give an appropriate overload signature.

# mypy
Revealed type is "Overload(
    def (builtins.str) -> builtins.object,
    def (builtins.str, default: builtins.object) -> builtins.object,
    def [_T] (builtins.str, default: _T`475) -> builtins.object
)"
# pyright:
Type of "d.get" is "Overload[
    (k: Literal['x']) -> int,
    (k: Literal['x'], default: Any) -> int,
    (k: Literal['y']) -> (int | None),
    (k: Literal['y'], default: int | __TDefault@D) -> (int | __TDefault@D),
    (k: str) -> (Any | None),
    (k: str, default: Any | __TDefault@D) -> (Any | __TDefault@D)
]"

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions