You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
FeedParser allows a message factory to be passed in and will use it to construct the return value to close(). Unfortunately you have to cast the return value of close() to the correct type:
#4227 is somewhat related, but the underlying issue is that since mypy doesn't know what the return type of the _factory() Callable is (since the default is of the uninhabited type), mypy cannot deduce the return type to close().
It seems to me we might be able to fall back to the bound type, but I'm not sure about that.
Would having a "default" type for TypeVars make sense? Falling back to the bound type makes sense with my example above, but I am also unsure whether that is the right thing to do for the general case.
There seem to be two separate things going on here:
Infer a default value for type variable from the type of a default argument value (@chadrik's example above). I've wanted this once or twice. Overloading seems like a reasonable workaround, though.
Give an explicit default value for a type variable. The scope could be for all instances of type variable or just for a particular class/function.
If it's for all instances, we may need a change to TypeVar, such as T = TypeVar('T', default=str). This needs to be proposed at https://github.com/python/typing.
If it's for a particular definition, we could use a class/function decorator such as @mypy_extensions.type_var_default(T, str). This could well be mypy-specific.
I think that the first change is not very controversial, but pretty low priority since there is a workaround. For the second change we'd need more evidence of it being generally useful.
I think that the first change is not very controversial, but pretty low priority since there is a workaround.
I can agree with this as long as this use case is taken into consideration during the overflow overhaul (henceforth known as the overflowhaul). Currently I can't solve this without running into overlapping overload errors.
For the second change we'd need more evidence of it being generally useful.
It looks like this pattern is used extensively in SQLAlchemy. A simplified example:
classNull: ...
classClause(Generic[T]):
def__init__(self, type: Optional[Type[T]] =None) ->None:
iftypeisNone:
type=Null# Something like this happens at runtimeself.type=typereveal_type(Clause(int)) # OK, `Clause[int]`reveal_type(Clause()) # Bad, `Clause[<nothing>]`, should be `Clause[Null]`
A potential solution is to use an overloaded __new__ but unfortunately it doesn't work.
I think this can be raised to at least normal priority.
IMO, I think the T = TypeVar('T', default=str) syntax would be the most robust in the long-run. TypeScript has a similar syntax and it's very handy:
classClause<T=Null>{type: T;constructor(type?: T){this.type=type ? type() : Null();}}letc=newClause()c.type// type is Nullletd=newClause(Integer);d.type// type is Integer
This could also potentially be combined with the bound parameter of TypeVar() to provide both the base type of the generic and a default value. @ilevkivskyi's example above would look like this:
classNull: ...
T=TypeVar('T', default=Null)
classClause(Generic[T]):
type: Tdef__init__(self, , type: Optional[Type[T]] =None) ->None:
iftypeisNone:
type=Null# Something like this happens at runtimeself.type=type()
reveal_type(Clause(int)) # OK, `Clause[int]`reveal_type(Clause()) # Ok, `Clause[Null]`
Then a developer (of either stubs or a library) wouldn't need to mess with __new__ to type this pattern.
Reacted by Povilas Balciunas, François Levasseur, Коренберг Марк, Benjamin Jones, Haowei Wang, codecakes, ippei and lovetheguitar
For what it's worth, the workaround suggested in the first bullet of #4236 (comment), namely using overloads to handle the default argument, doesn't work if the function has a catch-all **kwargs: Any.
In particular, I'm looking into making the click.group decorator respect the optional cls keyword arg (so that mypy understands that the returned object is an instance of the cls type, rather than always a click.Group). Because this decorator needs to take **kwargs: Any to pass along to the cls constructor, any @overloads will always match the first overload. At least in this particular case, something like the proposed default option (or respecting the default arg) would be useful.
I don’t think the T = TypeVar('T', default=str) concept makes sense as stated. Going back to @bryanforbes’ TypeScript vs. proposed Python examples:
in the TypeScript, the T = Null default means that T is Null unless T is provided, while
in the proposed Python, the TypeVar('T', default=Null) default purportedly means that T is Null unless type: Optional[Type[T]] is provided.
But on what grounds is mypy to reason that the type parameter is what controls T? What if there are multiple parameters referencing T? And how is mypy to notice the type error in Clause[int]() where T is provided but type is not?
then mypy ought to be able to infer that T is Null unless type is provided. I think all it needs to do is defer the type checking (or at least the type unification) of the default argument value from the declaration site to the call site. Related: #3737.
I’m coming here from a more complicated case in Zulip, where we have three type variables ItemT, CacheItemT, CompressedItemT and we want to infer that ItemT is CacheItemT unless an optional Callable[[ItemT], CacheItemT] parameter defaulting to an identity function is provided, and that CacheItemT is CompressedItemT unless a pair of optional Callable[[CacheItemT], CompressedItemT] and Callable[[CompressedItemT], CacheItemT] parameters defaulting to identity functions are provided.
Now that both overloading __new__() and overloading __init__() work correctly (see my comment just above), I think explicit type variable defaults is pretty low priority.
Activity
emmatyping commentedon Nov 10, 2017
#4227 is somewhat related, but the underlying issue is that since mypy doesn't know what the return type of the
_factory()Callable is (since the default is of the uninhabited type), mypy cannot deduce the return type toclose().It seems to me we might be able to fall back to the bound type, but I'm not sure about that.
srittau commentedon Nov 10, 2017
Would having a "default" type for
TypeVars make sense? Falling back to the bound type makes sense with my example above, but I am also unsure whether that is the right thing to do for the general case.chadrik commentedon Nov 13, 2017
I've run into a similar problem, where I intuitively wanted to add a default value in my stubbed function to affect the outcome:
JukkaL commentedon Nov 15, 2017
There seem to be two separate things going on here:
TypeVar, such asT = TypeVar('T', default=str). This needs to be proposed at https://github.com/python/typing.@mypy_extensions.type_var_default(T, str). This could well be mypy-specific.I think that the first change is not very controversial, but pretty low priority since there is a workaround. For the second change we'd need more evidence of it being generally useful.
chadrik commentedon Nov 15, 2017
I can agree with this as long as this use case is taken into consideration during the overflow overhaul (henceforth known as the overflowhaul). Currently I can't solve this without running into overlapping overload errors.
srittau commentedon Nov 15, 2017
If I understand correctly, the first suggestion would also allow us to write the
FeedParserdefinition as:I think that's a fine solution.
ilevkivskyi commentedon Aug 26, 2018
@JukkaL
It looks like this pattern is used extensively in SQLAlchemy. A simplified example:
A potential solution is to use an overloaded
__new__but unfortunately it doesn't work.I think this can be raised to at least normal priority.
bryanforbes commentedon Aug 26, 2018
IMO, I think the
T = TypeVar('T', default=str)syntax would be the most robust in the long-run. TypeScript has a similar syntax and it's very handy:This could also potentially be combined with the
boundparameter ofTypeVar()to provide both the base type of the generic and a default value. @ilevkivskyi's example above would look like this:Then a developer (of either stubs or a library) wouldn't need to mess with
__new__to type this pattern.bryanforbes commentedon Aug 26, 2018
I forgot to give an example of
defaultandbound:FuegoFro commentedon Mar 7, 2019
For what it's worth, the workaround suggested in the first bullet of #4236 (comment), namely using overloads to handle the default argument, doesn't work if the function has a catch-all
**kwargs: Any.In particular, I'm looking into making the
click.groupdecorator respect the optionalclskeyword arg (so that mypy understands that the returned object is an instance of theclstype, rather than always aclick.Group). Because this decorator needs to take**kwargs: Anyto pass along to theclsconstructor, any@overloads will always match the first overload. At least in this particular case, something like the proposeddefaultoption (or respecting the default arg) would be useful.emmatyping commentedon Mar 8, 2019
This came up again (if I'm not mistaken) in #6525. Raising priority to high.
andersk commentedon Aug 14, 2019
I don’t think the
T = TypeVar('T', default=str)concept makes sense as stated. Going back to @bryanforbes’ TypeScript vs. proposed Python examples:T = Nulldefault means thatTisNullunlessTis provided, whileTypeVar('T', default=Null)default purportedly means thatTisNullunlesstype: Optional[Type[T]]is provided.But on what grounds is mypy to reason that the
typeparameter is what controlsT? What if there are multiple parameters referencingT? And how is mypy to notice the type error inClause[int]()whereTis provided buttypeis not?On the other hand, if you could write
then mypy ought to be able to infer that
TisNullunlesstypeis provided. I think all it needs to do is defer the type checking (or at least the type unification) of the default argument value from the declaration site to the call site. Related: #3737.I’m coming here from a more complicated case in Zulip, where we have three type variables
ItemT,CacheItemT,CompressedItemTand we want to infer thatItemTisCacheItemTunless an optionalCallable[[ItemT], CacheItemT]parameter defaulting to an identity function is provided, and thatCacheItemTisCompressedItemTunless a pair of optionalCallable[[CacheItemT], CompressedItemT]andCallable[[CompressedItemT], CacheItemT]parameters defaulting to identity functions are provided.ilevkivskyi commentedon Aug 15, 2019
Mypy already allows overloading
__new__, so that one can already write:I think we can just add support for overloading on
selfin__init__for those cases where actual implementation uses__init__instead of__new__:ilevkivskyi commentedon Nov 12, 2019
Now that both overloading
__new__()and overloading__init__()work correctly (see my comment just above), I think explicit type variable defaults is pretty low priority.JukkaL commentedon Jan 29, 2020
Type variable defaults should be discussed on typing-sig@ or the typing issue tracker, since they require changes to the
typingmodule.jessekv commentedon May 27, 2024
To close the loop, PEP 696 – Type Defaults for Type Parameters was accepted and will land in Python 3.13.
edit: here is the updated issue number: #14851
pirate commentedon Aug 2, 2025
does anyone know if a backport is available for TypeVar(default=...) for python 3.11 and 3.12
brianschubert commentedon Aug 2, 2025
@pirate you can use
TypeVarfromtyping_extensions: https://pypi.org/project/typing-extensions/