How do I write a type hint to indicate that a variable is a specific subtype of the return type of a method

4 weeks ago 17
ARTICLE AD BOX

Use typing.cast when the runtime subtype is known

If you are certain that some_object.method() will always return B in your specific context, the idiomatic way to inform the type checker without using assert is typing.cast.

cast is a static typing construct: it affects only the type checker and has no effect at runtime.

from typing import cast class MyClass: def __init__(self): variable = cast(B, some_object.method()) self.attribute = variable

This tells tools like mypy or pyright to treat the value as B, even though the declared return type is A.

When to use this

Use assert isinstance(...) if you want a runtime check.

Use cast(...) if the subtype is guaranteed by external logic and you only need to narrow the type for static analysis.

cast is appropriate here because the type narrowing is based on contextual knowledge that the type checker cannot infer.

go2maxi's user avatar

New contributor

go2maxi is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

It depends on whether you are trying to hint an instance of a subclass or the class object itself.

Scenario 1: You want to accept the Class itself (The Factory Pattern)

If you want to pass the class Dog (the blueprint) to a function, use type[T].

Modern Python (3.9+): Use the built-in type[].

Older Python: Use typing.Type[].

Python

class Animal: ... class Dog(Animal): ...

def make_animal(animal_class: type[Animal]) -> Animal: return animal_class()

make_animal(Dog) # Valid make_animal(Animal) # Valid make_animal(str) # Error: 'str' is not a subtype of 'Animal'

### Scenario 2: You want the return type to match the input type

If you want your function to return the exact subclass that was passed in (e.g., if I pass Dog, I get back Dog, not just Animal), you need a TypeVar bound to the parent class.

Python

from typing import TypeVar

T = TypeVar("T", bound="Animal")

def create_instance(cls: type[T]) -> T: return cls()

dog = create_instance(Dog)

### Scenario 3: You just mean an instance

If you just want to accept an object that is a subclass of Animal, you don't need special syntax. Standard hints are covariant by default.

Python

# Accepts instance of Animal OR Dog OR Cat def pet_animal(pet: Animal): pass

pet_animal(Dog()) # Valid

Gavin Dobbs's user avatar

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Read Entire Article