Search code examples
pythonvisual-studio-codepython-typing

Python Typehint Generic Collection


I am wondering about the proper way to type-hint a 'collection' class in Python?

I have a collection class with an instance attribute of type 'T' to hold a collection of items:

from dataclasses import dataclass, field
from typing import TypeVar, Union

@dataclass
class SurfaceTypeA:
    def common_method(self) -> None:
        pass

@dataclass
class SurfaceTypeB:
    def common_method(self) -> None:
        pass

T = TypeVar("T", bound=Union[SurfaceTypeA, SurfaceTypeB])

@dataclass
class SurfaceCollection[T]:

    _surfaces: list[T] = field(default_factory=list)

    def run_common_method_on_surfaces(self) -> None:
        for s in self._surfaces:
            s.common_method()

This runs fine, but in my IDE (VS-Code), I get a type-warning on the line s.common_method():

Cannot access member "common_method" for type "object*"

Screen Shot from VS-Code

Is there a proper way to type-hint a scenario like this so VS-Code recognizes the type?


Solution

  • You're mixing old and new syntax. You either use TypeVar or class Foo[T]: but not both. Try

    class SurfaceCollection[T: SurfaceTypeA | SurfaceTypeB]:
    

    and deleting the TypeVar.

    Currently the T in class SurfaceCollection[T]: is shadowing the TypeVar and so is bound to object not Union[SurfaceTypeA, SurfaceTypeB].