⇦
2026-04-28
Container[Any]Given a container like:
@dataclass
class Container(Generic[T]):
value: T
It's tempting to type functions that could take any old Container like:
def f(x: Container[Any]) -> None:
...
However, if you do that, the following won't raise a type error:
def f(x: Container[Any]) -> None:
x.value + "some-string"
Any has snuck into your type system.
Instead, use object, then you'll get an error:
def f(x: Container[object]) -> None:
x.value + "some-string" # error: Unsupported left operand type for + ("object") [operator]
If you don't know what type a value is, let the typechecker know you don't know.
Maybe you never cared what type it was, maybe you need to if not isinstance(x.value, SomeType): raise ...
As of Python 3.13, you can have defaults for your TypeVars, [T=object] is probably a sensible default, as [T] can be equivalent to [T=Any] - with subtle differences depending on the typechecker:
Python==3.14.0b3 mypy==1.20.2 ty==0.0.33
@dataclass
@typing.final
class Container[T]:
value: T
def f() -> Container | str: ...
def g() -> object: ...
c = f()
if isinstance(c, Container):
reveal_type(c) # mypy: Container[Any] ty: Container[Unknown]
d = g()
if isinstance(d, Container):
reveal_type(d) # mypy: Container[Any] ty: Top[Container[Unknown]]
@dataclass
@typing.final
class Container[T=object]:
value: T
def f() -> Container | str: ...
def g() -> object: ...
c = f()
if isinstance(c, Container):
reveal_type(c) # mypy: Container[object] ty: Container[object]
d = g()
if isinstance(d, Container):
reveal_type(d) # mypy: Container[Any] ty: Container[object]
@dataclass
@typing.final
class Container[T=Any]:
value: T
def f() -> Container | str: ...
def g() -> object: ...
c = f()
if isinstance(c, Container):
reveal_type(c) # mypy: Container[Any] ty: Container[Any]
d = g()
if isinstance(d, Container):
reveal_type(d) # mypy: Container[Any] ty: Top[Container[Any]]
Note on Top.