From e6efb15a53f74b6c0fbb363564d8144c8d8a4bf7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 24 Sep 2016 08:09:06 -0700 Subject: [PATCH] Lazily create fresh literal types --- src/compiler/checker.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 54a28528da7..092ef8e4e6b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5440,7 +5440,7 @@ namespace ts { const remove = t.flags & TypeFlags.StringLiteral && types.containsString || t.flags & TypeFlags.NumberLiteral && types.containsNumber || - t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && i > 0 && types[i - 1] === (t).regularType; + t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral && containsType(types, (t).regularType); if (remove) { orderedRemoveItemAt(types, i); } @@ -5579,15 +5579,20 @@ namespace ts { function createLiteralType(flags: TypeFlags, text: string) { const type = createType(flags); - const freshType = createType(flags | TypeFlags.FreshLiteral); - type.text = freshType.text = text; - type.freshType = freshType; - freshType.regularType = type; + type.text = text; return type; } function getFreshTypeOfLiteralType(type: Type) { - return type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral) ? (type).freshType : type; + if (type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral)) { + if (!(type).freshType) { + const freshType = createLiteralType(type.flags | TypeFlags.FreshLiteral, (type).text); + freshType.regularType = type; + (type).freshType = freshType; + } + return (type).freshType; + } + return type; } function getRegularTypeOfLiteralType(type: Type) { @@ -6328,10 +6333,10 @@ namespace ts { } function isTypeRelatedTo(source: Type, target: Type, relation: Map) { - if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) { + if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { source = (source).regularType; } - if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) { + if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { target = (target).regularType; } if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { @@ -6431,10 +6436,10 @@ namespace ts { // Ternary.False if they are not related. function isRelatedTo(source: Type, target: Type, reportErrors?: boolean, headMessage?: DiagnosticMessage): Ternary { let result: Ternary; - if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) { + if (source.flags & TypeFlags.StringOrNumberLiteral && source.flags & TypeFlags.FreshLiteral) { source = (source).regularType; } - if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) { + if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { target = (target).regularType; } // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases