How can I type the return type of a subclass in Python?

67 Views Asked by At

I use the service object pattern in my codebase. I have a base class for service objects:

from abc import ABC, abstractmethod
from typing import Generic, TypeVar

T = TypeVar("T", contravariant=True)  # input type
R = TypeVar("R", covariant=True)  # return type


class BaseService(Generic[T, R], ABC):
    """Service object that strongly types its inputs and outputs."""

    inputs: T

    def __init__(self, inputs: T):
        self.inputs = inputs

    @classmethod
    def execute(cls, inputs: T, **kwargs) -> R:
        instance = cls(inputs, **kwargs)
        return instance.process()

    @abstractmethod
    def process(self) -> R:
        """
        Main method to be overridden; contains the business logic.
        """

Its usage is e.g.

from typing import TypedDict

class Inputs(TypedDict):
  foo: str

class DoubleService(BaseService[Inputs, str]):
  def process(self):
    return self.inputs["foo"] * 2


DoubleService.execute({"foo": "bar"}) # returns "barbar"

I want to enforce correct typing of the process method in subclasses. For example, I want all of the following to fail in the type checker:

class Inputs(TypedDict):
  foo: str

class InvalidOne(BaseService[Inputs, str]):
  def process(self) -> int: # wrong explicit return type
    # ...

class InvalidTwo(BaseService[Inputs, str]):
  def process(self):
    return 1 # wrong implicit return type

Is is possible to achieve this with any existing type checker? I don't care if it's Mypy / Pyright / something else.

0

There are 0 best solutions below