Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function for getting type of TypedDict value that works with static type checker

I am looking to make a Python (3.8+) function that is:

  • Input: key of a TypedDict
  • Output:
    • Returns the value (easy)
    • Is appropriately type hinted (where I am stuck)

Here is a code sample to help explain:

from typing import Any, Literal, TypedDict

class Foo(TypedDict):
    bar: int
    baz: str
    spam: Any

foo = Foo(bar=0, baz="hi", spam=1.0)

def get_type(key: Literal["bar", "baz"]):  # How to type hint the return here?
    """Function that get TypedDict's value when passed a key."""
    val = foo[key]
    # This works via intelligent indexing
    # SEE: https://mypy.readthedocs.io/en/stable/literal_types.html#intelligent-indexing
    reveal_type(val)  # mypy: Revealed type is 'Union[builtins.int, builtins.str]'
    return val

fetched_type = get_type("bar")
reveal_type(fetched_type)  # mypy: Revealed type is 'Any'
# I would like this to have output: 'int'

In case you can't tell, the static type checker I am using is mypy.

The function I have above get_type gets halfway there with intelligent indexing, but I am not sure how to type hint the return of get_type.

What type hint should I put for the return of get_type?


Research

Both of these questions

  • Factory function for mypy `TypedDict`
  • How to statically get TypeVar parameters from a Generic for use in static type checking?

provide answers using TypeVar. Is there some way of using TypeVar with TypedDict?

like image 505
Intrastellar Explorer Avatar asked Oct 16 '25 02:10

Intrastellar Explorer


1 Answers

If I understood your problem correctly, you could use @overload for get_type:

from typing import Any, Literal, TypedDict, Union, overload

class Foo(TypedDict):
    bar: int
    baz: str
    spam: Any

foo = Foo(bar=0, baz="hi", spam=1.0)


@overload
def get_type(key: Literal["bar"]) -> int: ...

@overload
def get_type(key: Literal["baz"]) -> str: ...
    

def get_type(key: Literal["bar", "baz"]) -> Union[int, str]:
    """Function that get TypedDict's value when passed a key."""
    val = foo[key]
    reveal_type(val)  # mypy: Revealed type is 'Union[builtins.int, builtins.str]'
    return val

fetched_type = get_type("bar")
reveal_type(fetched_type)  # mypy: Revealed type is 'builtins.int'

like image 51
alex_noname Avatar answered Oct 17 '25 17:10

alex_noname



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!