-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Number, enum, and boolean literal types #9407
Conversation
What about ("foo" === "bar"); // is this an error in this case, since a literal
// is inferred as a literal type at that location? These are similar to the "this branch is always true"/false warnings you'd get in some languages (which we now have more of with |
Comments based on my experience testing my PR (which you should steal tests from): I don't see any Are equivalent numbers with different text equivalent, eg |
@weswigham Unless someone has a compelling scenario, I'm strongly inclined not to include Yes, I'll look at poaching some tests. |
# Conflicts: # src/compiler/checker.ts
The RWC baseline differences look good except for a few cases where our optimistic control flow analysis is fooled by hidden side effects in function calls. We're discussing that in #9998. Otherwise I think we're finally ready to merge this PR. |
🎉 thank you for the hard work! |
it is a 2.0-RC feature. added milestone. and updated the roadmap. |
This PR expands upon #9163 by implementing number, enum, and boolean literal types and adding more comprehensive checking and type guard constructs for literal types. The PR supercedes #6196 and #7480, and fixes #2983, #6149, #6155, #7447, and #7642.
It is now possible to use string, numeric, and boolean literals (
true
andfalse
) as literal types:The predefined
boolean
type is now equivalent to the union typetrue | false
.When each member of an enum type has either an automatically assigned value, an initializer that specifies a numeric literal, or an initializer that specifies a single identifier naming another enum member, that enum type is considered a union enum type. The members of a union enum type can be used both as constants and as types, and the enum type is equivalent to a union of the declared member types.
All literal types as well as the
null
andundefined
types are considered unit types. A unit type is a type that has only a single value.Literal types have the following type relationships:
string
.number
.true
andfalse
are subtypes of and assignable to typeboolean
.Certain expression locations are now considered literal type locations. In a literal type location, a literal expression has a literal type (e.g.
"hello"
,0
,true
,ShapeKind.Circle
) instead of a regular type (e.g.string
,number
,boolean
,ShapeKind
). The following expression locations are considered literal type locations:===
,!==
,==
, and!=
operators.case
clause of aswitch
statement.?:
) in a literal type location.When both operands of
===
,!==
,==
, or!=
are unit types or unions of unit types, the operands are checked using those types and an error is reported if the types are not comparable. Otherwise the operands are checked with their full types.The equality comparison operators now narrow each operand based on the type of the other operand. For example:
When all
case
expressions in aswitch
statement have unit types, theswitch
expression variable is narrowed in eachcase
block and in thedefault
block based on the listed cases. For example:For an equality, truthiness, or switch type guard on a reference
x.y
, we not only narrowx.y
but also narrowx
itself based on the narrowed type ofx.y
. For example:The
&&
and||
operators now understand that0
,false
, and""
are falsy unit types and stricter typing of these operators is implemented as described here.