Reputation: 1139
Here is my code snippet. I wonder what return type to use for the create
classmethod of both factory classes. I would like to avoid using Union[Model1, Model2]
if it's possible.
T = typing.TypeVar("T", bound="BaseModel")
@dataclass
class BaseModel(object):
pass
@dataclass
class Model1(BaseModel):
pass
@dataclass
class Model2(BaseModel):
pass
class ModelFactory(ABC):
@classmethod
@abstractmethod
def create(cls) -> T:
pass
class Model1Factory(ModelFactory):
@classmethod
def create(cls) -> T:
return Model1()
class Model2Factory(ModelFactory):
@classmethod
def create(cls) -> T:
return Model2()
m1factory = Model1Factory()
m1 = m1factory.create()
The error I am getting from mypy:
type_hint.child_class_return_self.2.py:32: error: Incompatible return value type (got "Model1", expected "T")
type_hint.child_class_return_self.2.py:37: error: Incompatible return value type (got "Model2", expected "T")
type_hint.child_class_return_self.2.py:41: error: Need type annotation for 'm1'
Upvotes: 0
Views: 1434
Reputation: 3387
According to mypy cheat sheet you should go for Union[Model1, Model2]
, but if it's something you want to avoid, the next best candidate is Any
type.
Upvotes: 0
Reputation: 76
I think you just need to incorporate Generic
into the equation so that mypy
can accept different return types:
from abc import ABC
from typing import Generic, TypeVar
T = typing.TypeVar("T", bound="BaseModel")
@dataclass
class BaseModel(object):
pass
@dataclass
class Model1(BaseModel):
pass
@dataclass
class Model2(BaseModel):
pass
class ModelFactory(Generic[T], ABC):
@classmethod
@abstractmethod
def create(cls) -> T:
pass
class Model1Factory(ModelFactory[Model1]):
@classmethod
def create(cls) -> Model1:
return Model1()
class Model2Factory(ModelFactory[Model2]):
@classmethod
def create(cls) -> Model2:
return Model2()
m1factory = Model1Factory()
m1 = m1factory.create()
Upvotes: 2