TypeScript Version: 3.3.0-dev.20181129
Search Terms: ReturnType, Generic Param, Generic Function Argument
Code
//Innocent enough. //Take a T, return a T type Foo<T extends number> = (t: T) => T; //=== NOT using ReturnType<FooT> in Generic Parameters == declare function bar< T extends number, FooT extends Foo<T> >(t: T, foo: FooT): ReturnType<FooT> //OK! `barResult` is of type `3` const barResult = bar( 3 as (3|5), () => 3 ); //OK! `barResult2` is of type `3` const barResult2 = bar( 3 as (3|5), //`t` is of type `3|5` //Return type is 3 t => 3 ); //=== Using ReturnType<FooT> in Generic Parameters == declare function baz< T extends number, FooT extends Foo<T>, //The same as bar<> but we reference ReturnType<FooT> here Ret extends ReturnType<FooT> >(t: T, foo: FooT, ret: Ret): ReturnType<FooT> //OK! `bazResult` is of type `3` const bazResult = baz( 3 as (3|5), () => 3, 3 ); //NOT OK! `bazResult2` is of type `3|5`! const bazResult2 = baz( 3 as (3|5), //`t` is of type `3|5` //Return type is `3` t => 3, 3 ); //NOT OK! `bazResult3` is of type `3|5`! const bazResult3 = baz( 3 as (3|5), //`t` is of type `3|5` //Return type is `3` //We *force* the return type to be 3 (t) : 3 => (3 as 3), 3 );
Expected behavior:
bazResult2
and bazResult3
should be of type 3
, the same as bazResult
Actual behavior:
bazResult2
and bazResult3
are of type 3|5
, different from bazResult
(which is of type 3
)
The difference between bazResult
and bazResult2
is literally 3 characters but it causes the inferred types to be very different.
Playground Link: Here
I don't even know how to describe this...
My real use case is more complicated than the above example but I need the return type of a generic function to be inferred correctly to perform stronger compile-time type checks.
The strange thing is that () => 3
will give me the correct return type, but t => 3
will not.
In my own code, using the argument t
is absolutely necessary.
As far as I've seen, this problem only occurs both the following are true,
ReturnType<FooT>
is used in a generic param constraintFooT
has parameters (Like t => 3
has parameters, () => 3
does not)If either of the above are false, this problem does not occur
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4