Here’s another example, contrasting the behavior of mypy
and pyright
with Enum
and Literal
. From a typing perspective, my colleagues and I like to view Literal
as a typing shorthand for creating an Enum
class, but pyright
makes this hard to do because of the type “widening” going on.
from enum import Enum
from typing import Literal
class MyEnumAB(Enum):
A = 1
B = 2
def enum_returnset(thelist: list[MyEnumAB]) -> set[MyEnumAB]:
y = set([x for x in thelist])
reveal_type(y)
return y
MyLiteral = type[Literal[1, 2]]
def lit_returnset(thelist: list[MyLiteral]) -> set[MyLiteral]:
y = set([x for x in thelist])
reveal_type(y)
return y
pyright output
enumadd.py
enumadd.py:12:17 - information: Type of "y" is "set[MyEnumAB]"
enumadd.py:21:17 - information: Type of "y" is "set[type[int]]"
enumadd.py:22:12 - error: Type "set[type[int]]" is not assignable to return type "set[MyLiteral]"
"set[type[int]]" is not assignable to "set[MyLiteral]"
Type parameter "_T@set" is invariant, but "type[int]" is not the same as "MyLiteral"
Consider switching from "set" to "Container" which is covariant (reportReturnType)
mypy output:
enumadd.py:12: note: Revealed type is "builtins.set[enumadd.MyEnumAB]"
enumadd.py:21: note: Revealed type is "builtins.set[Union[type[Literal[1]], type[Literal[2]]]]"