From 7d4a18766cc7f2b75b90ec0d5ce7a465cffeace2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 23 Sep 2016 09:30:50 -0700 Subject: [PATCH 01/12] Track freshness of string and numeric literals --- src/compiler/checker.ts | 97 +++++++++++++++++++++++++++++++---------- src/compiler/types.ts | 12 +++-- 2 files changed, 82 insertions(+), 27 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51550ef873fc5..773b6acbfabc2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3838,6 +3838,14 @@ namespace ts { return true; } + function createEnumLiteralType(symbol: Symbol, baseType: EnumType, text: string) { + const type = createType(TypeFlags.EnumLiteral); + type.symbol = symbol; + type.baseType = baseType; + type.text = text; + return type; + } + function getDeclaredTypeOfEnum(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { @@ -3853,10 +3861,7 @@ namespace ts { const memberSymbol = getSymbolOfNode(member); const value = getEnumMemberValue(member); if (!memberTypes[value]) { - const memberType = memberTypes[value] = createType(TypeFlags.EnumLiteral); - memberType.symbol = memberSymbol; - memberType.baseType = enumType; - memberType.text = "" + value; + const memberType = memberTypes[value] = createEnumLiteralType(memberSymbol, enumType, "" + value); memberTypeList.push(memberType); } } @@ -5335,6 +5340,7 @@ namespace ts { containsUndefined?: boolean; containsNull?: boolean; containsNonWideningType?: boolean; + containsStringOrNumberLiteral?: boolean; } function binarySearchTypes(types: Type[], type: Type): number { @@ -5374,6 +5380,7 @@ namespace ts { if (!(type.flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true; } else if (!(type.flags & TypeFlags.Never)) { + if (type.flags & TypeFlags.StringOrNumberLiteral) typeSet.containsStringOrNumberLiteral = true; const len = typeSet.length; const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type); if (index < 0) { @@ -5420,6 +5427,19 @@ namespace ts { } } + function removeFreshLiteralTypes(types: Type[]) { + let i = types.length; + while (i > 1) { + i--; + const t = types[i]; + if (t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral) { + if (types[i - 1] === (t).regularType) { + orderedRemoveItemAt(types, i); + } + } + } + } + // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction // flag is specified we also reduce the constituent type set to only include types that aren't subtypes // of other types. Subtype reduction is expensive for large union types and is possible only when union @@ -5442,6 +5462,9 @@ namespace ts { if (subtypeReduction) { removeSubtypes(typeSet); } + else if (typeSet.containsStringOrNumberLiteral) { + removeFreshLiteralTypes(typeSet); + } if (typeSet.length === 0) { return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType : typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType : @@ -5549,10 +5572,21 @@ namespace ts { function createLiteralType(flags: TypeFlags, text: string) { const type = createType(flags); - type.text = text; + const freshType = createType(flags | TypeFlags.FreshLiteral); + type.text = freshType.text = text; + type.freshType = freshType; + freshType.regularType = type; return type; } + function getFreshTypeOfLiteralType(type: Type) { + return type.flags & TypeFlags.StringOrNumberLiteral && !(type.flags & TypeFlags.FreshLiteral) ? (type).freshType : type; + } + + function getRegularTypeOfLiteralType(type: Type) { + return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (type).regularType : type; + } + function getLiteralTypeForText(flags: TypeFlags, text: string) { const map = flags & TypeFlags.StringLiteral ? stringLiteralTypes : numericLiteralTypes; return map[text] || (map[text] = createLiteralType(flags, text)); @@ -5561,7 +5595,7 @@ namespace ts { function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = checkExpression(node.literal); + links.resolvedType = getRegularTypeOfLiteralType(checkExpression(node.literal)); } return links.resolvedType; } @@ -6273,7 +6307,7 @@ namespace ts { if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true; if (source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.EnumLiteral && - (source).text === (target).text && + (source).text === (target).text && isEnumTypeRelatedTo((source).baseType, (target).baseType, errorReporter)) { return true; } @@ -6287,6 +6321,12 @@ namespace ts { } function isTypeRelatedTo(source: Type, target: Type, relation: Map) { + if (source.flags & TypeFlags.Literal && source.flags & TypeFlags.FreshLiteral) { + source = (source).regularType; + } + if (target.flags & TypeFlags.Literal && target.flags & TypeFlags.FreshLiteral) { + target = (target).regularType; + } if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } @@ -6384,6 +6424,12 @@ 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) { + source = (source).regularType; + } + if (target.flags & TypeFlags.Literal && 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 if (source === target) return Ternary.True; @@ -6393,7 +6439,7 @@ namespace ts { if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True; - if (source.flags & TypeFlags.FreshObjectLiteral) { + if (source.flags & TypeFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) { if (hasExcessProperties(source, target, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, target); @@ -7323,8 +7369,8 @@ namespace ts { // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type: Type): TypeFlags { return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((type).types) : - type.flags & TypeFlags.StringLiteral ? type === emptyStringType ? TypeFlags.StringLiteral : 0 : - type.flags & TypeFlags.NumberLiteral ? type === zeroType ? TypeFlags.NumberLiteral : 0 : + type.flags & TypeFlags.StringLiteral ? (type).text === "" ? TypeFlags.StringLiteral : 0 : + type.flags & TypeFlags.NumberLiteral ? (type).text === "0" ? TypeFlags.NumberLiteral : 0 : type.flags & TypeFlags.BooleanLiteral ? type === falseType ? TypeFlags.BooleanLiteral : 0 : type.flags & TypeFlags.PossiblyFalsy; } @@ -7391,7 +7437,7 @@ namespace ts { * Leave signatures alone since they are not subject to the check. */ function getRegularTypeOfObjectLiteral(type: Type): Type { - if (!(type.flags & TypeFlags.FreshObjectLiteral)) { + if (!(type.flags & TypeFlags.ObjectLiteral && type.flags & TypeFlags.FreshLiteral)) { return type; } const regularType = (type).regularType; @@ -7407,7 +7453,7 @@ namespace ts { resolved.constructSignatures, resolved.stringIndexInfo, resolved.numberIndexInfo); - regularNew.flags = resolved.flags & ~TypeFlags.FreshObjectLiteral; + regularNew.flags = resolved.flags & ~TypeFlags.FreshLiteral; (type).regularType = regularNew; return regularNew; } @@ -8109,14 +8155,14 @@ namespace ts { } if (flags & TypeFlags.StringLiteral) { return strictNullChecks ? - type === emptyStringType ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : - type === emptyStringType ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; + (type).text === "" ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : + (type).text === "" ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; } if (flags & (TypeFlags.Number | TypeFlags.Enum)) { return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts; } if (flags & (TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) { - const isZero = type === zeroType || type.flags & TypeFlags.EnumLiteral && (type).text === "0"; + const isZero = (type).text === "0"; return strictNullChecks ? isZero ? TypeFacts.ZeroStrictFacts : TypeFacts.NonZeroStrictFacts : isZero ? TypeFacts.ZeroFacts : TypeFacts.NonZeroFacts; @@ -8289,7 +8335,7 @@ namespace ts { function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) { if (clause.kind === SyntaxKind.CaseClause) { - const caseType = checkExpression((clause).expression); + const caseType = getRegularTypeOfLiteralType(checkExpression((clause).expression)); return isUnitType(caseType) ? caseType : undefined; } return neverType; @@ -8670,7 +8716,11 @@ namespace ts { const narrowedType = filterType(type, t => areTypesComparable(t, valueType)); return narrowedType.flags & TypeFlags.Never ? type : narrowedType; } - return isUnitType(valueType) ? filterType(type, t => t !== valueType) : type; + if (isUnitType(valueType)) { + const regularType = getRegularTypeOfLiteralType(valueType); + return filterType(type, t => getRegularTypeOfLiteralType(t) !== regularType); + } + return type; } function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type { @@ -8715,7 +8765,7 @@ namespace ts { if (!hasDefaultClause) { return caseType; } - const defaultType = filterType(type, t => !(isUnitType(t) && contains(switchTypes, t))); + const defaultType = filterType(type, t => !(isUnitType(t) && contains(switchTypes, getRegularTypeOfLiteralType(t)))); return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); } @@ -10289,7 +10339,7 @@ namespace ts { const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.String) : undefined; const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.Number) : undefined; const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); - const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshObjectLiteral; + const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral; result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags) | (patternWithComputedProperties ? TypeFlags.ObjectLiteralPatternWithComputedProperties : 0); if (inDestructuringPattern) { result.pattern = node; @@ -13682,12 +13732,13 @@ namespace ts { } switch (node.kind) { case SyntaxKind.StringLiteral: - return getLiteralTypeForText(TypeFlags.StringLiteral, (node).text); + return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.StringLiteral, (node).text)); case SyntaxKind.NumericLiteral: - return getLiteralTypeForText(TypeFlags.NumberLiteral, (node).text); + return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.NumberLiteral, (node).text)); case SyntaxKind.TrueKeyword: + return trueType; case SyntaxKind.FalseKeyword: - return node.kind === SyntaxKind.TrueKeyword ? trueType : falseType; + return falseType; } } @@ -18472,7 +18523,7 @@ namespace ts { if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) { expr = expr.parent; } - return checkExpression(expr); + return getRegularTypeOfLiteralType(checkExpression(expr)); } /** diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e4bc9a29d5b03..8b5b2f1f25fba 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2372,7 +2372,7 @@ namespace ts { /* @internal */ ObjectLiteral = 1 << 23, // Originates in an object literal /* @internal */ - FreshObjectLiteral = 1 << 24, // Fresh object literal type + FreshLiteral = 1 << 24, // Fresh literal type /* @internal */ ContainsWideningType = 1 << 25, // Type is or contains undefined or null widening type /* @internal */ @@ -2385,6 +2385,7 @@ namespace ts { /* @internal */ Nullable = Undefined | Null, Literal = StringLiteral | NumberLiteral | BooleanLiteral | EnumLiteral, + StringOrNumberLiteral = StringLiteral | NumberLiteral, /* @internal */ DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null, PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean, @@ -2426,12 +2427,15 @@ namespace ts { /* @internal */ // Intrinsic types (TypeFlags.Intrinsic) export interface IntrinsicType extends Type { - intrinsicName: string; // Name of intrinsic type + intrinsicName: string; // Name of intrinsic type } // String literal types (TypeFlags.StringLiteral) + // Numeric literal types (TypeFlags.NumberLiteral) export interface LiteralType extends Type { - text: string; // Text of string literal + text: string; // Text of literal + freshType?: LiteralType; // Fresh version of type + regularType?: LiteralType; // Regular version of type } // Enum types (TypeFlags.Enum) @@ -2441,7 +2445,7 @@ namespace ts { // Enum types (TypeFlags.EnumLiteral) export interface EnumLiteralType extends LiteralType { - baseType: EnumType & UnionType; + baseType: EnumType & UnionType; // Base enum type } // Object types (TypeFlags.ObjectType) From a3c18b4a103165d06525061d110a723d92d64b4a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 23 Sep 2016 16:06:25 -0700 Subject: [PATCH 02/12] Only widen fresh literal types --- src/compiler/checker.ts | 64 +++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 773b6acbfabc2..01c5642c7d4c6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5340,6 +5340,8 @@ namespace ts { containsUndefined?: boolean; containsNull?: boolean; containsNonWideningType?: boolean; + containsString?: boolean; + containsNumber?: boolean; containsStringOrNumberLiteral?: boolean; } @@ -5368,23 +5370,26 @@ namespace ts { } function addTypeToUnion(typeSet: TypeSet, type: Type) { - if (type.flags & TypeFlags.Union) { + const flags = type.flags; + if (flags & TypeFlags.Union) { addTypesToUnion(typeSet, (type).types); } - else if (type.flags & TypeFlags.Any) { + else if (flags & TypeFlags.Any) { typeSet.containsAny = true; } - else if (!strictNullChecks && type.flags & TypeFlags.Nullable) { - if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true; - if (type.flags & TypeFlags.Null) typeSet.containsNull = true; - if (!(type.flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true; + else if (!strictNullChecks && flags & TypeFlags.Nullable) { + if (flags & TypeFlags.Undefined) typeSet.containsUndefined = true; + if (flags & TypeFlags.Null) typeSet.containsNull = true; + if (!(flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true; } - else if (!(type.flags & TypeFlags.Never)) { - if (type.flags & TypeFlags.StringOrNumberLiteral) typeSet.containsStringOrNumberLiteral = true; + else if (!(flags & TypeFlags.Never)) { + if (flags & TypeFlags.String) typeSet.containsString = true; + if (flags & TypeFlags.Number) typeSet.containsNumber = true; + if (flags & TypeFlags.StringOrNumberLiteral) typeSet.containsStringOrNumberLiteral = true; const len = typeSet.length; const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type); if (index < 0) { - if (!(type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { + if (!(flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { typeSet.splice(~index, 0, type); } } @@ -5417,7 +5422,7 @@ namespace ts { return false; } - function removeSubtypes(types: Type[]) { + function removeSubtypes(types: TypeSet) { let i = types.length; while (i > 0) { i--; @@ -5427,15 +5432,17 @@ namespace ts { } } - function removeFreshLiteralTypes(types: Type[]) { + function removeRedundantLiteralTypes(types: TypeSet) { let i = types.length; - while (i > 1) { + while (i > 0) { i--; const t = types[i]; - if (t.flags & TypeFlags.StringOrNumberLiteral && t.flags & TypeFlags.FreshLiteral) { - if (types[i - 1] === (t).regularType) { - orderedRemoveItemAt(types, i); - } + 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; + if (remove) { + orderedRemoveItemAt(types, i); } } } @@ -5463,7 +5470,7 @@ namespace ts { removeSubtypes(typeSet); } else if (typeSet.containsStringOrNumberLiteral) { - removeFreshLiteralTypes(typeSet); + removeRedundantLiteralTypes(typeSet); } if (typeSet.length === 0) { return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType : @@ -7348,6 +7355,15 @@ namespace ts { type; } + function getWidenedLiteralType(type: Type): Type { + return type.flags & TypeFlags.StringLiteral && type.flags & TypeFlags.FreshLiteral ? stringType : + type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType : + type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.EnumLiteral ? (type).baseType : + type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(map((type).types, getWidenedLiteralType)) : + type; + } + /** * Check if a Type was written as a tuple type literal. * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. @@ -7904,7 +7920,7 @@ namespace ts { const widenLiteralTypes = context.inferences[index].topLevel && !hasPrimitiveConstraint(signature.typeParameters[index]) && (context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index])); - const baseInferences = widenLiteralTypes ? map(inferences, getBaseTypeOfLiteralType) : inferences; + const baseInferences = widenLiteralTypes ? map(inferences, getWidenedLiteralType) : inferences; // Infer widened union or supertype, or the unknown type for no common supertype const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; @@ -9600,14 +9616,14 @@ namespace ts { if (parameter.dotDotDotToken) { const restTypes: Type[] = []; for (let i = indexOfParameter; i < iife.arguments.length; i++) { - restTypes.push(getBaseTypeOfLiteralType(checkExpression(iife.arguments[i]))); + restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i]))); } return createArrayType(getUnionType(restTypes)); } const links = getNodeLinks(iife); const cached = links.resolvedSignature; links.resolvedSignature = anySignature; - const type = getBaseTypeOfLiteralType(checkExpression(iife.arguments[indexOfParameter])); + const type = getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter])); links.resolvedSignature = cached; return type; } @@ -12709,7 +12725,7 @@ namespace ts { reportErrorsFromWidening(func, type); } if (isUnitType(type) && !(contextualSignature && isLiteralContextualType(getReturnTypeOfSignature(contextualSignature)))) { - type = getBaseTypeOfLiteralType(type); + type = getWidenedLiteralType(type); } const widenedType = getWidenedType(type); @@ -13093,7 +13109,7 @@ namespace ts { return silentNeverType; } if (node.operator === SyntaxKind.MinusToken && node.operand.kind === SyntaxKind.NumericLiteral) { - return getLiteralTypeForText(TypeFlags.NumberLiteral, "" + -(node.operand).text); + return getFreshTypeOfLiteralType(getLiteralTypeForText(TypeFlags.NumberLiteral, "" + -(node.operand).text)); } switch (node.operator) { case SyntaxKind.PlusToken: @@ -13786,7 +13802,7 @@ namespace ts { const type = checkExpressionCached(declaration.initializer); return getCombinedNodeFlags(declaration) & NodeFlags.Const || getCombinedModifierFlags(declaration) & ModifierFlags.Readonly || - isTypeAssertion(declaration.initializer) ? type : getBaseTypeOfLiteralType(type); + isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); } function isLiteralContextualType(contextualType: Type) { @@ -13808,7 +13824,7 @@ namespace ts { function checkExpressionForMutableLocation(node: Expression, contextualMapper?: TypeMapper): Type { const type = checkExpression(node, contextualMapper); - return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getBaseTypeOfLiteralType(type); + return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type); } function checkPropertyAssignment(node: PropertyAssignment, contextualMapper?: TypeMapper): Type { From b9adef6416a088ee9d3180a077660f84c8624845 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 23 Sep 2016 16:07:59 -0700 Subject: [PATCH 03/12] Accept new baselines --- .../reference/numericLiteralTypes1.types | 10 ++-- .../reference/numericLiteralTypes2.types | 12 ++--- ...lTypesAndLogicalOrExpressions01.errors.txt | 5 +- ...ngLiteralTypesAndLogicalOrExpressions01.js | 2 +- ...LiteralTypesAsTypeParameterConstraint01.js | 6 +-- ...eralTypesAsTypeParameterConstraint01.types | 8 +-- ...LiteralTypesAsTypeParameterConstraint02.js | 2 +- ...eralTypesAsTypeParameterConstraint02.types | 2 +- ...tringLiteralTypesInUnionTypes01.errors.txt | 26 ---------- .../stringLiteralTypesInUnionTypes02.types | 40 +++++++------- ...tringLiteralTypesInUnionTypes03.errors.txt | 28 ---------- .../stringLiteralTypesInUnionTypes04.types | 16 +++--- .../stringLiteralTypesTypePredicates01.types | 8 +-- ...gumentsWithStringLiteralTypes01.errors.txt | 52 +++++++++++-------- .../typeArgumentsWithStringLiteralTypes01.js | 8 +-- .../reference/useSharedArrayBuffer4.types | 2 +- .../reference/useSharedArrayBuffer5.types | 2 +- .../reference/useSharedArrayBuffer6.types | 2 +- 18 files changed, 91 insertions(+), 140 deletions(-) delete mode 100644 tests/baselines/reference/stringLiteralTypesInUnionTypes01.errors.txt delete mode 100644 tests/baselines/reference/stringLiteralTypesInUnionTypes03.errors.txt diff --git a/tests/baselines/reference/numericLiteralTypes1.types b/tests/baselines/reference/numericLiteralTypes1.types index f091dd99d60b2..56e4bcc0f3fc1 100644 --- a/tests/baselines/reference/numericLiteralTypes1.types +++ b/tests/baselines/reference/numericLiteralTypes1.types @@ -370,7 +370,7 @@ function f14(x: 0 | 1 | 2, y: string) { >y : string var b = x || y; ->b : string | number +>b : string | 1 | 2 >x || y : string | 1 | 2 >x : 0 | 1 | 2 >y : string @@ -383,25 +383,25 @@ function f15(x: 0 | false, y: 1 | "one") { >y : 1 | "one" var a = x && y; ->a : number | boolean +>a : boolean | 0 >x && y : false | 0 >x : false | 0 >y : 1 | "one" var b = y && x; ->b : number | boolean +>b : boolean | 0 >y && x : false | 0 >y : 1 | "one" >x : false | 0 var c = x || y; ->c : string | number +>c : 1 | "one" >x || y : 1 | "one" >x : false | 0 >y : 1 | "one" var d = y || x; ->d : string | number | boolean +>d : boolean | 0 | 1 | "one" >y || x : false | 0 | 1 | "one" >y : 1 | "one" >x : false | 0 diff --git a/tests/baselines/reference/numericLiteralTypes2.types b/tests/baselines/reference/numericLiteralTypes2.types index a5744de2a34ca..b8e2526a221fc 100644 --- a/tests/baselines/reference/numericLiteralTypes2.types +++ b/tests/baselines/reference/numericLiteralTypes2.types @@ -365,13 +365,13 @@ function f14(x: 0 | 1 | 2, y: string) { >y : string var a = x && y; ->a : string | number +>a : string | 0 >x && y : string | 0 >x : 0 | 1 | 2 >y : string var b = x || y; ->b : string | number +>b : string | 1 | 2 >x || y : string | 1 | 2 >x : 0 | 1 | 2 >y : string @@ -384,25 +384,25 @@ function f15(x: 0 | false, y: 1 | "one") { >y : 1 | "one" var a = x && y; ->a : number | boolean +>a : boolean | 0 >x && y : false | 0 >x : false | 0 >y : 1 | "one" var b = y && x; ->b : number | boolean +>b : boolean | 0 >y && x : false | 0 >y : 1 | "one" >x : false | 0 var c = x || y; ->c : string | number +>c : 1 | "one" >x || y : 1 | "one" >x : false | 0 >y : 1 | "one" var d = y || x; ->d : string | number +>d : 1 | "one" >y || x : 1 | "one" >y : 1 | "one" >x : false | 0 diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.errors.txt b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.errors.txt index 3a884d2d1c455..1596d74281aa3 100644 --- a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.errors.txt +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.errors.txt @@ -1,16 +1,13 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts(6,5): error TS2322: Type 'string' is not assignable to type '"foo"'. tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts(8,5): error TS2322: Type 'string' is not assignable to type '"foo" | "bar"'. -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts (2 errors) ==== +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAndLogicalOrExpressions01.ts (1 errors) ==== declare function myRandBool(): boolean; let a: "foo" = "foo"; let b = a || "foo"; let c: "foo" = b; - ~ -!!! error TS2322: Type 'string' is not assignable to type '"foo"'. let d = b || "bar"; let e: "foo" | "bar" = d; ~ diff --git a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js index b6bcaf7c887c1..33dce2041e36e 100644 --- a/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js +++ b/tests/baselines/reference/stringLiteralTypesAndLogicalOrExpressions01.js @@ -20,7 +20,7 @@ var e = d; //// [stringLiteralTypesAndLogicalOrExpressions01.d.ts] declare function myRandBool(): boolean; declare let a: "foo"; -declare let b: string; +declare let b: "foo"; declare let c: "foo"; declare let d: string; declare let e: "foo" | "bar"; diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js index 805f16228ba9a..4f49d326ec04f 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.js @@ -38,8 +38,8 @@ hResult = h("bar"); declare function foo(f: (x: T) => T): (x: T) => T; declare function bar(f: (x: T) => T): (x: T) => T; declare let f: (x: "foo") => "foo"; -declare let fResult: string; +declare let fResult: "foo"; declare let g: (x: "foo") => "foo"; -declare let gResult: string; +declare let gResult: "foo"; declare let h: (x: "foo" | "bar") => "foo" | "bar"; -declare let hResult: string; +declare let hResult: "foo" | "bar"; diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types index e213faf3b6901..fe9163fc81911 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint01.types @@ -33,7 +33,7 @@ let f = foo(x => x); >x : "foo" let fResult = f("foo"); ->fResult : string +>fResult : "foo" >f("foo") : "foo" >f : (x: "foo") => "foo" >"foo" : "foo" @@ -48,7 +48,7 @@ let g = foo((x => x)); >x : "foo" let gResult = g("foo"); ->gResult : string +>gResult : "foo" >g("foo") : "foo" >g : (x: "foo") => "foo" >"foo" : "foo" @@ -62,14 +62,14 @@ let h = bar(x => x); >x : "foo" | "bar" let hResult = h("foo"); ->hResult : string +>hResult : "foo" | "bar" >h("foo") : "foo" | "bar" >h : (x: "foo" | "bar") => "foo" | "bar" >"foo" : "foo" hResult = h("bar"); >hResult = h("bar") : "foo" | "bar" ->hResult : string +>hResult : "foo" | "bar" >h("bar") : "foo" | "bar" >h : (x: "foo" | "bar") => "foo" | "bar" >"bar" : "bar" diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js index 06ee42b68ad70..173e74a6eef86 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.js @@ -18,4 +18,4 @@ var fResult = f("foo"); //// [stringLiteralTypesAsTypeParameterConstraint02.d.ts] declare function foo(f: (x: T) => T): (x: T) => T; declare let f: (x: "foo") => "foo"; -declare let fResult: string; +declare let fResult: "foo"; diff --git a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.types b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.types index 75ba54cf6c231..3a1b8fdc05c83 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.types +++ b/tests/baselines/reference/stringLiteralTypesAsTypeParameterConstraint02.types @@ -26,7 +26,7 @@ let f = foo((y: "foo" | "bar") => y === "foo" ? y : "foo"); >"foo" : "foo" let fResult = f("foo"); ->fResult : string +>fResult : "foo" >f("foo") : "foo" >f : (x: "foo") => "foo" >"foo" : "foo" diff --git a/tests/baselines/reference/stringLiteralTypesInUnionTypes01.errors.txt b/tests/baselines/reference/stringLiteralTypesInUnionTypes01.errors.txt deleted file mode 100644 index 39b2b154cc864..0000000000000 --- a/tests/baselines/reference/stringLiteralTypesInUnionTypes01.errors.txt +++ /dev/null @@ -1,26 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes01.ts(16,9): error TS2322: Type 'string' is not assignable to type '"foo" | "bar" | "baz"'. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes01.ts (1 errors) ==== - - type T = "foo" | "bar" | "baz"; - - var x: "foo" | "bar" | "baz" = undefined; - var y: T = undefined; - - if (x === "foo") { - let a = x; - } - else if (x !== "bar") { - let b = x || y; - } - else { - let c = x; - let d = y; - let e: (typeof x) | (typeof y) = c || d; - ~ -!!! error TS2322: Type 'string' is not assignable to type '"foo" | "bar" | "baz"'. - } - - x = y; - y = x; \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesInUnionTypes02.types b/tests/baselines/reference/stringLiteralTypesInUnionTypes02.types index 40b34796e72bd..0be891ade44cd 100644 --- a/tests/baselines/reference/stringLiteralTypesInUnionTypes02.types +++ b/tests/baselines/reference/stringLiteralTypesInUnionTypes02.types @@ -1,62 +1,62 @@ === tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes02.ts === type T = string | "foo" | "bar" | "baz"; ->T : string | "foo" | "bar" | "baz" +>T : string var x: "foo" | "bar" | "baz" | string = undefined; ->x : string | "foo" | "bar" | "baz" +>x : string >undefined : undefined var y: T = undefined; ->y : string | "foo" | "bar" | "baz" ->T : string | "foo" | "bar" | "baz" +>y : string +>T : string >undefined : undefined if (x === "foo") { >x === "foo" : boolean ->x : string | "foo" | "bar" | "baz" +>x : string >"foo" : "foo" let a = x; >a : string ->x : string | "foo" +>x : string } else if (x !== "bar") { >x !== "bar" : boolean ->x : string | "bar" | "baz" +>x : string >"bar" : "bar" let b = x || y; >b : string >x || y : string ->x : string | "baz" ->y : string | "foo" | "bar" | "baz" +>x : string +>y : string } else { let c = x; >c : string ->x : string | "bar" +>x : string let d = y; >d : string ->y : string | "foo" | "bar" | "baz" +>y : string let e: (typeof x) | (typeof y) = c || d; ->e : string | "foo" | "bar" | "baz" ->x : string | "bar" ->y : string | "foo" | "bar" | "baz" +>e : string +>x : string +>y : string >c || d : string >c : string >d : string } x = y; ->x = y : string | "foo" | "bar" | "baz" ->x : string | "foo" | "bar" | "baz" ->y : string | "foo" | "bar" | "baz" +>x = y : string +>x : string +>y : string y = x; ->y = x : string | "foo" | "bar" | "baz" ->y : string | "foo" | "bar" | "baz" ->x : string | "foo" | "bar" | "baz" +>y = x : string +>y : string +>x : string diff --git a/tests/baselines/reference/stringLiteralTypesInUnionTypes03.errors.txt b/tests/baselines/reference/stringLiteralTypesInUnionTypes03.errors.txt deleted file mode 100644 index 784f368c164e3..0000000000000 --- a/tests/baselines/reference/stringLiteralTypesInUnionTypes03.errors.txt +++ /dev/null @@ -1,28 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes03.ts(16,9): error TS2322: Type 'string | number' is not assignable to type 'number | "foo" | "bar"'. - Type 'string' is not assignable to type 'number | "foo" | "bar"'. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesInUnionTypes03.ts (1 errors) ==== - - type T = number | "foo" | "bar"; - - var x: "foo" | "bar" | number; - var y: T = undefined; - - if (x === "foo") { - let a = x; - } - else if (x !== "bar") { - let b = x || y; - } - else { - let c = x; - let d = y; - let e: (typeof x) | (typeof y) = c || d; - ~ -!!! error TS2322: Type 'string | number' is not assignable to type 'number | "foo" | "bar"'. -!!! error TS2322: Type 'string' is not assignable to type 'number | "foo" | "bar"'. - } - - x = y; - y = x; \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesInUnionTypes04.types b/tests/baselines/reference/stringLiteralTypesInUnionTypes04.types index 3d2a41ec5c9ee..05b6b9b9b7aed 100644 --- a/tests/baselines/reference/stringLiteralTypesInUnionTypes04.types +++ b/tests/baselines/reference/stringLiteralTypesInUnionTypes04.types @@ -19,7 +19,7 @@ if (x === "") { >"" : "" let a = x; ->a : string +>a : "" >x : "" } @@ -29,7 +29,7 @@ if (x !== "") { >"" : "" let b = x; ->b : string +>b : "foo" >x : "foo" } @@ -39,7 +39,7 @@ if (x == "") { >"" : "" let c = x; ->c : string +>c : "" >x : "" } @@ -49,7 +49,7 @@ if (x != "") { >"" : "" let d = x; ->d : string +>d : "foo" >x : "foo" } @@ -57,7 +57,7 @@ if (x) { >x : T let e = x; ->e : string +>e : "foo" >x : "foo" } @@ -66,7 +66,7 @@ if (!x) { >x : T let f = x; ->f : string +>f : T >x : T } @@ -76,7 +76,7 @@ if (!!x) { >x : T let g = x; ->g : string +>g : "foo" >x : "foo" } @@ -87,6 +87,6 @@ if (!!!x) { >x : T let h = x; ->h : string +>h : T >x : T } diff --git a/tests/baselines/reference/stringLiteralTypesTypePredicates01.types b/tests/baselines/reference/stringLiteralTypesTypePredicates01.types index 0a87ffad86548..822103b86f571 100644 --- a/tests/baselines/reference/stringLiteralTypesTypePredicates01.types +++ b/tests/baselines/reference/stringLiteralTypesTypePredicates01.types @@ -42,12 +42,12 @@ if (kindIs(x, "A")) { >"A" : "A" let a = x; ->a : string +>a : "A" >x : "A" } else { let b = x; ->b : string +>b : "B" >x : "B" } @@ -59,11 +59,11 @@ if (!kindIs(x, "B")) { >"B" : "B" let c = x; ->c : string +>c : "A" >x : "A" } else { let d = x; ->d : string +>d : "B" >x : "B" } diff --git a/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt b/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt index 2876390758f1d..48c7efb37e8c1 100644 --- a/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt +++ b/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.errors.txt @@ -11,17 +11,21 @@ tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes0 tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(55,43): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(57,52): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(58,43): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(68,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(70,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(75,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(77,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(61,5): error TS2322: Type 'string' is not assignable to type '"Hello"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(63,5): error TS2322: Type 'string' is not assignable to type '"Hello"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(75,5): error TS2322: Type '"Hello" | "World"' is not assignable to type '"Hello"'. + Type '"World"' is not assignable to type '"Hello"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(77,5): error TS2322: Type '"Hello" | "World"' is not assignable to type '"Hello"'. + Type '"World"' is not assignable to type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(87,43): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(88,43): error TS2345: Argument of type '"Hello"' is not assignable to parameter of type '"World"'. tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(89,52): error TS2345: Argument of type '"World"' is not assignable to parameter of type '"Hello"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(100,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(104,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(107,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. -tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(111,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(93,5): error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(97,5): error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(100,25): error TS2345: Argument of type '"Hello" | "World"' is not assignable to parameter of type '"Hello"'. + Type '"World"' is not assignable to type '"Hello"'. +tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts(104,25): error TS2345: Argument of type '"Hello" | "World"' is not assignable to parameter of type '"Hello"'. + Type '"World"' is not assignable to type '"Hello"'. ==== tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes01.ts (24 errors) ==== @@ -112,30 +116,32 @@ tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes0 // Assignment from the returned value should cause an error. a = takeReturnString(a); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"Hello"'. b = takeReturnString(b); c = takeReturnString(c); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"Hello"'. d = takeReturnString(d); e = takeReturnString(e); // Should be valid a = takeReturnHello(a); - ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. b = takeReturnHello(b); c = takeReturnHello(c); - ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. d = takeReturnHello(d); e = takeReturnHello(e); // Assignment from the returned value should cause an error. a = takeReturnHelloWorld(a); - ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. + ~ +!!! error TS2322: Type '"Hello" | "World"' is not assignable to type '"Hello"'. +!!! error TS2322: Type '"World"' is not assignable to type '"Hello"'. b = takeReturnHelloWorld(b); c = takeReturnHelloWorld(c); - ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. + ~ +!!! error TS2322: Type '"Hello" | "World"' is not assignable to type '"Hello"'. +!!! error TS2322: Type '"World"' is not assignable to type '"Hello"'. d = takeReturnHelloWorld(d); e = takeReturnHelloWorld(e); } @@ -158,30 +164,32 @@ tests/cases/conformance/types/stringLiteral/typeArgumentsWithStringLiteralTypes0 // Assignment from the returned value should cause an error. a = takeReturnString(a); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. b = takeReturnString(b); c = takeReturnString(c); d = takeReturnString(d); e = takeReturnString(e); + ~ +!!! error TS2322: Type 'string' is not assignable to type '"Hello" | "World"'. // Passing these as arguments should cause an error. a = takeReturnHello(a); ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. +!!! error TS2345: Argument of type '"Hello" | "World"' is not assignable to parameter of type '"Hello"'. +!!! error TS2345: Type '"World"' is not assignable to type '"Hello"'. b = takeReturnHello(b); c = takeReturnHello(c); d = takeReturnHello(d); e = takeReturnHello(e); ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello"'. +!!! error TS2345: Argument of type '"Hello" | "World"' is not assignable to parameter of type '"Hello"'. +!!! error TS2345: Type '"World"' is not assignable to type '"Hello"'. // Both should be valid. a = takeReturnHelloWorld(a); - ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. b = takeReturnHelloWorld(b); c = takeReturnHelloWorld(c); d = takeReturnHelloWorld(d); e = takeReturnHelloWorld(e); - ~ -!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"Hello" | "World"'. } \ No newline at end of file diff --git a/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.js b/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.js index ca67e358705cf..c07dd22539648 100644 --- a/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.js +++ b/tests/baselines/reference/typeArgumentsWithStringLiteralTypes01.js @@ -229,16 +229,16 @@ declare namespace n1 { let e: string; } declare namespace n2 { - let a: string; + let a: "Hello"; let b: any; - let c: string; + let c: "Hello"; let d: any; let e: any; } declare namespace n3 { - let a: string; + let a: "Hello" | "World"; let b: any; let c: any; let d: any; - let e: string; + let e: "Hello" | "World"; } diff --git a/tests/baselines/reference/useSharedArrayBuffer4.types b/tests/baselines/reference/useSharedArrayBuffer4.types index d070150c95b91..27b99acd2319e 100644 --- a/tests/baselines/reference/useSharedArrayBuffer4.types +++ b/tests/baselines/reference/useSharedArrayBuffer4.types @@ -24,7 +24,7 @@ var species = foge[Symbol.species]; >species : symbol var stringTag = foge[Symbol.toStringTag]; ->stringTag : string +>stringTag : "SharedArrayBuffer" >foge[Symbol.toStringTag] : "SharedArrayBuffer" >foge : SharedArrayBuffer >Symbol.toStringTag : symbol diff --git a/tests/baselines/reference/useSharedArrayBuffer5.types b/tests/baselines/reference/useSharedArrayBuffer5.types index 848a1596591c5..44d41d5247784 100644 --- a/tests/baselines/reference/useSharedArrayBuffer5.types +++ b/tests/baselines/reference/useSharedArrayBuffer5.types @@ -15,7 +15,7 @@ var species = foge[Symbol.species]; >species : symbol var stringTag = foge[Symbol.toStringTag]; ->stringTag : string +>stringTag : "SharedArrayBuffer" >foge[Symbol.toStringTag] : "SharedArrayBuffer" >foge : SharedArrayBuffer >Symbol.toStringTag : symbol diff --git a/tests/baselines/reference/useSharedArrayBuffer6.types b/tests/baselines/reference/useSharedArrayBuffer6.types index 4cf07e4932082..d4d831e68fbd9 100644 --- a/tests/baselines/reference/useSharedArrayBuffer6.types +++ b/tests/baselines/reference/useSharedArrayBuffer6.types @@ -15,7 +15,7 @@ var species = foge[Symbol.species]; >species : symbol var stringTag = foge[Symbol.toStringTag]; ->stringTag : string +>stringTag : "SharedArrayBuffer" >foge[Symbol.toStringTag] : "SharedArrayBuffer" >foge : SharedArrayBuffer >Symbol.toStringTag : symbol From 55034d8e103410a6cbd4610c8f50935276db6dda Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 24 Sep 2016 07:38:26 -0700 Subject: [PATCH 04/12] Emit widened literal type for const without type annotation --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 01c5642c7d4c6..54a28528da7f1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18950,7 +18950,7 @@ namespace ts { // Get type of the symbol if this is the valid symbol otherwise get type at location const symbol = getSymbolOfNode(declaration); const type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature)) - ? getTypeOfSymbol(symbol) + ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : unknownType; getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); From ed003b93f4e4f123cb23dee57046b888fdd6168d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 24 Sep 2016 07:38:35 -0700 Subject: [PATCH 05/12] Accept new baselines --- tests/baselines/reference/constDeclarations.js | 4 ++-- tests/baselines/reference/constDeclarations2.js | 4 ++-- .../declarationEmitClassMemberNameConflict2.js | 2 +- ...handOfExportedEntity01_targetES2015_CommonJS.js | 2 +- ...orthandOfExportedEntity02_targetES5_CommonJS.js | 2 +- .../reference/stringLiteralTypesOverloads02.js | 14 +++++++------- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/baselines/reference/constDeclarations.js b/tests/baselines/reference/constDeclarations.js index 7e5902ed5a160..060c0aba61cd6 100644 --- a/tests/baselines/reference/constDeclarations.js +++ b/tests/baselines/reference/constDeclarations.js @@ -25,6 +25,6 @@ for (const c5 = 0, c6 = 0; c5 < c6;) { //// [constDeclarations.d.ts] -declare const c1: false; +declare const c1: boolean; declare const c2: number; -declare const c3: 0, c4: string, c5: any; +declare const c3: number, c4: string, c5: any; diff --git a/tests/baselines/reference/constDeclarations2.js b/tests/baselines/reference/constDeclarations2.js index ea7134d46645a..e4ee67ebdcdd0 100644 --- a/tests/baselines/reference/constDeclarations2.js +++ b/tests/baselines/reference/constDeclarations2.js @@ -20,7 +20,7 @@ var M; //// [constDeclarations2.d.ts] declare module M { - const c1: false; + const c1: boolean; const c2: number; - const c3: 0, c4: string, c5: any; + const c3: number, c4: string, c5: any; } diff --git a/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js b/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js index 233ca0fe138f0..6e18377d30f15 100644 --- a/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js +++ b/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js @@ -45,7 +45,7 @@ var Foo = (function () { //// [declarationEmitClassMemberNameConflict2.d.ts] -declare const Bar: "bar"; +declare const Bar: string; declare enum Hello { World = 0, } diff --git a/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js b/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js index df23dba87760c..9e057951b3a66 100644 --- a/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js +++ b/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js @@ -17,5 +17,5 @@ exports.foo = foo; //// [shorthandOfExportedEntity01_targetES2015_CommonJS.d.ts] -export declare const test: "test"; +export declare const test: string; export declare function foo(): void; diff --git a/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js b/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js index a594a1b6de5c0..764739705c4e1 100644 --- a/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js +++ b/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js @@ -17,5 +17,5 @@ exports.foo = foo; //// [shorthandOfExportedEntity02_targetES5_CommonJS.d.ts] -export declare const test: "test"; +export declare const test: string; export declare function foo(): void; diff --git a/tests/baselines/reference/stringLiteralTypesOverloads02.js b/tests/baselines/reference/stringLiteralTypesOverloads02.js index 0e7bd8c82c81e..184af2d74b73a 100644 --- a/tests/baselines/reference/stringLiteralTypesOverloads02.js +++ b/tests/baselines/reference/stringLiteralTypesOverloads02.js @@ -100,12 +100,12 @@ declare function getFalsyPrimitive(x: "number" | "string"): number | string; declare function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; declare namespace Consts1 { } -declare const string: "string"; -declare const number: "number"; -declare const boolean: "boolean"; -declare const stringOrNumber: "string" | "number"; -declare const stringOrBoolean: "string" | "boolean"; -declare const booleanOrNumber: "number" | "boolean"; -declare const stringOrBooleanOrNumber: "string" | "number" | "boolean"; +declare const string: string; +declare const number: string; +declare const boolean: string; +declare const stringOrNumber: string; +declare const stringOrBoolean: string; +declare const booleanOrNumber: string; +declare const stringOrBooleanOrNumber: string; declare namespace Consts2 { } From e6efb15a53f74b6c0fbb363564d8144c8d8a4bf7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 24 Sep 2016 08:09:06 -0700 Subject: [PATCH 06/12] 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 54a28528da7f1..092ef8e4e6b8d 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 From 4a78047af02607b84c71d6b22d243b7e9cbf46b3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 24 Sep 2016 08:09:27 -0700 Subject: [PATCH 07/12] Accept new baselines --- tests/baselines/reference/arrayconcat.types | 2 +- .../bestCommonTypeOfConditionalExpressions2.types | 2 +- .../computedPropertyNamesContextualType6_ES5.types | 2 +- .../computedPropertyNamesContextualType6_ES6.types | 2 +- .../reference/conditionalExpression1.errors.txt | 8 ++++---- .../baselines/reference/conditionalExpressions2.types | 2 +- .../reference/declFileTypeAnnotationParenType.types | 2 +- .../functionWithMultipleReturnStatements.types | 10 +++++----- tests/baselines/reference/literalTypes2.types | 6 +++--- .../subtypesOfTypeParameterWithConstraints2.types | 4 ++-- tests/baselines/reference/underscoreTest1.types | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/arrayconcat.types b/tests/baselines/reference/arrayconcat.types index 27724c63ab1da..adbb1f7d021e4 100644 --- a/tests/baselines/reference/arrayconcat.types +++ b/tests/baselines/reference/arrayconcat.types @@ -46,7 +46,7 @@ class parser { >this : this >options : IOptions[] >sort : (compareFn?: (a: IOptions, b: IOptions) => number) => IOptions[] ->function(a, b) { var aName = a.name.toLowerCase(); var bName = b.name.toLowerCase(); if (aName > bName) { return 1; } else if (aName < bName) { return -1; } else { return 0; } } : (a: IOptions, b: IOptions) => 0 | 1 | -1 +>function(a, b) { var aName = a.name.toLowerCase(); var bName = b.name.toLowerCase(); if (aName > bName) { return 1; } else if (aName < bName) { return -1; } else { return 0; } } : (a: IOptions, b: IOptions) => 1 | -1 | 0 >a : IOptions >b : IOptions diff --git a/tests/baselines/reference/bestCommonTypeOfConditionalExpressions2.types b/tests/baselines/reference/bestCommonTypeOfConditionalExpressions2.types index ad09c274c9ba6..997f4ea52492d 100644 --- a/tests/baselines/reference/bestCommonTypeOfConditionalExpressions2.types +++ b/tests/baselines/reference/bestCommonTypeOfConditionalExpressions2.types @@ -30,7 +30,7 @@ var derived2: Derived2; var r2 = true ? 1 : ''; >r2 : string | number ->true ? 1 : '' : "" | 1 +>true ? 1 : '' : 1 | "" >true : true >1 : 1 >'' : "" diff --git a/tests/baselines/reference/computedPropertyNamesContextualType6_ES5.types b/tests/baselines/reference/computedPropertyNamesContextualType6_ES5.types index 636510726446d..91ad88c8aded5 100644 --- a/tests/baselines/reference/computedPropertyNamesContextualType6_ES5.types +++ b/tests/baselines/reference/computedPropertyNamesContextualType6_ES5.types @@ -19,7 +19,7 @@ declare function foo(obj: I): T foo({ >foo({ p: "", 0: () => { }, ["hi" + "bye"]: true, [0 + 1]: 0, [+"hi"]: [0]}) : string | number | boolean | (() => void) | number[] >foo : (obj: I) => T ->{ p: "", 0: () => { }, ["hi" + "bye"]: true, [0 + 1]: 0, [+"hi"]: [0]} : { [x: string]: true | "" | 0 | (() => void) | number[]; [x: number]: 0 | (() => void) | number[]; 0: () => void; p: ""; } +>{ p: "", 0: () => { }, ["hi" + "bye"]: true, [0 + 1]: 0, [+"hi"]: [0]} : { [x: string]: true | "" | (() => void) | 0 | number[]; [x: number]: (() => void) | 0 | number[]; 0: () => void; p: ""; } p: "", >p : string diff --git a/tests/baselines/reference/computedPropertyNamesContextualType6_ES6.types b/tests/baselines/reference/computedPropertyNamesContextualType6_ES6.types index fa34f015a2361..131e49dd173fa 100644 --- a/tests/baselines/reference/computedPropertyNamesContextualType6_ES6.types +++ b/tests/baselines/reference/computedPropertyNamesContextualType6_ES6.types @@ -19,7 +19,7 @@ declare function foo(obj: I): T foo({ >foo({ p: "", 0: () => { }, ["hi" + "bye"]: true, [0 + 1]: 0, [+"hi"]: [0]}) : string | number | boolean | (() => void) | number[] >foo : (obj: I) => T ->{ p: "", 0: () => { }, ["hi" + "bye"]: true, [0 + 1]: 0, [+"hi"]: [0]} : { [x: string]: true | "" | 0 | (() => void) | number[]; [x: number]: 0 | (() => void) | number[]; 0: () => void; p: ""; } +>{ p: "", 0: () => { }, ["hi" + "bye"]: true, [0 + 1]: 0, [+"hi"]: [0]} : { [x: string]: true | "" | (() => void) | 0 | number[]; [x: number]: (() => void) | 0 | number[]; 0: () => void; p: ""; } p: "", >p : string diff --git a/tests/baselines/reference/conditionalExpression1.errors.txt b/tests/baselines/reference/conditionalExpression1.errors.txt index 66af533680866..2b34212952382 100644 --- a/tests/baselines/reference/conditionalExpression1.errors.txt +++ b/tests/baselines/reference/conditionalExpression1.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/conditionalExpression1.ts(1,5): error TS2322: Type '"" | 1' is not assignable to type 'boolean'. - Type '""' is not assignable to type 'boolean'. +tests/cases/compiler/conditionalExpression1.ts(1,5): error TS2322: Type '1 | ""' is not assignable to type 'boolean'. + Type '1' is not assignable to type 'boolean'. ==== tests/cases/compiler/conditionalExpression1.ts (1 errors) ==== var x: boolean = (true ? 1 : ""); // should be an error ~ -!!! error TS2322: Type '"" | 1' is not assignable to type 'boolean'. -!!! error TS2322: Type '""' is not assignable to type 'boolean'. \ No newline at end of file +!!! error TS2322: Type '1 | ""' is not assignable to type 'boolean'. +!!! error TS2322: Type '1' is not assignable to type 'boolean'. \ No newline at end of file diff --git a/tests/baselines/reference/conditionalExpressions2.types b/tests/baselines/reference/conditionalExpressions2.types index 0247b0f649d80..c2b2e23e57b1c 100644 --- a/tests/baselines/reference/conditionalExpressions2.types +++ b/tests/baselines/reference/conditionalExpressions2.types @@ -16,7 +16,7 @@ var b = false ? undefined : 0; var c = false ? 1 : 0; >c : number ->false ? 1 : 0 : 0 | 1 +>false ? 1 : 0 : 1 | 0 >false : false >1 : 1 >0 : 0 diff --git a/tests/baselines/reference/declFileTypeAnnotationParenType.types b/tests/baselines/reference/declFileTypeAnnotationParenType.types index f3c8db5533a94..1fd0b6ee5d958 100644 --- a/tests/baselines/reference/declFileTypeAnnotationParenType.types +++ b/tests/baselines/reference/declFileTypeAnnotationParenType.types @@ -25,7 +25,7 @@ var y = [() => new c()]; var k: (() => c) | string = (() => new c()) || ""; >k : string | (() => c) >c : c ->(() => new c()) || "" : "" | (() => c) +>(() => new c()) || "" : (() => c) | "" >(() => new c()) : () => c >() => new c() : () => c >new c() : c diff --git a/tests/baselines/reference/functionWithMultipleReturnStatements.types b/tests/baselines/reference/functionWithMultipleReturnStatements.types index 775ca52e1dba7..fec29e5a01be1 100644 --- a/tests/baselines/reference/functionWithMultipleReturnStatements.types +++ b/tests/baselines/reference/functionWithMultipleReturnStatements.types @@ -4,7 +4,7 @@ // it is an error if there is no single BCT, these are error cases function f1() { ->f1 : () => "" | 1 +>f1 : () => 1 | "" if (true) { >true : true @@ -19,7 +19,7 @@ function f1() { } function f2() { ->f2 : () => "" | 1 | 2 +>f2 : () => 1 | "" | 2 if (true) { >true : true @@ -40,7 +40,7 @@ function f2() { } function f3() { ->f3 : () => "" | 1 +>f3 : () => 1 | "" try { return 1; @@ -55,7 +55,7 @@ function f3() { } function f4() { ->f4 : () => "" | 1 +>f4 : () => 1 | "" try { return 1; @@ -72,7 +72,7 @@ function f4() { } function f5() { ->f5 : () => "" | 1 +>f5 : () => 1 | "" return 1; >1 : 1 diff --git a/tests/baselines/reference/literalTypes2.types b/tests/baselines/reference/literalTypes2.types index ba12ada644ba1..716b016f64e15 100644 --- a/tests/baselines/reference/literalTypes2.types +++ b/tests/baselines/reference/literalTypes2.types @@ -482,7 +482,7 @@ function f6() { const { c1 = true, c2 = 0, c3 = "foo" } = { c1: false, c2: 1, c3: "bar" }; >c1 : boolean >true : true ->c2 : 0 | 1 +>c2 : 1 | 0 >0 : 0 >c3 : "foo" | "bar" >"foo" : "foo" @@ -552,10 +552,10 @@ class C2 { >0 : 0 } bar() { ->bar : () => 0 | 1 +>bar : () => 1 | 0 return cond ? 0 : 1; ->cond ? 0 : 1 : 0 | 1 +>cond ? 0 : 1 : 1 | 0 >cond : boolean >0 : 0 >1 : 1 diff --git a/tests/baselines/reference/subtypesOfTypeParameterWithConstraints2.types b/tests/baselines/reference/subtypesOfTypeParameterWithConstraints2.types index 99aef9e95f6d7..23ac78ec01376 100644 --- a/tests/baselines/reference/subtypesOfTypeParameterWithConstraints2.types +++ b/tests/baselines/reference/subtypesOfTypeParameterWithConstraints2.types @@ -259,14 +259,14 @@ function f6(x: T) { var r2 = true ? '' : x; // ok >r2 : string | T ->true ? '' : x : "" | T +>true ? '' : x : T | "" >true : true >'' : "" >x : T var r2 = true ? x : ''; // ok >r2 : string | T ->true ? x : '' : "" | T +>true ? x : '' : T | "" >true : true >x : T >'' : "" diff --git a/tests/baselines/reference/underscoreTest1.types b/tests/baselines/reference/underscoreTest1.types index d4898d43beda4..97e064fb12c45 100644 --- a/tests/baselines/reference/underscoreTest1.types +++ b/tests/baselines/reference/underscoreTest1.types @@ -512,7 +512,7 @@ _.compact([0, 1, false, 2, '', 3]); >_.compact : (list: T[]) => T[] >_ : Underscore.Static >compact : (list: T[]) => T[] ->[0, 1, false, 2, '', 3] : (false | "" | 0 | 1 | 2 | 3)[] +>[0, 1, false, 2, '', 3] : (false | 1 | 2 | 3 | 0 | "")[] >0 : 0 >1 : 1 >false : false From 9771f429ed96b3598bcf60e337b5677de77ae6b1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 24 Sep 2016 15:58:53 -0700 Subject: [PATCH 08/12] Add tests --- .../types/literal/literalTypeWidening.ts | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/cases/conformance/types/literal/literalTypeWidening.ts diff --git a/tests/cases/conformance/types/literal/literalTypeWidening.ts b/tests/cases/conformance/types/literal/literalTypeWidening.ts new file mode 100644 index 0000000000000..98ed328f0d27d --- /dev/null +++ b/tests/cases/conformance/types/literal/literalTypeWidening.ts @@ -0,0 +1,97 @@ +// Widening vs. non-widening literal types + +function f1() { + const c1 = "hello"; // Widening type "hello" + let v1 = c1; // Type string + const c2 = c1; // Widening type "hello" + let v2 = c2; // Type string + const c3: "hello" = "hello"; // Type "hello" + let v3 = c3; // Type "hello" + const c4: "hello" = c1; // Type "hello" + let v4 = c4; // Type "hello" +} + +function f2(cond: boolean) { + const c1 = cond ? "foo" : "bar"; // widening "foo" | widening "bar" + const c2: "foo" | "bar" = c1; // "foo" | "bar" + const c3 = cond ? c1 : c2; // "foo" | "bar" + const c4 = cond ? c3 : "baz"; // "foo" | "bar" | widening "baz" + const c5: "foo" | "bar" | "baz" = c4; // "foo" | "bar" | "baz" + let v1 = c1; // string + let v2 = c2; // "foo" | "bar" + let v3 = c3; // "foo" | "bar" + let v4 = c4; // string + let v5 = c5; // "foo" | "bar" | "baz" +} + +function f3() { + const c1 = 123; // Widening type 123 + let v1 = c1; // Type number + const c2 = c1; // Widening type 123 + let v2 = c2; // Type number + const c3: 123 = 123; // Type 123 + let v3 = c3; // Type 123 + const c4: 123 = c1; // Type 123 + let v4 = c4; // Type 123 +} + +function f4(cond: boolean) { + const c1 = cond ? 123 : 456; // widening 123 | widening 456 + const c2: 123 | 456 = c1; // 123 | 456 + const c3 = cond ? c1 : c2; // 123 | 456 + const c4 = cond ? c3 : 789; // 123 | 456 | widening 789 + const c5: 123 | 456 | 789 = c4; // 123 | 456 | 789 + let v1 = c1; // number + let v2 = c2; // 123 | 456 + let v3 = c3; // 123 | 456 + let v4 = c4; // number + let v5 = c5; // 123 | 456 | 789 +} + +function f5() { + const c1 = "foo"; + let v1 = c1; + const c2: "foo" = "foo"; + let v2 = c2; + const c3 = "foo" as "foo"; + let v3 = c3; + const c4 = <"foo">"foo"; + let v4 = c4; +} + +// Repro from #10898 + +type FAILURE = "FAILURE"; +const FAILURE = "FAILURE"; + +type Result = T | FAILURE; + +function doWork(): Result { + return FAILURE; +} + +function isSuccess(result: Result): result is T { + return !isFailure(result); +} + +function isFailure(result: Result): result is FAILURE { + return result === FAILURE; +} + +function increment(x: number): number { + return x + 1; +} + +let result = doWork(); + +if (isSuccess(result)) { + increment(result); +} + +// Repro from #10898 + +type TestEvent = "onmouseover" | "onmouseout"; + +function onMouseOver(): TestEvent { return "onmouseover"; } + +let x = onMouseOver(); \ No newline at end of file From a8e004255e3bbb08cd1c75f5cd403b79be7633c3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 24 Sep 2016 15:59:06 -0700 Subject: [PATCH 09/12] Accept new baselines --- .../reference/literalTypeWidening.js | 174 ++++++++++ .../reference/literalTypeWidening.symbols | 285 ++++++++++++++++ .../reference/literalTypeWidening.types | 318 ++++++++++++++++++ 3 files changed, 777 insertions(+) create mode 100644 tests/baselines/reference/literalTypeWidening.js create mode 100644 tests/baselines/reference/literalTypeWidening.symbols create mode 100644 tests/baselines/reference/literalTypeWidening.types diff --git a/tests/baselines/reference/literalTypeWidening.js b/tests/baselines/reference/literalTypeWidening.js new file mode 100644 index 0000000000000..580021235575a --- /dev/null +++ b/tests/baselines/reference/literalTypeWidening.js @@ -0,0 +1,174 @@ +//// [literalTypeWidening.ts] +// Widening vs. non-widening literal types + +function f1() { + const c1 = "hello"; // Widening type "hello" + let v1 = c1; // Type string + const c2 = c1; // Widening type "hello" + let v2 = c2; // Type string + const c3: "hello" = "hello"; // Type "hello" + let v3 = c3; // Type "hello" + const c4: "hello" = c1; // Type "hello" + let v4 = c4; // Type "hello" +} + +function f2(cond: boolean) { + const c1 = cond ? "foo" : "bar"; // widening "foo" | widening "bar" + const c2: "foo" | "bar" = c1; // "foo" | "bar" + const c3 = cond ? c1 : c2; // "foo" | "bar" + const c4 = cond ? c3 : "baz"; // "foo" | "bar" | widening "baz" + const c5: "foo" | "bar" | "baz" = c4; // "foo" | "bar" | "baz" + let v1 = c1; // string + let v2 = c2; // "foo" | "bar" + let v3 = c3; // "foo" | "bar" + let v4 = c4; // string + let v5 = c5; // "foo" | "bar" | "baz" +} + +function f3() { + const c1 = 123; // Widening type 123 + let v1 = c1; // Type number + const c2 = c1; // Widening type 123 + let v2 = c2; // Type number + const c3: 123 = 123; // Type 123 + let v3 = c3; // Type 123 + const c4: 123 = c1; // Type 123 + let v4 = c4; // Type 123 +} + +function f4(cond: boolean) { + const c1 = cond ? 123 : 456; // widening 123 | widening 456 + const c2: 123 | 456 = c1; // 123 | 456 + const c3 = cond ? c1 : c2; // 123 | 456 + const c4 = cond ? c3 : 789; // 123 | 456 | widening 789 + const c5: 123 | 456 | 789 = c4; // 123 | 456 | 789 + let v1 = c1; // number + let v2 = c2; // 123 | 456 + let v3 = c3; // 123 | 456 + let v4 = c4; // number + let v5 = c5; // 123 | 456 | 789 +} + +function f5() { + const c1 = "foo"; + let v1 = c1; + const c2: "foo" = "foo"; + let v2 = c2; + const c3 = "foo" as "foo"; + let v3 = c3; + const c4 = <"foo">"foo"; + let v4 = c4; +} + +// Repro from #10898 + +type FAILURE = "FAILURE"; +const FAILURE = "FAILURE"; + +type Result = T | FAILURE; + +function doWork(): Result { + return FAILURE; +} + +function isSuccess(result: Result): result is T { + return !isFailure(result); +} + +function isFailure(result: Result): result is FAILURE { + return result === FAILURE; +} + +function increment(x: number): number { + return x + 1; +} + +let result = doWork(); + +if (isSuccess(result)) { + increment(result); +} + +// Repro from #10898 + +type TestEvent = "onmouseover" | "onmouseout"; + +function onMouseOver(): TestEvent { return "onmouseover"; } + +let x = onMouseOver(); + +//// [literalTypeWidening.js] +// Widening vs. non-widening literal types +function f1() { + var c1 = "hello"; // Widening type "hello" + var v1 = c1; // Type string + var c2 = c1; // Widening type "hello" + var v2 = c2; // Type string + var c3 = "hello"; // Type "hello" + var v3 = c3; // Type "hello" + var c4 = c1; // Type "hello" + var v4 = c4; // Type "hello" +} +function f2(cond) { + var c1 = cond ? "foo" : "bar"; // widening "foo" | widening "bar" + var c2 = c1; // "foo" | "bar" + var c3 = cond ? c1 : c2; // "foo" | "bar" + var c4 = cond ? c3 : "baz"; // "foo" | "bar" | widening "baz" + var c5 = c4; // "foo" | "bar" | "baz" + var v1 = c1; // string + var v2 = c2; // "foo" | "bar" + var v3 = c3; // "foo" | "bar" + var v4 = c4; // string + var v5 = c5; // "foo" | "bar" | "baz" +} +function f3() { + var c1 = 123; // Widening type 123 + var v1 = c1; // Type number + var c2 = c1; // Widening type 123 + var v2 = c2; // Type number + var c3 = 123; // Type 123 + var v3 = c3; // Type 123 + var c4 = c1; // Type 123 + var v4 = c4; // Type 123 +} +function f4(cond) { + var c1 = cond ? 123 : 456; // widening 123 | widening 456 + var c2 = c1; // 123 | 456 + var c3 = cond ? c1 : c2; // 123 | 456 + var c4 = cond ? c3 : 789; // 123 | 456 | widening 789 + var c5 = c4; // 123 | 456 | 789 + var v1 = c1; // number + var v2 = c2; // 123 | 456 + var v3 = c3; // 123 | 456 + var v4 = c4; // number + var v5 = c5; // 123 | 456 | 789 +} +function f5() { + var c1 = "foo"; + var v1 = c1; + var c2 = "foo"; + var v2 = c2; + var c3 = "foo"; + var v3 = c3; + var c4 = "foo"; + var v4 = c4; +} +var FAILURE = "FAILURE"; +function doWork() { + return FAILURE; +} +function isSuccess(result) { + return !isFailure(result); +} +function isFailure(result) { + return result === FAILURE; +} +function increment(x) { + return x + 1; +} +var result = doWork(); +if (isSuccess(result)) { + increment(result); +} +function onMouseOver() { return "onmouseover"; } +var x = onMouseOver(); diff --git a/tests/baselines/reference/literalTypeWidening.symbols b/tests/baselines/reference/literalTypeWidening.symbols new file mode 100644 index 0000000000000..e0da630180eaf --- /dev/null +++ b/tests/baselines/reference/literalTypeWidening.symbols @@ -0,0 +1,285 @@ +=== tests/cases/conformance/types/literal/literalTypeWidening.ts === +// Widening vs. non-widening literal types + +function f1() { +>f1 : Symbol(f1, Decl(literalTypeWidening.ts, 0, 0)) + + const c1 = "hello"; // Widening type "hello" +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 3, 9)) + + let v1 = c1; // Type string +>v1 : Symbol(v1, Decl(literalTypeWidening.ts, 4, 7)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 3, 9)) + + const c2 = c1; // Widening type "hello" +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 5, 9)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 3, 9)) + + let v2 = c2; // Type string +>v2 : Symbol(v2, Decl(literalTypeWidening.ts, 6, 7)) +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 5, 9)) + + const c3: "hello" = "hello"; // Type "hello" +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 7, 9)) + + let v3 = c3; // Type "hello" +>v3 : Symbol(v3, Decl(literalTypeWidening.ts, 8, 7)) +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 7, 9)) + + const c4: "hello" = c1; // Type "hello" +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 9, 9)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 3, 9)) + + let v4 = c4; // Type "hello" +>v4 : Symbol(v4, Decl(literalTypeWidening.ts, 10, 7)) +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 9, 9)) +} + +function f2(cond: boolean) { +>f2 : Symbol(f2, Decl(literalTypeWidening.ts, 11, 1)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 13, 12)) + + const c1 = cond ? "foo" : "bar"; // widening "foo" | widening "bar" +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 14, 9)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 13, 12)) + + const c2: "foo" | "bar" = c1; // "foo" | "bar" +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 15, 9)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 14, 9)) + + const c3 = cond ? c1 : c2; // "foo" | "bar" +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 16, 9)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 13, 12)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 14, 9)) +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 15, 9)) + + const c4 = cond ? c3 : "baz"; // "foo" | "bar" | widening "baz" +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 17, 9)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 13, 12)) +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 16, 9)) + + const c5: "foo" | "bar" | "baz" = c4; // "foo" | "bar" | "baz" +>c5 : Symbol(c5, Decl(literalTypeWidening.ts, 18, 9)) +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 17, 9)) + + let v1 = c1; // string +>v1 : Symbol(v1, Decl(literalTypeWidening.ts, 19, 7)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 14, 9)) + + let v2 = c2; // "foo" | "bar" +>v2 : Symbol(v2, Decl(literalTypeWidening.ts, 20, 7)) +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 15, 9)) + + let v3 = c3; // "foo" | "bar" +>v3 : Symbol(v3, Decl(literalTypeWidening.ts, 21, 7)) +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 16, 9)) + + let v4 = c4; // string +>v4 : Symbol(v4, Decl(literalTypeWidening.ts, 22, 7)) +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 17, 9)) + + let v5 = c5; // "foo" | "bar" | "baz" +>v5 : Symbol(v5, Decl(literalTypeWidening.ts, 23, 7)) +>c5 : Symbol(c5, Decl(literalTypeWidening.ts, 18, 9)) +} + +function f3() { +>f3 : Symbol(f3, Decl(literalTypeWidening.ts, 24, 1)) + + const c1 = 123; // Widening type 123 +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 27, 9)) + + let v1 = c1; // Type number +>v1 : Symbol(v1, Decl(literalTypeWidening.ts, 28, 7)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 27, 9)) + + const c2 = c1; // Widening type 123 +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 29, 9)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 27, 9)) + + let v2 = c2; // Type number +>v2 : Symbol(v2, Decl(literalTypeWidening.ts, 30, 7)) +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 29, 9)) + + const c3: 123 = 123; // Type 123 +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 31, 9)) + + let v3 = c3; // Type 123 +>v3 : Symbol(v3, Decl(literalTypeWidening.ts, 32, 7)) +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 31, 9)) + + const c4: 123 = c1; // Type 123 +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 33, 9)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 27, 9)) + + let v4 = c4; // Type 123 +>v4 : Symbol(v4, Decl(literalTypeWidening.ts, 34, 7)) +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 33, 9)) +} + +function f4(cond: boolean) { +>f4 : Symbol(f4, Decl(literalTypeWidening.ts, 35, 1)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 37, 12)) + + const c1 = cond ? 123 : 456; // widening 123 | widening 456 +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 38, 9)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 37, 12)) + + const c2: 123 | 456 = c1; // 123 | 456 +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 39, 9)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 38, 9)) + + const c3 = cond ? c1 : c2; // 123 | 456 +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 40, 9)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 37, 12)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 38, 9)) +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 39, 9)) + + const c4 = cond ? c3 : 789; // 123 | 456 | widening 789 +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 41, 9)) +>cond : Symbol(cond, Decl(literalTypeWidening.ts, 37, 12)) +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 40, 9)) + + const c5: 123 | 456 | 789 = c4; // 123 | 456 | 789 +>c5 : Symbol(c5, Decl(literalTypeWidening.ts, 42, 9)) +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 41, 9)) + + let v1 = c1; // number +>v1 : Symbol(v1, Decl(literalTypeWidening.ts, 43, 7)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 38, 9)) + + let v2 = c2; // 123 | 456 +>v2 : Symbol(v2, Decl(literalTypeWidening.ts, 44, 7)) +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 39, 9)) + + let v3 = c3; // 123 | 456 +>v3 : Symbol(v3, Decl(literalTypeWidening.ts, 45, 7)) +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 40, 9)) + + let v4 = c4; // number +>v4 : Symbol(v4, Decl(literalTypeWidening.ts, 46, 7)) +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 41, 9)) + + let v5 = c5; // 123 | 456 | 789 +>v5 : Symbol(v5, Decl(literalTypeWidening.ts, 47, 7)) +>c5 : Symbol(c5, Decl(literalTypeWidening.ts, 42, 9)) +} + +function f5() { +>f5 : Symbol(f5, Decl(literalTypeWidening.ts, 48, 1)) + + const c1 = "foo"; +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 51, 9)) + + let v1 = c1; +>v1 : Symbol(v1, Decl(literalTypeWidening.ts, 52, 7)) +>c1 : Symbol(c1, Decl(literalTypeWidening.ts, 51, 9)) + + const c2: "foo" = "foo"; +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 53, 9)) + + let v2 = c2; +>v2 : Symbol(v2, Decl(literalTypeWidening.ts, 54, 7)) +>c2 : Symbol(c2, Decl(literalTypeWidening.ts, 53, 9)) + + const c3 = "foo" as "foo"; +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 55, 9)) + + let v3 = c3; +>v3 : Symbol(v3, Decl(literalTypeWidening.ts, 56, 7)) +>c3 : Symbol(c3, Decl(literalTypeWidening.ts, 55, 9)) + + const c4 = <"foo">"foo"; +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 57, 9)) + + let v4 = c4; +>v4 : Symbol(v4, Decl(literalTypeWidening.ts, 58, 7)) +>c4 : Symbol(c4, Decl(literalTypeWidening.ts, 57, 9)) +} + +// Repro from #10898 + +type FAILURE = "FAILURE"; +>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5)) + +const FAILURE = "FAILURE"; +>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5)) + +type Result = T | FAILURE; +>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 66, 12)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 66, 12)) +>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5)) + +function doWork(): Result { +>doWork : Symbol(doWork, Decl(literalTypeWidening.ts, 66, 29)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 68, 16)) +>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 68, 16)) + + return FAILURE; +>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5)) +} + +function isSuccess(result: Result): result is T { +>isSuccess : Symbol(isSuccess, Decl(literalTypeWidening.ts, 70, 1)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 72, 19)) +>result : Symbol(result, Decl(literalTypeWidening.ts, 72, 22)) +>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 72, 19)) +>result : Symbol(result, Decl(literalTypeWidening.ts, 72, 22)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 72, 19)) + + return !isFailure(result); +>isFailure : Symbol(isFailure, Decl(literalTypeWidening.ts, 74, 1)) +>result : Symbol(result, Decl(literalTypeWidening.ts, 72, 22)) +} + +function isFailure(result: Result): result is FAILURE { +>isFailure : Symbol(isFailure, Decl(literalTypeWidening.ts, 74, 1)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 76, 19)) +>result : Symbol(result, Decl(literalTypeWidening.ts, 76, 22)) +>Result : Symbol(Result, Decl(literalTypeWidening.ts, 64, 26)) +>T : Symbol(T, Decl(literalTypeWidening.ts, 76, 19)) +>result : Symbol(result, Decl(literalTypeWidening.ts, 76, 22)) +>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5)) + + return result === FAILURE; +>result : Symbol(result, Decl(literalTypeWidening.ts, 76, 22)) +>FAILURE : Symbol(FAILURE, Decl(literalTypeWidening.ts, 59, 1), Decl(literalTypeWidening.ts, 64, 5)) +} + +function increment(x: number): number { +>increment : Symbol(increment, Decl(literalTypeWidening.ts, 78, 1)) +>x : Symbol(x, Decl(literalTypeWidening.ts, 80, 19)) + + return x + 1; +>x : Symbol(x, Decl(literalTypeWidening.ts, 80, 19)) +} + +let result = doWork(); +>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 3)) +>doWork : Symbol(doWork, Decl(literalTypeWidening.ts, 66, 29)) + +if (isSuccess(result)) { +>isSuccess : Symbol(isSuccess, Decl(literalTypeWidening.ts, 70, 1)) +>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 3)) + + increment(result); +>increment : Symbol(increment, Decl(literalTypeWidening.ts, 78, 1)) +>result : Symbol(result, Decl(literalTypeWidening.ts, 84, 3)) +} + +// Repro from #10898 + +type TestEvent = "onmouseover" | "onmouseout"; +>TestEvent : Symbol(TestEvent, Decl(literalTypeWidening.ts, 88, 1)) + +function onMouseOver(): TestEvent { return "onmouseover"; } +>onMouseOver : Symbol(onMouseOver, Decl(literalTypeWidening.ts, 92, 46)) +>TestEvent : Symbol(TestEvent, Decl(literalTypeWidening.ts, 88, 1)) + +let x = onMouseOver(); +>x : Symbol(x, Decl(literalTypeWidening.ts, 96, 3)) +>onMouseOver : Symbol(onMouseOver, Decl(literalTypeWidening.ts, 92, 46)) + diff --git a/tests/baselines/reference/literalTypeWidening.types b/tests/baselines/reference/literalTypeWidening.types new file mode 100644 index 0000000000000..db5df6ba90c7c --- /dev/null +++ b/tests/baselines/reference/literalTypeWidening.types @@ -0,0 +1,318 @@ +=== tests/cases/conformance/types/literal/literalTypeWidening.ts === +// Widening vs. non-widening literal types + +function f1() { +>f1 : () => void + + const c1 = "hello"; // Widening type "hello" +>c1 : "hello" +>"hello" : "hello" + + let v1 = c1; // Type string +>v1 : string +>c1 : "hello" + + const c2 = c1; // Widening type "hello" +>c2 : "hello" +>c1 : "hello" + + let v2 = c2; // Type string +>v2 : string +>c2 : "hello" + + const c3: "hello" = "hello"; // Type "hello" +>c3 : "hello" +>"hello" : "hello" + + let v3 = c3; // Type "hello" +>v3 : "hello" +>c3 : "hello" + + const c4: "hello" = c1; // Type "hello" +>c4 : "hello" +>c1 : "hello" + + let v4 = c4; // Type "hello" +>v4 : "hello" +>c4 : "hello" +} + +function f2(cond: boolean) { +>f2 : (cond: boolean) => void +>cond : boolean + + const c1 = cond ? "foo" : "bar"; // widening "foo" | widening "bar" +>c1 : "foo" | "bar" +>cond ? "foo" : "bar" : "foo" | "bar" +>cond : boolean +>"foo" : "foo" +>"bar" : "bar" + + const c2: "foo" | "bar" = c1; // "foo" | "bar" +>c2 : "foo" | "bar" +>c1 : "foo" | "bar" + + const c3 = cond ? c1 : c2; // "foo" | "bar" +>c3 : "foo" | "bar" +>cond ? c1 : c2 : "foo" | "bar" +>cond : boolean +>c1 : "foo" | "bar" +>c2 : "foo" | "bar" + + const c4 = cond ? c3 : "baz"; // "foo" | "bar" | widening "baz" +>c4 : "foo" | "bar" | "baz" +>cond ? c3 : "baz" : "foo" | "bar" | "baz" +>cond : boolean +>c3 : "foo" | "bar" +>"baz" : "baz" + + const c5: "foo" | "bar" | "baz" = c4; // "foo" | "bar" | "baz" +>c5 : "foo" | "bar" | "baz" +>c4 : "foo" | "bar" | "baz" + + let v1 = c1; // string +>v1 : string +>c1 : "foo" | "bar" + + let v2 = c2; // "foo" | "bar" +>v2 : "foo" | "bar" +>c2 : "foo" | "bar" + + let v3 = c3; // "foo" | "bar" +>v3 : "foo" | "bar" +>c3 : "foo" | "bar" + + let v4 = c4; // string +>v4 : string +>c4 : "foo" | "bar" | "baz" + + let v5 = c5; // "foo" | "bar" | "baz" +>v5 : "foo" | "bar" | "baz" +>c5 : "foo" | "bar" | "baz" +} + +function f3() { +>f3 : () => void + + const c1 = 123; // Widening type 123 +>c1 : 123 +>123 : 123 + + let v1 = c1; // Type number +>v1 : number +>c1 : 123 + + const c2 = c1; // Widening type 123 +>c2 : 123 +>c1 : 123 + + let v2 = c2; // Type number +>v2 : number +>c2 : 123 + + const c3: 123 = 123; // Type 123 +>c3 : 123 +>123 : 123 + + let v3 = c3; // Type 123 +>v3 : 123 +>c3 : 123 + + const c4: 123 = c1; // Type 123 +>c4 : 123 +>c1 : 123 + + let v4 = c4; // Type 123 +>v4 : 123 +>c4 : 123 +} + +function f4(cond: boolean) { +>f4 : (cond: boolean) => void +>cond : boolean + + const c1 = cond ? 123 : 456; // widening 123 | widening 456 +>c1 : 123 | 456 +>cond ? 123 : 456 : 123 | 456 +>cond : boolean +>123 : 123 +>456 : 456 + + const c2: 123 | 456 = c1; // 123 | 456 +>c2 : 123 | 456 +>c1 : 123 | 456 + + const c3 = cond ? c1 : c2; // 123 | 456 +>c3 : 123 | 456 +>cond ? c1 : c2 : 123 | 456 +>cond : boolean +>c1 : 123 | 456 +>c2 : 123 | 456 + + const c4 = cond ? c3 : 789; // 123 | 456 | widening 789 +>c4 : 123 | 456 | 789 +>cond ? c3 : 789 : 123 | 456 | 789 +>cond : boolean +>c3 : 123 | 456 +>789 : 789 + + const c5: 123 | 456 | 789 = c4; // 123 | 456 | 789 +>c5 : 123 | 456 | 789 +>c4 : 123 | 456 | 789 + + let v1 = c1; // number +>v1 : number +>c1 : 123 | 456 + + let v2 = c2; // 123 | 456 +>v2 : 123 | 456 +>c2 : 123 | 456 + + let v3 = c3; // 123 | 456 +>v3 : 123 | 456 +>c3 : 123 | 456 + + let v4 = c4; // number +>v4 : number +>c4 : 123 | 456 | 789 + + let v5 = c5; // 123 | 456 | 789 +>v5 : 123 | 456 | 789 +>c5 : 123 | 456 | 789 +} + +function f5() { +>f5 : () => void + + const c1 = "foo"; +>c1 : "foo" +>"foo" : "foo" + + let v1 = c1; +>v1 : string +>c1 : "foo" + + const c2: "foo" = "foo"; +>c2 : "foo" +>"foo" : "foo" + + let v2 = c2; +>v2 : "foo" +>c2 : "foo" + + const c3 = "foo" as "foo"; +>c3 : "foo" +>"foo" as "foo" : "foo" +>"foo" : "foo" + + let v3 = c3; +>v3 : "foo" +>c3 : "foo" + + const c4 = <"foo">"foo"; +>c4 : "foo" +><"foo">"foo" : "foo" +>"foo" : "foo" + + let v4 = c4; +>v4 : "foo" +>c4 : "foo" +} + +// Repro from #10898 + +type FAILURE = "FAILURE"; +>FAILURE : "FAILURE" + +const FAILURE = "FAILURE"; +>FAILURE : "FAILURE" +>"FAILURE" : "FAILURE" + +type Result = T | FAILURE; +>Result : Result +>T : T +>T : T +>FAILURE : "FAILURE" + +function doWork(): Result { +>doWork : () => Result +>T : T +>Result : Result +>T : T + + return FAILURE; +>FAILURE : "FAILURE" +} + +function isSuccess(result: Result): result is T { +>isSuccess : (result: Result) => result is T +>T : T +>result : Result +>Result : Result +>T : T +>result : any +>T : T + + return !isFailure(result); +>!isFailure(result) : boolean +>isFailure(result) : boolean +>isFailure : (result: Result) => result is "FAILURE" +>result : Result +} + +function isFailure(result: Result): result is FAILURE { +>isFailure : (result: Result) => result is "FAILURE" +>T : T +>result : Result +>Result : Result +>T : T +>result : any +>FAILURE : "FAILURE" + + return result === FAILURE; +>result === FAILURE : boolean +>result : Result +>FAILURE : "FAILURE" +} + +function increment(x: number): number { +>increment : (x: number) => number +>x : number + + return x + 1; +>x + 1 : number +>x : number +>1 : 1 +} + +let result = doWork(); +>result : Result +>doWork() : Result +>doWork : () => Result + +if (isSuccess(result)) { +>isSuccess(result) : boolean +>isSuccess : (result: Result) => result is T +>result : Result + + increment(result); +>increment(result) : number +>increment : (x: number) => number +>result : number +} + +// Repro from #10898 + +type TestEvent = "onmouseover" | "onmouseout"; +>TestEvent : TestEvent + +function onMouseOver(): TestEvent { return "onmouseover"; } +>onMouseOver : () => TestEvent +>TestEvent : TestEvent +>"onmouseover" : "onmouseover" + +let x = onMouseOver(); +>x : TestEvent +>onMouseOver() : TestEvent +>onMouseOver : () => TestEvent + From e1d5bdffd7531f32954ba62af159ba31ce9ca488 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 26 Sep 2016 12:46:39 -0700 Subject: [PATCH 10/12] String and numeric literal initializes in ambient const declarations --- src/compiler/checker.ts | 47 ++++++++++++++++++++++++---- src/compiler/declarationEmitter.ts | 4 +++ src/compiler/diagnosticMessages.json | 4 +++ src/compiler/types.ts | 2 ++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 092ef8e4e6b8d..30a4074fd6b3a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2015,6 +2015,10 @@ namespace ts { isExternalModuleAugmentation(node.parent.parent); } + function literalTypeToString(type: LiteralType) { + return type.flags & TypeFlags.StringLiteral ? `"${escapeString((type).text)}"` : (type).text; + } + function getSymbolDisplayBuilder(): SymbolDisplayBuilder { function getNameOfSymbol(symbol: Symbol): string { @@ -2190,11 +2194,8 @@ namespace ts { else if (type.flags & TypeFlags.Anonymous) { writeAnonymousType(type, nextFlags); } - else if (type.flags & TypeFlags.StringLiteral) { - writer.writeStringLiteral(`"${escapeString((type).text)}"`); - } - else if (type.flags & TypeFlags.NumberLiteral) { - writer.writeStringLiteral((type).text); + else if (type.flags & TypeFlags.StringOrNumberLiteral) { + writer.writeStringLiteral(literalTypeToString(type)); } else { // Should never get here @@ -19015,6 +19016,19 @@ namespace ts { return undefined; } + function isLiteralConstDeclaration(node: VariableDeclaration): boolean { + if (isConst(node)) { + const type = getTypeOfSymbol(getSymbolOfNode(node)); + return !!(type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral); + } + return false; + } + + function writeLiteralConstValue(node: VariableDeclaration, writer: SymbolWriter) { + const type = getTypeOfSymbol(getSymbolOfNode(node)); + writer.writeStringLiteral(literalTypeToString(type)); + } + function createResolver(): EmitResolver { // this variable and functions that use it are deliberately moved here from the outer scope // to avoid scope pollution @@ -19059,7 +19073,9 @@ namespace ts { isArgumentsLocalBinding, getExternalModuleFileFromDeclaration, getTypeReferenceDirectivesForEntityName, - getTypeReferenceDirectivesForSymbol + getTypeReferenceDirectivesForSymbol, + isLiteralConstDeclaration, + writeLiteralConstValue }; // defined here to avoid outer scope pollution @@ -20205,10 +20221,29 @@ namespace ts { } } + function isStringOrNumberLiteralExpression(expr: Expression) { + return expr.kind === SyntaxKind.StringLiteral || expr.kind === SyntaxKind.NumericLiteral || + expr.kind === SyntaxKind.PrefixUnaryExpression && (expr).operator === SyntaxKind.MinusToken && + (expr).operand.kind === SyntaxKind.NumericLiteral; + } + function checkGrammarVariableDeclaration(node: VariableDeclaration) { if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) { if (isInAmbientContext(node)) { if (node.initializer) { + if (isConst(node) && !node.type) { + if (!isStringOrNumberLiteralExpression(node.initializer)) { + return grammarErrorOnNode(node.initializer, Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal); + } + } + else { + // Error on equals token which immediate precedes the initializer + const equalsTokenLength = "=".length; + return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, + equalsTokenLength, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); + } + } + if (node.initializer && !(isConst(node) && isStringOrNumberLiteralExpression(node.initializer))) { // Error on equals token which immediate precedes the initializer const equalsTokenLength = "=".length; return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - equalsTokenLength, diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index a015ad79b9791..dfca14bd0d1c2 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1142,6 +1142,10 @@ namespace ts { if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) { emitTypeOfVariableDeclarationFromTypeLiteral(node); } + else if (resolver.isLiteralConstDeclaration(node)) { + write(" = "); + resolver.writeLiteralConstValue(node, writer); + } else if (!hasModifier(node, ModifierFlags.Private)) { writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index be4ee2fa07d98..11eb12bb2b418 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -819,6 +819,10 @@ "category": "Error", "code": 1253 }, + "A 'const' initializer in an ambient context must be a string or numeric literal.": { + "category": "Error", + "code": 1254 + }, "'with' statements are not allowed in an async function block.": { "category": "Error", "code": 1300 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8b5b2f1f25fba..c69d2aee3f124 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2156,6 +2156,8 @@ namespace ts { getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile; getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[]; getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; + isLiteralConstDeclaration(node: VariableDeclaration): boolean; + writeLiteralConstValue(node: VariableDeclaration, writer: SymbolWriter): void; } export const enum SymbolFlags { From 791ae5b3c9ec490365d392409c283943af02995e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 26 Sep 2016 12:47:14 -0700 Subject: [PATCH 11/12] Accept new baselines --- .../constDeclarations-ambient-errors.errors.txt | 11 ++++------- tests/baselines/reference/constDeclarations.js | 2 +- tests/baselines/reference/constDeclarations2.js | 2 +- .../declarationEmitClassMemberNameConflict2.js | 2 +- ...orthandOfExportedEntity01_targetES2015_CommonJS.js | 2 +- .../shorthandOfExportedEntity02_targetES5_CommonJS.js | 2 +- .../reference/stringLiteralTypesOverloads02.js | 6 +++--- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/baselines/reference/constDeclarations-ambient-errors.errors.txt b/tests/baselines/reference/constDeclarations-ambient-errors.errors.txt index 6e2d00dc4c42c..2ecc7fc7ed322 100644 --- a/tests/baselines/reference/constDeclarations-ambient-errors.errors.txt +++ b/tests/baselines/reference/constDeclarations-ambient-errors.errors.txt @@ -1,13 +1,12 @@ tests/cases/compiler/constDeclarations-ambient-errors.ts(3,27): error TS1039: Initializers are not allowed in ambient contexts. tests/cases/compiler/constDeclarations-ambient-errors.ts(4,26): error TS1039: Initializers are not allowed in ambient contexts. -tests/cases/compiler/constDeclarations-ambient-errors.ts(5,18): error TS1039: Initializers are not allowed in ambient contexts. +tests/cases/compiler/constDeclarations-ambient-errors.ts(5,20): error TS1254: A 'const' initializer in an ambient context must be a string or numeric literal. tests/cases/compiler/constDeclarations-ambient-errors.ts(5,37): error TS1039: Initializers are not allowed in ambient contexts. tests/cases/compiler/constDeclarations-ambient-errors.ts(5,51): error TS1039: Initializers are not allowed in ambient contexts. -tests/cases/compiler/constDeclarations-ambient-errors.ts(8,14): error TS1039: Initializers are not allowed in ambient contexts. tests/cases/compiler/constDeclarations-ambient-errors.ts(9,22): error TS1039: Initializers are not allowed in ambient contexts. -==== tests/cases/compiler/constDeclarations-ambient-errors.ts (7 errors) ==== +==== tests/cases/compiler/constDeclarations-ambient-errors.ts (6 errors) ==== // error: no intialization expected in ambient declarations declare const c1: boolean = true; @@ -17,8 +16,8 @@ tests/cases/compiler/constDeclarations-ambient-errors.ts(9,22): error TS1039: In ~ !!! error TS1039: Initializers are not allowed in ambient contexts. declare const c3 = null, c4 :string = "", c5: any = 0; - ~ -!!! error TS1039: Initializers are not allowed in ambient contexts. + ~~~~ +!!! error TS1254: A 'const' initializer in an ambient context must be a string or numeric literal. ~ !!! error TS1039: Initializers are not allowed in ambient contexts. ~ @@ -26,8 +25,6 @@ tests/cases/compiler/constDeclarations-ambient-errors.ts(9,22): error TS1039: In declare module M { const c6 = 0; - ~ -!!! error TS1039: Initializers are not allowed in ambient contexts. const c7: number = 7; ~ !!! error TS1039: Initializers are not allowed in ambient contexts. diff --git a/tests/baselines/reference/constDeclarations.js b/tests/baselines/reference/constDeclarations.js index 060c0aba61cd6..00d0a61ef9b7b 100644 --- a/tests/baselines/reference/constDeclarations.js +++ b/tests/baselines/reference/constDeclarations.js @@ -27,4 +27,4 @@ for (const c5 = 0, c6 = 0; c5 < c6;) { //// [constDeclarations.d.ts] declare const c1: boolean; declare const c2: number; -declare const c3: number, c4: string, c5: any; +declare const c3 = 0, c4: string, c5: any; diff --git a/tests/baselines/reference/constDeclarations2.js b/tests/baselines/reference/constDeclarations2.js index e4ee67ebdcdd0..0c372924b50ca 100644 --- a/tests/baselines/reference/constDeclarations2.js +++ b/tests/baselines/reference/constDeclarations2.js @@ -22,5 +22,5 @@ var M; declare module M { const c1: boolean; const c2: number; - const c3: number, c4: string, c5: any; + const c3 = 0, c4: string, c5: any; } diff --git a/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js b/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js index 6e18377d30f15..c5f8203a659e0 100644 --- a/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js +++ b/tests/baselines/reference/declarationEmitClassMemberNameConflict2.js @@ -45,7 +45,7 @@ var Foo = (function () { //// [declarationEmitClassMemberNameConflict2.d.ts] -declare const Bar: string; +declare const Bar = "bar"; declare enum Hello { World = 0, } diff --git a/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js b/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js index 9e057951b3a66..c1728d68e9bbf 100644 --- a/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js +++ b/tests/baselines/reference/shorthandOfExportedEntity01_targetES2015_CommonJS.js @@ -17,5 +17,5 @@ exports.foo = foo; //// [shorthandOfExportedEntity01_targetES2015_CommonJS.d.ts] -export declare const test: string; +export declare const test = "test"; export declare function foo(): void; diff --git a/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js b/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js index 764739705c4e1..e89a413463e25 100644 --- a/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js +++ b/tests/baselines/reference/shorthandOfExportedEntity02_targetES5_CommonJS.js @@ -17,5 +17,5 @@ exports.foo = foo; //// [shorthandOfExportedEntity02_targetES5_CommonJS.d.ts] -export declare const test: string; +export declare const test = "test"; export declare function foo(): void; diff --git a/tests/baselines/reference/stringLiteralTypesOverloads02.js b/tests/baselines/reference/stringLiteralTypesOverloads02.js index 184af2d74b73a..c0a7622075aef 100644 --- a/tests/baselines/reference/stringLiteralTypesOverloads02.js +++ b/tests/baselines/reference/stringLiteralTypesOverloads02.js @@ -100,9 +100,9 @@ declare function getFalsyPrimitive(x: "number" | "string"): number | string; declare function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; declare namespace Consts1 { } -declare const string: string; -declare const number: string; -declare const boolean: string; +declare const string = "string"; +declare const number = "number"; +declare const boolean = "boolean"; declare const stringOrNumber: string; declare const stringOrBoolean: string; declare const booleanOrNumber: string; From b6b8e8c3080ab312f8f55b0ef597e385ae9d27b7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 26 Sep 2016 12:47:22 -0700 Subject: [PATCH 12/12] Add tests --- .../reference/ambientConstLiterals.js | 72 ++++++++++++ .../reference/ambientConstLiterals.symbols | 75 +++++++++++++ .../reference/ambientConstLiterals.types | 105 ++++++++++++++++++ tests/cases/compiler/ambientConstLiterals.ts | 22 ++++ 4 files changed, 274 insertions(+) create mode 100644 tests/baselines/reference/ambientConstLiterals.js create mode 100644 tests/baselines/reference/ambientConstLiterals.symbols create mode 100644 tests/baselines/reference/ambientConstLiterals.types create mode 100644 tests/cases/compiler/ambientConstLiterals.ts diff --git a/tests/baselines/reference/ambientConstLiterals.js b/tests/baselines/reference/ambientConstLiterals.js new file mode 100644 index 0000000000000..4a590826b1d80 --- /dev/null +++ b/tests/baselines/reference/ambientConstLiterals.js @@ -0,0 +1,72 @@ +//// [ambientConstLiterals.ts] + +function f(x: T): T { + return x; +} + +enum E { A, B, C } + +const c1 = "abc"; +const c2 = 123; +const c3 = c1; +const c4 = c2; +const c5 = f(123); +const c6 = f(-123); +const c7 = true; +const c8 = E.A; +const c9 = { x: "abc" }; +const c10 = [123]; +const c11 = "abc" + "def"; +const c12 = 123 + 456; +const c13 = Math.random() > 0.5 ? "abc" : "def"; +const c14 = Math.random() > 0.5 ? 123 : 456; + +//// [ambientConstLiterals.js] +function f(x) { + return x; +} +var E; +(function (E) { + E[E["A"] = 0] = "A"; + E[E["B"] = 1] = "B"; + E[E["C"] = 2] = "C"; +})(E || (E = {})); +var c1 = "abc"; +var c2 = 123; +var c3 = c1; +var c4 = c2; +var c5 = f(123); +var c6 = f(-123); +var c7 = true; +var c8 = E.A; +var c9 = { x: "abc" }; +var c10 = [123]; +var c11 = "abc" + "def"; +var c12 = 123 + 456; +var c13 = Math.random() > 0.5 ? "abc" : "def"; +var c14 = Math.random() > 0.5 ? 123 : 456; + + +//// [ambientConstLiterals.d.ts] +declare function f(x: T): T; +declare enum E { + A = 0, + B = 1, + C = 2, +} +declare const c1 = "abc"; +declare const c2 = 123; +declare const c3 = "abc"; +declare const c4 = 123; +declare const c5 = 123; +declare const c6 = -123; +declare const c7: boolean; +declare const c8: E; +declare const c9: { + x: string; +}; +declare const c10: number[]; +declare const c11: string; +declare const c12: number; +declare const c13: string; +declare const c14: number; diff --git a/tests/baselines/reference/ambientConstLiterals.symbols b/tests/baselines/reference/ambientConstLiterals.symbols new file mode 100644 index 0000000000000..67d168a07502f --- /dev/null +++ b/tests/baselines/reference/ambientConstLiterals.symbols @@ -0,0 +1,75 @@ +=== tests/cases/compiler/ambientConstLiterals.ts === + +function f(x: T): T { +>f : Symbol(f, Decl(ambientConstLiterals.ts, 0, 0)) +>T : Symbol(T, Decl(ambientConstLiterals.ts, 1, 11)) +>x : Symbol(x, Decl(ambientConstLiterals.ts, 1, 14)) +>T : Symbol(T, Decl(ambientConstLiterals.ts, 1, 11)) +>T : Symbol(T, Decl(ambientConstLiterals.ts, 1, 11)) + + return x; +>x : Symbol(x, Decl(ambientConstLiterals.ts, 1, 14)) +} + +enum E { A, B, C } +>E : Symbol(E, Decl(ambientConstLiterals.ts, 3, 1)) +>A : Symbol(E.A, Decl(ambientConstLiterals.ts, 5, 8)) +>B : Symbol(E.B, Decl(ambientConstLiterals.ts, 5, 11)) +>C : Symbol(E.C, Decl(ambientConstLiterals.ts, 5, 14)) + +const c1 = "abc"; +>c1 : Symbol(c1, Decl(ambientConstLiterals.ts, 7, 5)) + +const c2 = 123; +>c2 : Symbol(c2, Decl(ambientConstLiterals.ts, 8, 5)) + +const c3 = c1; +>c3 : Symbol(c3, Decl(ambientConstLiterals.ts, 9, 5)) +>c1 : Symbol(c1, Decl(ambientConstLiterals.ts, 7, 5)) + +const c4 = c2; +>c4 : Symbol(c4, Decl(ambientConstLiterals.ts, 10, 5)) +>c2 : Symbol(c2, Decl(ambientConstLiterals.ts, 8, 5)) + +const c5 = f(123); +>c5 : Symbol(c5, Decl(ambientConstLiterals.ts, 11, 5)) +>f : Symbol(f, Decl(ambientConstLiterals.ts, 0, 0)) + +const c6 = f(-123); +>c6 : Symbol(c6, Decl(ambientConstLiterals.ts, 12, 5)) +>f : Symbol(f, Decl(ambientConstLiterals.ts, 0, 0)) + +const c7 = true; +>c7 : Symbol(c7, Decl(ambientConstLiterals.ts, 13, 5)) + +const c8 = E.A; +>c8 : Symbol(c8, Decl(ambientConstLiterals.ts, 14, 5)) +>E.A : Symbol(E.A, Decl(ambientConstLiterals.ts, 5, 8)) +>E : Symbol(E, Decl(ambientConstLiterals.ts, 3, 1)) +>A : Symbol(E.A, Decl(ambientConstLiterals.ts, 5, 8)) + +const c9 = { x: "abc" }; +>c9 : Symbol(c9, Decl(ambientConstLiterals.ts, 15, 5)) +>x : Symbol(x, Decl(ambientConstLiterals.ts, 15, 12)) + +const c10 = [123]; +>c10 : Symbol(c10, Decl(ambientConstLiterals.ts, 16, 5)) + +const c11 = "abc" + "def"; +>c11 : Symbol(c11, Decl(ambientConstLiterals.ts, 17, 5)) + +const c12 = 123 + 456; +>c12 : Symbol(c12, Decl(ambientConstLiterals.ts, 18, 5)) + +const c13 = Math.random() > 0.5 ? "abc" : "def"; +>c13 : Symbol(c13, Decl(ambientConstLiterals.ts, 19, 5)) +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + +const c14 = Math.random() > 0.5 ? 123 : 456; +>c14 : Symbol(c14, Decl(ambientConstLiterals.ts, 20, 5)) +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/ambientConstLiterals.types b/tests/baselines/reference/ambientConstLiterals.types new file mode 100644 index 0000000000000..8b6fc98462881 --- /dev/null +++ b/tests/baselines/reference/ambientConstLiterals.types @@ -0,0 +1,105 @@ +=== tests/cases/compiler/ambientConstLiterals.ts === + +function f(x: T): T { +>f : (x: T) => T +>T : T +>x : T +>T : T +>T : T + + return x; +>x : T +} + +enum E { A, B, C } +>E : E +>A : E.A +>B : E.B +>C : E.C + +const c1 = "abc"; +>c1 : "abc" +>"abc" : "abc" + +const c2 = 123; +>c2 : 123 +>123 : 123 + +const c3 = c1; +>c3 : "abc" +>c1 : "abc" + +const c4 = c2; +>c4 : 123 +>c2 : 123 + +const c5 = f(123); +>c5 : 123 +>f(123) : 123 +>f : (x: T) => T +>123 : 123 + +const c6 = f(-123); +>c6 : -123 +>f(-123) : -123 +>f : (x: T) => T +>-123 : -123 +>123 : 123 + +const c7 = true; +>c7 : true +>true : true + +const c8 = E.A; +>c8 : E.A +>E.A : E.A +>E : typeof E +>A : E.A + +const c9 = { x: "abc" }; +>c9 : { x: string; } +>{ x: "abc" } : { x: string; } +>x : string +>"abc" : "abc" + +const c10 = [123]; +>c10 : number[] +>[123] : number[] +>123 : 123 + +const c11 = "abc" + "def"; +>c11 : string +>"abc" + "def" : string +>"abc" : "abc" +>"def" : "def" + +const c12 = 123 + 456; +>c12 : number +>123 + 456 : number +>123 : 123 +>456 : 456 + +const c13 = Math.random() > 0.5 ? "abc" : "def"; +>c13 : "abc" | "def" +>Math.random() > 0.5 ? "abc" : "def" : "abc" | "def" +>Math.random() > 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>"abc" : "abc" +>"def" : "def" + +const c14 = Math.random() > 0.5 ? 123 : 456; +>c14 : 123 | 456 +>Math.random() > 0.5 ? 123 : 456 : 123 | 456 +>Math.random() > 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>123 : 123 +>456 : 456 + diff --git a/tests/cases/compiler/ambientConstLiterals.ts b/tests/cases/compiler/ambientConstLiterals.ts new file mode 100644 index 0000000000000..040b739bf9345 --- /dev/null +++ b/tests/cases/compiler/ambientConstLiterals.ts @@ -0,0 +1,22 @@ +// @declaration: true + +function f(x: T): T { + return x; +} + +enum E { A, B, C } + +const c1 = "abc"; +const c2 = 123; +const c3 = c1; +const c4 = c2; +const c5 = f(123); +const c6 = f(-123); +const c7 = true; +const c8 = E.A; +const c9 = { x: "abc" }; +const c10 = [123]; +const c11 = "abc" + "def"; +const c12 = 123 + 456; +const c13 = Math.random() > 0.5 ? "abc" : "def"; +const c14 = Math.random() > 0.5 ? 123 : 456; \ No newline at end of file