microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.64k stars 12.44k forks source link

Typescript 4.2.x - incorrectly infered generic return type of a record union (extra undefined) #43943

Open TheEdward162 opened 3 years ago

TheEdward162 commented 3 years ago

Bug Report

🔎 Search Terms

undefined, generic inference, typescript 4.2

🕗 Version & Regression Information

4.2.0-beta - 4.3.0-dev.20210504 (everything since 4.2 beta, including all stable releases) NOT in 4.1.x or before

The return type inference of the the arrow function hasn't changed, according to the playground it was always infered as { kind: "failure"; value?: undefined; } | { kind: "success"; value: number; }. However, before 4.2. the type of the generic function above it (the andThen) was correctly narrowed down to AndThenResult<number>. This happened even without explicit type annotations, as one would expect.

In 4.2+ the undefined gets propagated into andThen<number | undefined> and this breaks the assignment (and my expectations).

⏯ Playground Link

Playground link with relevant code

💻 Code

// @strict: true
type AndThenResult<T> = { kind: 'success', value: T } | { kind: 'failure' };

function andThen<U>(
    fun: (_: number) => AndThenResult<U>
) {
    return fun(1)
}
//    V error here, type inference gets `AndThenResult<number | undefined>` from `andThen` in TS 4.2+
const a: AndThenResult<number> = andThen(
    // looks like this function infers { kind: "failure"; value?: undefined; } | { kind: "success"; value: number; } on any TS version in the playground
    // however the undefined only gets propagated up in 4.2+
    x => {
        if (x === 1) {
            return { kind: 'failure' }
        }
        return {
            kind: 'success',
            value: x
        }
    }
)

🙁 Actual behavior

The types don't match and the code doesn't compile. The return type of andThen(fn) is different than that expected on a.

🙂 Expected behavior

The types do match, the function return type is narrowed to AndThenResult<number> and nothing breaks.

typescript-bot commented 4 months ago

The change between v4.1.5 and v4.2.3 occurred at 22bee779d729547ca1ea90b1575f34a6f178ad21.

typescript-bot commented 4 months ago

:wave: Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript.


Issue body code block by @TheEdward162

:x: Failed: -

Historical Information
Version Reproduction Outputs
5.0.2, 5.1.3, 5.2.2, 5.3.2, 5.4.2

:x: Failed: -

  • Type 'AndThenResult' is not assignable to type 'AndThenResult'. Type '{ kind: "success"; value: number | undefined; }' is not assignable to type 'AndThenResult'. Type '{ kind: "success"; value: number | undefined; }' is not assignable to type '{ kind: "success"; value: number; }'. Types of property 'value' are incompatible. Type 'number | undefined' is not assignable to type 'number'. Type 'undefined' is not assignable to type 'number'.