Search code examples
pythonpython-typing

What's the point of using TypeVar?


When speaking about Generics, Python gives the following example:

from collections.abc import Sequence
from typing import TypeVar

T = TypeVar('T')      # Declare type variable

def first(l: Sequence[T]) -> T:   # Generic function
    return l[0]

Could someone please explain what TypeVar does in this case? For example, if it can be anything, why not just give it the value Any? And if it's constrained, why not give it a Union value? In other words, what is the usefulness of using TypeVar(...)?

I suppose in reviewing the above, it's used when an element of some sort of sub-element? For example, it could be:

[{set1}, {set2}, {set3}, ...]

And that type would be Sequence[set] -> set

But something like this:

[1, 2, 3, ...]

Would have type Sequence[int] -> int. Are there any other usages besides this "item-in-iterable"?


Solution

  • The purpose of the TypeVar in this context is to say that the function returns a specific type that is related to the argument's type.

    For example, if you did:

    a = first([1, 2, 3]) + "foo"
    

    you would get an error, because in this expression T becomes bound to the type int, and so you'd get an error about adding an int and a str.

    If you annotated first with Any types as you describe, this would not produce a mypy error (and hence you'd get a TypeError at runtime instead), because the return value of first would always simply be Any.

    See the mypy documentation on generics for a lot more examples of how to use typevars: https://mypy.readthedocs.io/en/stable/generics.html