3

I want to define a function example that takes an argument of type Widget or anything that extends Widget and returns the same type as the argument. So if Button extends Widget, calling example(Button()) returns type Button.

I tried the following:

T_co = TypeVar('T_co', Widget, covariant=True)

def example(widget: T_co) -> T_co:
  ...

However the type checker (Pyright) ignores the covariance. Upon further research I found a note in PEP 484:

Note: Covariance or contravariance is not a property of a type variable, but a property of a generic class defined using this variable. Variance is only applicable to generic types; generic functions do not have this property. The latter should be defined using only type variables without covariant or contravariant keyword arguments.

However if I try to define a generic function without the covariant argument as specified in the note:

T_co = TypeVar('T_co', Widget)

def example(widget: T_co) -> T_co:
  ...

I can only pass values of type Widget to the function (not Button).

How can I achieve this?

4
  • Sorry a little lost. Does type(myVar) not accurately return what you want? If it does than you can just use isinstance(mVar, Widget) since isinstance can handle inheritance. Commented Oct 14, 2019 at 15:28
  • @Error-SyntacticalRemorse I'm looking for compiler (Pyright) type checking, not runtime Commented Oct 14, 2019 at 16:10
  • Static type checking, not compile time (since python doesn't really compile). That being the case I would recommend switching to MyPy, it is more commonly used and thus has more features to make your life easier. That being said, you are probably better off type hinting than trying to enforce, and handling types during runtime if you are making a package for others to use, Commented Oct 14, 2019 at 16:47
  • Thanks, static is the correct term. I know about MyPy but this particular issue is correctly handled by Pyright; it's states as such in PEP 484. I am just interested in what the workaround is. Commented Oct 14, 2019 at 18:20

1 Answer 1

3

I was able to find the answer in the MyPy docs. Turns out I was looking for bound, not covariant. This can be done like so:

T = TypeVar('T', bound=Widget)

def example(widget: T) -> T:
  ...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.