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.
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 toTypeVar("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
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?
How could I do this without a single-constraint TypeVar?