Is there anyway to make this work
from typing import Literal
def foo(bar: Literal["bar"]) -> Literal["foo"]:foo = "foo"return foobar = "bar"
foo(bar)
Here are the errors
foo.py:4: error: Incompatible return value type (got "str", expected "Literal['foo']")
foo.py:8: error: Argument 1 to "foo" has incompatible type "str"; expected "Literal['bar']"
Is pretty obvious that foo
variable and bar
are literals because they are assigned to literals, so this is safe, but mypy seems to not track this. Is there anything that I'm missing?
MyPy infers literals to their builtin type, not a Literal
of their value.
mypy Docs » Literal types
You must explicitly add an annotation to a variable to declare that it has a literal type. [..] variables without this annotation are not assumed to be literals.
To allow inference of Literal
values, annotate the variable as Final
:
from typing import Finalfrom typing_extensions import Finalbar: Final = "bar"
reveal_type(bar) # Revealed type is 'Literal['bar']?'
Annotating a variable as Final
indicates that its value will not be substituted for a value of similar type. This makes it correct to infer the type as the specific Literal
value, instead of just the general type.
Note that this inference is contextual: The type is inferred as Literal
for all cases where a Literal
is expected. For cases in which a type is expected, be it the literal type, a base type or TypeVar, the type is inferred as the general type.
reveal_type([bar]) # Revealed type is 'builtins.list[builtins.str*]'