@@ -296,8 +296,8 @@ namespace ts {
296
296
createPromiseType,
297
297
createArrayType,
298
298
getBooleanType: () => booleanType,
299
- getFalseType: () => falseType,
300
- getTrueType: () => trueType,
299
+ getFalseType: (fresh? ) => fresh ? falseType : regularFalseType ,
300
+ getTrueType: (fresh? ) => fresh ? trueType : regularTrueType ,
301
301
getVoidType: () => voidType,
302
302
getUndefinedType: () => undefinedType,
303
303
getNullType: () => nullType,
@@ -405,9 +405,22 @@ namespace ts {
405
405
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null");
406
406
const stringType = createIntrinsicType(TypeFlags.String, "string");
407
407
const numberType = createIntrinsicType(TypeFlags.Number, "number");
408
- const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false");
409
- const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true");
410
- const booleanType = createBooleanType([falseType, trueType]);
408
+ const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType;
409
+ const regularFalseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType;
410
+ const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType;
411
+ const regularTrueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType;
412
+ falseType.flags |= TypeFlags.FreshLiteral;
413
+ trueType.flags |= TypeFlags.FreshLiteral;
414
+ trueType.regularType = regularTrueType;
415
+ regularTrueType.freshType = trueType;
416
+ falseType.regularType = regularFalseType;
417
+ regularFalseType.freshType = falseType;
418
+ const booleanType = createBooleanType([regularFalseType, regularTrueType]);
419
+ // Also mark all combinations of fresh/regular booleans as "Boolean" so they print as `boolean` instead of `true | false`
420
+ // (The union is cached, so simply doing the marking here is sufficient)
421
+ createBooleanType([regularFalseType, trueType]);
422
+ createBooleanType([falseType, regularTrueType]);
423
+ createBooleanType([falseType, trueType]);
411
424
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
412
425
const voidType = createIntrinsicType(TypeFlags.Void, "void");
413
426
const neverType = createIntrinsicType(TypeFlags.Never, "never");
@@ -4173,7 +4186,7 @@ namespace ts {
4173
4186
const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(<LiteralType>t);
4174
4187
if (baseType.flags & TypeFlags.Union) {
4175
4188
const count = (<UnionType>baseType).types.length;
4176
- if (i + count <= types.length && types[i + count - 1] === ( <UnionType>baseType).types[count - 1]) {
4189
+ if (i + count <= types.length && getRegularTypeOfLiteralType( types[i + count - 1]) === getRegularTypeOfLiteralType(( <UnionType>baseType).types[count - 1]) ) {
4177
4190
result.push(baseType);
4178
4191
i += count - 1;
4179
4192
continue;
@@ -6160,7 +6173,7 @@ namespace ts {
6160
6173
if (type.flags & TypeFlags.UniqueESSymbol) {
6161
6174
return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
6162
6175
}
6163
- if (type.flags & TypeFlags.StringOrNumberLiteral ) {
6176
+ if (type.flags & ( TypeFlags.StringLiteral | TypeFlags.NumberLiteral) ) {
6164
6177
return escapeLeadingUnderscores("" + (<LiteralType>type).value);
6165
6178
}
6166
6179
return Debug.fail();
@@ -8813,7 +8826,7 @@ namespace ts {
8813
8826
t.flags & TypeFlags.StringLiteral && includes & TypeFlags.String ||
8814
8827
t.flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number ||
8815
8828
t.flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol ||
8816
- t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (<LiteralType>t).regularType);
8829
+ t.flags & TypeFlags.Literal && t.flags & TypeFlags.FreshLiteral && containsType(types, (<LiteralType>t).regularType);
8817
8830
if (remove) {
8818
8831
orderedRemoveItemAt(types, i);
8819
8832
}
@@ -9813,8 +9826,8 @@ namespace ts {
9813
9826
}
9814
9827
9815
9828
function getFreshTypeOfLiteralType(type: Type): Type {
9816
- if (type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral)) {
9817
- if (!(<LiteralType>type).freshType) {
9829
+ if (type.flags & TypeFlags.Literal && !(type.flags & TypeFlags.FreshLiteral)) {
9830
+ if (!(<LiteralType>type).freshType) { // NOTE: Safe because all freshable intrinsics always have fresh types already
9818
9831
const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (<LiteralType>type).value, (<LiteralType>type).symbol);
9819
9832
freshType.regularType = <LiteralType>type;
9820
9833
(<LiteralType>type).freshType = freshType;
@@ -9825,7 +9838,7 @@ namespace ts {
9825
9838
}
9826
9839
9827
9840
function getRegularTypeOfLiteralType(type: Type): Type {
9828
- return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType :
9841
+ return type.flags & TypeFlags.Literal && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType :
9829
9842
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) :
9830
9843
type;
9831
9844
}
@@ -11038,11 +11051,11 @@ namespace ts {
11038
11051
}
11039
11052
11040
11053
function isTypeRelatedTo(source: Type, target: Type, relation: Map<RelationComparisonResult>) {
11041
- if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) {
11042
- source = (<LiteralType >source).regularType;
11054
+ if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) {
11055
+ source = (<FreshableType >source).regularType;
11043
11056
}
11044
- if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) {
11045
- target = (<LiteralType >target).regularType;
11057
+ if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) {
11058
+ target = (<FreshableType >target).regularType;
11046
11059
}
11047
11060
if (source === target ||
11048
11061
relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
@@ -11197,11 +11210,11 @@ namespace ts {
11197
11210
* * Ternary.False if they are not related.
11198
11211
*/
11199
11212
function isRelatedTo(source: Type, target: Type, reportErrors = false, headMessage?: DiagnosticMessage): Ternary {
11200
- if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) {
11201
- source = (<LiteralType >source).regularType;
11213
+ if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) {
11214
+ source = (<FreshableType >source).regularType;
11202
11215
}
11203
- if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) {
11204
- target = (<LiteralType >target).regularType;
11216
+ if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) {
11217
+ target = (<FreshableType >target).regularType;
11205
11218
}
11206
11219
if (source.flags & TypeFlags.Substitution) {
11207
11220
source = relation === definitelyAssignableRelation ? (<SubstitutionType>source).typeVariable : (<SubstitutionType>source).substitute;
@@ -12769,7 +12782,7 @@ namespace ts {
12769
12782
return type.flags & TypeFlags.EnumLiteral && type.flags & TypeFlags.FreshLiteral ? getBaseTypeOfEnumLiteralType(<LiteralType>type) :
12770
12783
type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType :
12771
12784
type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType :
12772
- type.flags & TypeFlags.BooleanLiteral ? booleanType :
12785
+ type.flags & TypeFlags.BooleanLiteral && type.flags & TypeFlags.FreshLiteral ? booleanType :
12773
12786
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getWidenedLiteralType)) :
12774
12787
type;
12775
12788
}
@@ -12823,7 +12836,7 @@ namespace ts {
12823
12836
return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((<UnionType>type).types) :
12824
12837
type.flags & TypeFlags.StringLiteral ? (<LiteralType>type).value === "" ? TypeFlags.StringLiteral : 0 :
12825
12838
type.flags & TypeFlags.NumberLiteral ? (<LiteralType>type).value === 0 ? TypeFlags.NumberLiteral : 0 :
12826
- type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 :
12839
+ type.flags & TypeFlags.BooleanLiteral ? ( type === falseType || type === regularFalseType) ? TypeFlags.BooleanLiteral : 0 :
12827
12840
type.flags & TypeFlags.PossiblyFalsy;
12828
12841
}
12829
12842
@@ -12840,7 +12853,8 @@ namespace ts {
12840
12853
function getDefinitelyFalsyPartOfType(type: Type): Type {
12841
12854
return type.flags & TypeFlags.String ? emptyStringType :
12842
12855
type.flags & TypeFlags.Number ? zeroType :
12843
- type.flags & TypeFlags.Boolean || type === falseType ? falseType :
12856
+ type.flags & TypeFlags.Boolean || type === regularFalseType ? regularFalseType :
12857
+ type === falseType ? falseType :
12844
12858
type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null) ||
12845
12859
type.flags & TypeFlags.StringLiteral && (<LiteralType>type).value === "" ||
12846
12860
type.flags & TypeFlags.NumberLiteral && (<LiteralType>type).value === 0 ? type :
@@ -14095,7 +14109,10 @@ namespace ts {
14095
14109
if (assignedType.flags & TypeFlags.Never) {
14096
14110
return assignedType;
14097
14111
}
14098
- const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
14112
+ let reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
14113
+ if (assignedType.flags & (TypeFlags.FreshLiteral | TypeFlags.Literal)) {
14114
+ reducedType = mapType(reducedType, getFreshTypeOfLiteralType); // Ensure that if the assignment is a fresh type, that we narrow to fresh types
14115
+ }
14099
14116
// Our crude heuristic produces an invalid result in some cases: see GH#26130.
14100
14117
// For now, when that happens, we give up and don't narrow at all. (This also
14101
14118
// means we'll never narrow for erroneous assignments where the assigned type
@@ -14148,8 +14165,8 @@ namespace ts {
14148
14165
}
14149
14166
if (flags & TypeFlags.BooleanLike) {
14150
14167
return strictNullChecks ?
14151
- type === falseType ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts :
14152
- type === falseType ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
14168
+ ( type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts :
14169
+ ( type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts;
14153
14170
}
14154
14171
if (flags & TypeFlags.Object) {
14155
14172
return isFunctionObjectType(<ObjectType>type) ?
@@ -28381,19 +28398,20 @@ namespace ts {
28381
28398
function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean {
28382
28399
if (isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node)) {
28383
28400
const type = getTypeOfSymbol(getSymbolOfNode(node));
28384
- return !!(type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral);
28401
+ return !!(type.flags & TypeFlags.Literal && type.flags & TypeFlags.FreshLiteral);
28385
28402
}
28386
28403
return false;
28387
28404
}
28388
28405
28389
- function literalTypeToNode(type: LiteralType, enclosing: Node): Expression {
28390
- const enumResult = type.flags & TypeFlags.EnumLiteral && nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing);
28391
- return enumResult || createLiteral(type.value);
28406
+ function literalTypeToNode(type: FreshableType, enclosing: Node): Expression {
28407
+ const enumResult = type.flags & TypeFlags.EnumLiteral ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing)
28408
+ : type === trueType ? createTrue() : type === falseType && createFalse();
28409
+ return enumResult || createLiteral((type as LiteralType).value);
28392
28410
}
28393
28411
28394
28412
function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration) {
28395
28413
const type = getTypeOfSymbol(getSymbolOfNode(node));
28396
- return literalTypeToNode(<LiteralType >type, node);
28414
+ return literalTypeToNode(<FreshableType >type, node);
28397
28415
}
28398
28416
28399
28417
function createResolver(): EmitResolver {
@@ -29765,7 +29783,7 @@ namespace ts {
29765
29783
29766
29784
function checkAmbientInitializer(node: VariableDeclaration | PropertyDeclaration | PropertySignature) {
29767
29785
if (node.initializer) {
29768
- const isInvalidInitializer = !(isStringOrNumberLiteralExpression(node.initializer) || isSimpleLiteralEnumReference(node.initializer));
29786
+ const isInvalidInitializer = !(isStringOrNumberLiteralExpression(node.initializer) || isSimpleLiteralEnumReference(node.initializer) || node.initializer.kind === SyntaxKind.TrueKeyword || node.initializer.kind === SyntaxKind.FalseKeyword );
29769
29787
const isConstOrReadonly = isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node);
29770
29788
if (isConstOrReadonly && !node.type) {
29771
29789
if (isInvalidInitializer) {
0 commit comments