Skip to content

undefined type from optional chaining doesn't produce correct generic inference candidate from union #34579

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
RyanCavanaugh opened this issue Oct 18, 2019 · 3 comments · Fixed by #34588
Assignees
Labels
Bug A bug in TypeScript

Comments

@RyanCavanaugh
Copy link
Member

TypeScript Version: 10/18/2019 nightly

Search Terms: optional chaining generic inference undefined

Code

declare function unbox<T>(box: { value: T | undefined }): T;
declare const su: string | undefined;

const b1 = { value: su?.length };
// Incorrect error - T inferred to be number | undefined
const v1: number = unbox(b1);

// No error
const b2 = { value: su?.length as number | undefined };
const v2: number = unbox(b2);

// No error
const b3: { value: number | undefined } = { value: su?.length  };
const v3: number = unbox(b3);

Expected behavior: In all cases, T should be inferred to be number

Actual behavior: When the undefined part of the union of the type of value originates in an optional chaining, it doesn't infer correctly

Playground Link: http://www.typescriptlang.org/play/?ts=Nightly&ssl=1&ssc=1&pln=15&pc=1#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXzQCMcAPAHgBUA+ACmJIC54BveANygmRCYvgB8CqUIiyoQweAF8AlLwDcAWABQoSLARg8AZwzxtyJrphiA5gKEixEpcpVbUu+IQCM8ALwt2nbkeQB+ADoIEFRTDAALaVsAehj4AEl0HBg4THgQVJT4AFp4PjFETLhJDBxnBFRkAFtCTIs0K3Fgex09NhcmKtr6zyJSOhcZWxU4+AA5cuKU1sc9QgAmDy8OLh59AODQ8KiobXhuupgG4RBRZujZpzYFrpqj5f6SOgXhlVH4yYysmCv5gGYmKxVr4Dvd6oJGmdrJIpMtgT51gYgiEwpF4JdlA5roCwT1jn1UPQ6P83sogA (nightly link)

Related Issues: Nope

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Oct 18, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.7.2 milestone Oct 18, 2019
@RyanCavanaugh
Copy link
Member Author

cc @rbuckton who was looking at this with us

@JannesMeyer
Copy link

I think I've come across the same issue. This is my code:

let values = { a: 1 } as { a: number } | undefined;

let a = values?.a;
assertDefined(a); // This does not narrow the type to number
console.log(a.toString()); // Error: Object is possibly undefined

function assertDefined<T>(x: T | undefined | null): asserts x is T {
    if (x == null) {
        throw new Error('Expected a value');
    }
}

Playground link

@rosslovas
Copy link

rosslovas commented Nov 6, 2019

This is in the 3.7.2 milestone but the fix didn't actually make it in (playground link). Would be good to get this in 3.7.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
4 participants