Skip to content

narrowing is lost at creating literals #21436

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
zpdDG4gta8XKpMCd opened this issue Jan 27, 2018 · 4 comments
Closed

narrowing is lost at creating literals #21436

zpdDG4gta8XKpMCd opened this issue Jan 27, 2018 · 4 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@zpdDG4gta8XKpMCd
Copy link

zpdDG4gta8XKpMCd commented Jan 27, 2018

interface A { isIt: true; text: string; }
interface B { isIt: false; value: number; }
type C = A | B;
const isIt = Math.random() > 0.5;
const c : C = isIt ? { isIt, text: 'hey' } : { isIt, value: 123 }; /* <-- expected to work, actual:
Type '{ isIt: boolean; text: string; } | { isIt: boolean; value: number; }' is not assignable to type 'C'.
  Type '{ isIt: boolean; text: string; }' is not assignable to type 'C'.
    Type '{ isIt: boolean; text: string; }' is not assignable to type 'B'.
      Property 'value' is missing in type '{ isIt: boolean; text: string; }'.
*/

the following works tho:

const c : C = isIt ? { isIt: isIt, text: 'hey' } : { isIt: isIt, value: 123 };
@DanielRosenwasser
Copy link
Member

It's extremely strange to me that quick info seems to narrow isIt to true in the true branch, but doesn't narrow at all in the false branch.

@DanielRosenwasser DanielRosenwasser added the Bug A bug in TypeScript label Jan 27, 2018
@DanielRosenwasser DanielRosenwasser added this to the TypeScript 2.8 milestone Jan 27, 2018
@jack-williams
Copy link
Collaborator

jack-williams commented Jan 30, 2018

@DanielRosenwasser I believe you get the correct narrowing behavior with strictNullChecks enabled. What would be the expected behavior with strictNullChecks off?

@weswigham
Copy link
Member

weswigham commented Jan 30, 2018

@ahejlsberg You left a comment inside isLiteralOfContextualType to the effect that this behavior is intended:

                    // If the contextual type is a union containing both of the 'true' and 'false' types we
                    // don't consider it a literal context for boolean literals.

is there a motivating example for this, or can the exception for booleans be removed?

@ahejlsberg
Copy link
Member

@weswigham As I recall it had to do with destructuring an object literal that specifies the value true for a property and at the same time specifices false as the destructuring default. You could try to remove it and see what baseline effects it has.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

6 participants