Skip to content

Disallow TypeVar with only one constraint #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vlasovskikh opened this issue Apr 14, 2015 · 12 comments
Closed

Disallow TypeVar with only one constraint #82

vlasovskikh opened this issue Apr 14, 2015 · 12 comments

Comments

@vlasovskikh
Copy link
Member

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.

@justanr
Copy link

justanr commented Apr 29, 2015

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".

@gvanrossum
Copy link
Member

For that we have already type aliases

Address = str
Message = str

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

gvanrossum pushed a commit that referenced this issue May 18, 2015
@theY4Kman
Copy link

theY4Kman commented May 5, 2017

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?

@ilevkivskyi
Copy link
Member

How about

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

@ilevkivskyi
Copy link
Member

ilevkivskyi commented May 5, 2017

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

@theY4Kman
Copy link

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

@untitaker
Copy link

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

@ilevkivskyi
Copy link
Member

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.

@untitaker
Copy link

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

@dumblob
Copy link

dumblob commented May 12, 2021

Hm, currently ran into this issue: ...

Forget it - it was a typo (the class should not derive from the typevar).

@Ma233
Copy link

Ma233 commented Oct 7, 2021

Hi, I just met a situation that may need a TypeVar with only one constraint:

from enum import Enum
from typing import Type

StateEnum = TypeVar("StateEnum", Enum)

class StateMachine:
    def __init__(self, state_enum: Type[StateEnum], initial_state: StateEnum): ...

Here I want to annotate that the initial_state is an instance of state_enum which will be declared later, and state_enum is a subclass of Enum.

@gvanrossum
Copy link
Member

@Magine, you should use bound=Enum.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants