Typing: Disallow TypeVar with only one constraint

Created on 14 Apr 2015  路  9Comments  路  Source: python/typing

Types like TypeVar('T', Foo) don't make sense since you can always replace them with just Foo. Although type vars with the only constraint don't break anything, they look really confusing and send the wrong message about using TypeVar. Issue #39 is a good example of this problem.

Most helpful comment

I'm not sure I understand this. What if I want to constrain a method such that two parameters use the exact same type, not just compatible types?

T = TypeVar('T', Model)

def bulk_create(model: Type[T], instances: Sequence[T]):
    pass

How could I do this without a single-constraint TypeVar?

All 9 comments

Could it be used like type synonyms in Haskell? Sure, it's a Foo, but you're communicating specifically what kind of Foo it it is.

type Address = [Char]
type Message = [Char]

send_email :: Address -> Message -> IO ()

which is far more informative than:

send_email :: [Char] -> [Char] -> IO ()

Yes, technically it's just two strings, but we're getting more information out of the type signature than "just input strings".

For that we have already type aliases

Address = str
Message = str

def send_email(add: Address, msg: Message):

I'm not sure I understand this. What if I want to constrain a method such that two parameters use the exact same type, not just compatible types?

T = TypeVar('T', Model)

def bulk_create(model: Type[T], instances: Sequence[T]):
    pass

How could I do this without a single-constraint TypeVar?

How about

def bulk_create(model: Type[Model], instances: Sequence[Model]):
    pass

Oh, I see, maybe you actually wanted T = TypeVar('T', bound=Model)?
Maybe you could clarify your use case, what exactly do you need?

Ah, yes, that's exactly what I wanted. My apologies for missing that. Thank you! :)

For my understanding, is TypeVar("T", bound=Union[Foo, Bar]) equivalent to TypeVar("T", Foo, Bar)?

For my understanding, is TypeVar("T", bound=Union[Foo, Bar]) equivalent to TypeVar("T", Foo, Bar)?

No, these are totally different things. Upper bound is what it says -- an upper bound. While type variable with value restrictions can take only _exactly_ a restriction. For example (read PEP 484) passing a subtype of Foo will still infer T = Foo.

I see, thanks. Here's an example for future reference:

from typing import TypeVar
from typing import Union

class MyInt(int):
    pass

T = TypeVar("T", int, str)
U = TypeVar("U", bound=Union[int, str])

def takes_t(x: T) -> T:
    return x

def takes_u(x: U) -> U:
    return x

a: int = takes_t(42)
b: int = takes_u(42)

c: str = takes_t("hi")
d: str = takes_u("hi")

e: MyInt = takes_t(MyInt())  # Does not typecheck: takes_t returns int
f: MyInt = takes_u(MyInt())  # Typechecks: takes_u returns MyInt
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tomzx picture tomzx  路  5Comments

matthiaskramm picture matthiaskramm  路  6Comments

LiraNuna picture LiraNuna  路  7Comments

feluxe picture feluxe  路  8Comments

mitar picture mitar  路  5Comments