A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/microsoft/TypeScript/issues/29133 below:

Referencing ReturnType<FooT> in generic param, and passing a function that has one param causes incorrect type inference... · Issue #29133 · microsoft/TypeScript · GitHub

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,

  1. ReturnType<FooT> is used in a generic param constraint
  2. The concrete type of FooT 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