Skip to content
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

Fix boolean literal types #10577

Merged
merged 4 commits into from
Sep 9, 2016
Merged

Fix boolean literal types #10577

merged 4 commits into from
Sep 9, 2016

Conversation

ahejlsberg
Copy link
Member

Fixes #10432.

This PR introduces two changes:

  • When an expression has the contextual type boolean we now consider it a literal type context. Previously we specifically excluded this case.
  • When a binding element has a default value, we now give it a union type of the destructured type and the default type. Previously we'd give it only the destructured type and require the default type to be assignable to the destructured type.

Some background on the changes.

Since boolean is identical to the union type true | false, when an expression has the contextual type boolean we really should consider it a literal type context (because the contextual type is a union of unit types). Before this PR we specifically excluded that case in the name of backwards compatibility. With the fix we no longer do. However, that causes another issue to appear:

let { x = true } = { x: cond ? false : undefined };

In the example above, the expression cond ? false : undefined is contextually typed by type boolean because of the default value on the left hand side. That causes us to consider the expression a literal type context, and we therefore use type false for the false literal. So, the type of x on the right hand side becomes false | undefined. Now, when we destructure x we require the default value to be of a type assignable to false | undefined. But boolean isn't.

The issue really is that when a binding element has a default value, we ought to give it a union type of the destructuring type and the default type. With this PR we do. The downside is that you might sometimes end up with a union type when an error might have been more appropriate.

@mhegazy @DanielRosenwasser You might want to take a look.

}
function h({ prop = "baz" }: StringUnion) {}
>h : ({prop}: StringUnion) => void
>prop : "foo" | "bar" | "baz"
Copy link
Member

@DanielRosenwasser DanielRosenwasser Aug 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initializer is completely ignoring the type annotation in this case. I would say this is undesirable.

@ahejlsberg
Copy link
Member Author

@mhegazy Want to take a look? I think we need this one in 2.0.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 9, 2016

👍

@ahejlsberg ahejlsberg merged commit 8b1acf6 into master Sep 9, 2016
@ahejlsberg ahejlsberg deleted the fixBooleanLiteralTypes branch September 9, 2016 17:58
@mhegazy
Copy link
Contributor

mhegazy commented Sep 9, 2016

merged in release-2.0 in 2cd4d20

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: Boolean type literals misbehaving
4 participants