Mypy typing for kwargs in case of inheritance

Viewed 1068

I have found couples of answers about how to handle kwargs with MyPy. But actually my problem is that mypy does not properly catch this:

from typing import Union


class Parent:
    def __init__(self, a: int, b: str) -> None:
        self.a = a
        self.b = b


class Child(Parent):
    def __init__(self, c: float, **kwargs: Union[int, str]) -> None:
        super().__init__(**kwargs)
        self.c = c


child = Child(a="a", b=2, c=2.3)

# tmp.py:12: error: Argument 1 to "__init__" of "Parent" has incompatible type "**Dict[str, Union[int, str]]"; expected "int"
# tmp.py:12: error: Argument 1 to "__init__" of "Parent" has incompatible type "**Dict[str, Union[int, str]]"; expected "str"
# Found 2 errors in 1 file (checked 1 source file)

I don't know how to handle this case. I don't want to update the Child.__init__ because it is a less maintainable pattern.

2 Answers

This seems to work, but is it only a workaround?

from typing import overload

class Parent:

    def __init__(self, a: int, b: str) -> None:
        self.a = a
        self.b = b


class Child(Parent):

    @overload
    def __init__(self, c: float) -> None: ...

    @overload
    def __init__(self, c: float, * , a: int=..., b: str=...) -> None: ...

    def __init__(self, c: float, **kwargs) -> None:
        super().__init__(**kwargs)
        self.c = c


child = Child(2.3)
child = Child(2.3, a=3)
child = Child(2.3, b='5')
child = Child(2.3, a=3, b='5')
child = Child(a=3, b='5', c=2.3)
child = Child(a=3, b='5')  # mypy error ok
child = Child(a='3', b='5', c=2.3)  # mypy error ok
child = Child(a=3, b=5, c=2.3)  # mypy error ok
child = Child(a=3, b='5', c='2.3')  # mypy error ok
Related