I have two calculator types, Calculator1
, Calculator2
defined as follows:
Calculator1: TypeAlias = Callable[[int], int]
Calculator2: TypeAlias = Callable[[int], int]
I would like to ensure that the type checker is able to raise error in case they are used interchangeably. For example, I define additional functionality:
def calc1(x: int) -> int:
return x ** 2
def get_calc1() -> Calculator1:
return calc1
def double_application(num: int, calc: Calculator2) -> int:
return calc(calc(num))
Even when I pass in Calculator1
in double_application
it doesn't raise error. I tried this using the following functionality:
def main():
calc = get_calc1()
val = 2
final_val = double_application(val, calc)
print(final_val)
main()
I am unclear on how I would be able to separate them without creating a NewType
. Further, a NewType
can't be defined over Callable
of the follow sort. I had raised this question in a previous question (here).
You must use NewType
for your desired semantics. To make NewType
work with Callable
s, you need an intermediate type that is both subclassable and a Callable
. See this mypy playground snippet for how I use SubclassableCallable
to achieve what you need. Declarations are also below:
@dataclass(frozen=True)
class SubclassableCallable:
func: Callable[[int], int]
def __call__(self, x: int, /) -> int:
return self.func(x)
Calculator1 = NewType("Calculator1", SubclassableCallable)
Calculator2 = NewType("Calculator2", SubclassableCallable)
The resulting mypy
error is, as you expect:
error: Argument 2 to "double_application" has incompatible type "Calculator1"; expected "Calculator2" [arg-type]