Literal types let you indicate that an expression is equal to some specific primitive value. For example, Literal["foo"] means the value is not just a str, but specifically the string "foo".
from typing import Literal, overload@overloaddef fetch_data(raw: Literal[True]) -> bytes: ...@overloaddef fetch_data(raw: Literal[False]) -> str: ...@overloaddef fetch_data(raw: bool) -> bytes | str: ...def fetch_data(raw: bool) -> bytes | str: ...reveal_type(fetch_data(True)) # Revealed type is "bytes"reveal_type(fetch_data(False)) # Revealed type is "str"
from typing import Final, Literaldef expects_literal(x: Literal[19]) -> None: ...c: Final = 19reveal_type(c) # Revealed type is "Literal[19]?"expects_literal(c) # OK
The ? indicates the type is context-sensitive. Mypy substitutes the original value when checking.
Use literal types to precisely index into structured heterogeneous types:
from typing import Literal, Finaltup = ("foo", 3.4)# Indexing with an int literal gives exact typereveal_type(tup[0]) # Revealed type is "str"# Regular int gives union typeint_index = 0reveal_type(tup[int_index]) # Revealed type is "str | float"# Literal or Final gives exact type backlit_index: Literal[0] = 0fin_index: Final = 0reveal_type(tup[lit_index]) # Revealed type is "str"reveal_type(tup[fin_index]) # Revealed type is "str"
from enum import Enumfrom typing_extensions import assert_neverclass Direction(Enum): up = 'up' down = 'down'reveal_type(Direction.up) # Revealed type is "Literal[Direction.up]?"def choose_direction(direction: Direction) -> None: if direction is Direction.up: reveal_type(direction) # Revealed type is "Literal[Direction.up]" print('Going up!') return elif direction is Direction.down: print('Down') return assert_never(direction)