2026-04-28

Stop doing 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.