Search code examples
pythontype-hintingmypy

How can I properly type a subclass of class which sub-types a Generic base class?


I have two classes inheriting from dict, like this:

class A(dict):

class B(A):

This all works fine - the two classes use the inherited dict functionality and do other required stuff. However, I also want to use type-hinting. The first should reduce the range of the Dict generic and the second should reduce it further. For example, I'd like to write something like:

class A(Dict[str, Any]):

class B(A[str, int]):

This works fine for A but not for B (that code is not syntactically correct, of course).

Class B isn't a sub-type of A (since it can't handle anything other than int) and that's fine but I do need it to inherit. Can I get mypy to understand the correct type of B and still inherit from A?

The only solution I can see at present is to re-implement all the inherited methods from A but that would be a lot of runtime boiler-plate just to declare the correct typing.


Solution

  • So a little more thought and I think it's easy. I just need to move the shared functionality out of A and into a new generic which inherits from Dict. Simple:

    from typing import Generic, TypeVar, Dict, Any
    
    KT = TypeVar('KT')
    VT = TypeVar('VT')
    
    class GenericA(Dict[KT, VT]):
        def my_method(self):
            print(list(self.values()))
    
    
    A = GenericA[str, Any]
    
    class B(GenericA[str, int]):
        def more_methods(self):
            print(list(self.keys()))
    
    a = A({"a" : "blob", "b" : "blib"})
    a.my_method()
    
    b = B({"a" : 1, "b" : 2})
    b.my_method()
    b.more_methods()