From cd7f039fd7ddf33395a4ea0ec1ec59359a455ad3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 31 Jan 2023 16:58:51 -0800 Subject: [PATCH 1/6] Widening and non-widening computed enum types --- src/compiler/checker.ts | 47 +++++++++++++++++++++++++---------------- src/compiler/types.ts | 19 ++++++++--------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a01c44bf6aaff..18993ccc2cf3a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -157,6 +157,7 @@ import { entityNameToString, EnumDeclaration, EnumMember, + EnumType, equateValues, escapeLeadingUnderscores, escapeString, @@ -9654,8 +9655,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const t = types[i]; flags |= t.flags; if (!(t.flags & TypeFlags.Nullable)) { - if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLiteral)) { - const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(t as LiteralType); + if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLike)) { + const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLikeType(t as LiteralType); if (baseType.flags & TypeFlags.Union) { const count = (baseType as UnionType).types.length; if (i + count <= types.length && getRegularTypeOfLiteralType(types[i + count - 1]) === getRegularTypeOfLiteralType((baseType as UnionType).types[count - 1])) { @@ -11898,8 +11899,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.declaredType; } - function getBaseTypeOfEnumLiteralType(type: Type) { - return type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type; + function getBaseTypeOfEnumLikeType(type: Type) { + return type.flags & TypeFlags.EnumLike && type.symbol.flags & SymbolFlags.EnumMember ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type; } function getDeclaredTypeOfEnum(symbol: Symbol): Type { @@ -11913,9 +11914,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (hasBindableName(member)) { const memberSymbol = getSymbolOfDeclaration(member); const value = getEnumMemberValue(member); - const memberType = value !== undefined ? - getFreshTypeOfLiteralType(getEnumLiteralType(value, getSymbolId(symbol), memberSymbol)) : - createTypeWithSymbol(TypeFlags.Enum, memberSymbol); + const memberType = getFreshTypeOfLiteralType(value !== undefined ? + getEnumLiteralType(value, getSymbolId(symbol), memberSymbol) : + createComputedEnumType(memberSymbol)); getSymbolLinks(memberSymbol).declaredType = memberType; memberTypeList.push(getRegularTypeOfLiteralType(memberType)); } @@ -11925,7 +11926,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const enumType = memberTypeList.length ? getUnionType(memberTypeList, UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined) : - createTypeWithSymbol(TypeFlags.Enum, symbol); + createComputedEnumType(symbol); if (enumType.flags & TypeFlags.Union) { enumType.flags |= TypeFlags.EnumLiteral; enumType.symbol = symbol; @@ -11935,6 +11936,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.declaredType; } + function createComputedEnumType(symbol: Symbol) { + const regularType = createTypeWithSymbol(TypeFlags.Enum, symbol) as EnumType; + const freshType = createTypeWithSymbol(TypeFlags.Enum, symbol) as EnumType; + regularType.regularType = regularType; + regularType.freshType = freshType; + freshType.regularType = regularType; + freshType.freshType = freshType; + return regularType; + } + function getDeclaredTypeOfEnumMember(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { @@ -16176,7 +16187,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { orderedRemoveItemAt(typeSet, 1); } } - if (includes & (TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) { + if (includes & (TypeFlags.Enum | TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) { removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & UnionReduction.Subtype)); } if (includes & TypeFlags.StringLiteral && includes & TypeFlags.TemplateLiteral) { @@ -18026,25 +18037,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getFreshTypeOfLiteralType(type: Type): Type { - if (type.flags & TypeFlags.Literal) { - if (!(type as LiteralType).freshType) { + if (type.flags & TypeFlags.Freshable) { + if (!(type as FreshableType).freshType) { const freshType = createLiteralType(type.flags, (type as LiteralType).value, (type as LiteralType).symbol, type as LiteralType); freshType.freshType = freshType; - (type as LiteralType).freshType = freshType; + (type as FreshableType).freshType = freshType; } - return (type as LiteralType).freshType; + return (type as FreshableType).freshType; } return type; } function getRegularTypeOfLiteralType(type: Type): Type { - return type.flags & TypeFlags.Literal ? (type as LiteralType).regularType : + return type.flags & TypeFlags.Freshable ? (type as FreshableType).regularType : type.flags & TypeFlags.Union ? ((type as UnionType).regularType || ((type as UnionType).regularType = mapType(type, getRegularTypeOfLiteralType) as UnionType)) : type; } function isFreshLiteralType(type: Type) { - return !!(type.flags & TypeFlags.Literal) && (type as LiteralType).freshType === type; + return !!(type.flags & TypeFlags.Freshable) && (type as LiteralType).freshType === type; } function getStringLiteralType(value: string): StringLiteralType { @@ -22935,7 +22946,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getBaseTypeOfLiteralType(type: Type): Type { - return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type as LiteralType) : + return type.flags & TypeFlags.EnumLike ? getBaseTypeOfEnumLikeType(type as LiteralType) : type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType : type.flags & TypeFlags.NumberLiteral ? numberType : type.flags & TypeFlags.BigIntLiteral ? bigintType : @@ -22950,7 +22961,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getWidenedLiteralType(type: Type): Type { - return type.flags & TypeFlags.EnumLiteral && isFreshLiteralType(type) ? getBaseTypeOfEnumLiteralType(type as LiteralType) : + return type.flags & TypeFlags.EnumLike && isFreshLiteralType(type) ? getBaseTypeOfEnumLikeType(type as LiteralType) : type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType : type.flags & TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType : type.flags & TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType : @@ -25587,7 +25598,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return true; } - if (source.flags & TypeFlags.EnumLiteral && getBaseTypeOfEnumLiteralType(source as LiteralType) === target) { + if (source.flags & TypeFlags.EnumLike && getBaseTypeOfEnumLikeType(source as LiteralType) === target) { return true; } return containsType(target.types, source); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0a43afe978ea4..341262be7ebb6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6028,7 +6028,8 @@ export const enum TypeFlags { /** @internal */ Nullable = Undefined | Null, Literal = StringLiteral | NumberLiteral | BigIntLiteral | BooleanLiteral, - Unit = Literal | UniqueESSymbol | Nullable, + Unit = Enum | Literal | UniqueESSymbol | Nullable, + Freshable = Enum | Literal, StringOrNumberLiteral = StringLiteral | NumberLiteral, /** @internal */ StringOrNumberLiteralOrUnique = StringLiteral | NumberLiteral | UniqueESSymbol, @@ -6122,22 +6123,20 @@ export interface NullableType extends IntrinsicType { objectFlags: ObjectFlags; } -/** @internal */ -export interface FreshableIntrinsicType extends IntrinsicType { - freshType: IntrinsicType; // Fresh version of type - regularType: IntrinsicType; // Regular version of type +export interface FreshableType extends Type { + freshType: FreshableType; // Fresh version of type + regularType: FreshableType; // Regular version of type } /** @internal */ -export type FreshableType = LiteralType | FreshableIntrinsicType; +export interface FreshableIntrinsicType extends FreshableType, IntrinsicType { +} // String literal types (TypeFlags.StringLiteral) // Numeric literal types (TypeFlags.NumberLiteral) // BigInt literal types (TypeFlags.BigIntLiteral) -export interface LiteralType extends Type { +export interface LiteralType extends FreshableType { value: string | number | PseudoBigInt; // Value of literal - freshType: LiteralType; // Fresh version of type - regularType: LiteralType; // Regular version of type } // Unique symbol types (TypeFlags.UniqueESSymbol) @@ -6159,7 +6158,7 @@ export interface BigIntLiteralType extends LiteralType { } // Enum types (TypeFlags.Enum) -export interface EnumType extends Type { +export interface EnumType extends FreshableType { } // Types included in TypeFlags.ObjectFlagsType have an objectFlags property. Some ObjectFlags From 340dae5dba80cbca2e9778185716c8035220409a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 31 Jan 2023 16:59:36 -0800 Subject: [PATCH 2/6] Accept new baselines --- tests/baselines/reference/ambientDeclarations.types | 2 +- tests/baselines/reference/ambientEnum1.types | 2 +- tests/baselines/reference/ambientErrors.types | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 13 ++++++++----- tests/baselines/reference/api/typescript.d.ts | 13 ++++++++----- ...eclarationEmitForGlobalishSpecifierSymlink.types | 4 ++-- ...clarationEmitForGlobalishSpecifierSymlink2.types | 2 +- .../disallowLineTerminatorBeforeArrow.types | 2 +- tests/baselines/reference/enumBasics.types | 8 ++++---- tests/baselines/reference/enumErrors.types | 2 +- tests/baselines/reference/enumMerging.types | 4 ++-- tests/baselines/reference/enumWithExport.types | 2 +- .../reference/methodContainingLocalFunction.types | 2 +- .../moduleLocalImportNotIncorrectlyRedirected.types | 2 +- .../baselines/reference/numericEnumMappedType.types | 2 +- .../this_inside-enum-should-not-be-allowed.types | 4 ++-- 16 files changed, 36 insertions(+), 30 deletions(-) diff --git a/tests/baselines/reference/ambientDeclarations.types b/tests/baselines/reference/ambientDeclarations.types index 00d32716118a9..1ed180abaf57d 100644 --- a/tests/baselines/reference/ambientDeclarations.types +++ b/tests/baselines/reference/ambientDeclarations.types @@ -118,7 +118,7 @@ declare enum E3 { >E3 : E3 A ->A : E3 +>A : E3.A } declare module E3 { >E3 : typeof E3 diff --git a/tests/baselines/reference/ambientEnum1.types b/tests/baselines/reference/ambientEnum1.types index 29573226568b8..bb2dd24513dd2 100644 --- a/tests/baselines/reference/ambientEnum1.types +++ b/tests/baselines/reference/ambientEnum1.types @@ -12,7 +12,7 @@ >E2 : E2 x = 'foo'.length ->x : E2 +>x : E2.x >'foo'.length : number >'foo' : "foo" >length : number diff --git a/tests/baselines/reference/ambientErrors.types b/tests/baselines/reference/ambientErrors.types index 24aebd357acd4..2fa301147972f 100644 --- a/tests/baselines/reference/ambientErrors.types +++ b/tests/baselines/reference/ambientErrors.types @@ -55,7 +55,7 @@ declare enum E2 { >E2 : E2 x = 'foo'.length ->x : E2 +>x : E2.x >'foo'.length : number >'foo' : "foo" >length : number diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 65f9a35b41dc6..aacb405346da6 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6659,7 +6659,8 @@ declare namespace ts { TemplateLiteral = 134217728, StringMapping = 268435456, Literal = 2944, - Unit = 109440, + Unit = 109472, + Freshable = 2976, StringOrNumberLiteral = 384, PossiblyFalsy = 117724, StringLike = 402653316, @@ -6711,10 +6712,12 @@ declare namespace ts { isClass(): this is InterfaceType; isIndexType(): this is IndexType; } - interface LiteralType extends Type { + interface FreshableType extends Type { + freshType: FreshableType; + regularType: FreshableType; + } + interface LiteralType extends FreshableType { value: string | number | PseudoBigInt; - freshType: LiteralType; - regularType: LiteralType; } interface UniqueESSymbolType extends Type { symbol: Symbol; @@ -6729,7 +6732,7 @@ declare namespace ts { interface BigIntLiteralType extends LiteralType { value: PseudoBigInt; } - interface EnumType extends Type { + interface EnumType extends FreshableType { } enum ObjectFlags { None = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index e973a18179380..b1df6e30f2ab7 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2684,7 +2684,8 @@ declare namespace ts { TemplateLiteral = 134217728, StringMapping = 268435456, Literal = 2944, - Unit = 109440, + Unit = 109472, + Freshable = 2976, StringOrNumberLiteral = 384, PossiblyFalsy = 117724, StringLike = 402653316, @@ -2736,10 +2737,12 @@ declare namespace ts { isClass(): this is InterfaceType; isIndexType(): this is IndexType; } - interface LiteralType extends Type { + interface FreshableType extends Type { + freshType: FreshableType; + regularType: FreshableType; + } + interface LiteralType extends FreshableType { value: string | number | PseudoBigInt; - freshType: LiteralType; - regularType: LiteralType; } interface UniqueESSymbolType extends Type { symbol: Symbol; @@ -2754,7 +2757,7 @@ declare namespace ts { interface BigIntLiteralType extends LiteralType { value: PseudoBigInt; } - interface EnumType extends Type { + interface EnumType extends FreshableType { } enum ObjectFlags { None = 0, diff --git a/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink.types b/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink.types index b42d42019b48a..1ef98b00f27c9 100644 --- a/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink.types +++ b/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink.types @@ -6,7 +6,7 @@ export enum A { >A : A Val ->Val : A +>Val : A.Val } === /p1/node_modules/typescript-fsa/index.d.ts === @@ -19,7 +19,7 @@ export enum A { >A : A Val ->Val : A +>Val : A.Val } === /p2/node_modules/typescript-fsa/index.d.ts === diff --git a/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink2.types b/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink2.types index a52f51708abeb..1b09ebbd5abad 100644 --- a/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink2.types +++ b/tests/baselines/reference/declarationEmitForGlobalishSpecifierSymlink2.types @@ -6,7 +6,7 @@ export enum A { >A : A Val ->Val : A +>Val : A.Val } === /cache/typescript-fsa/index.d.ts === diff --git a/tests/baselines/reference/disallowLineTerminatorBeforeArrow.types b/tests/baselines/reference/disallowLineTerminatorBeforeArrow.types index 8cab0d7834e9a..acee84d94b375 100644 --- a/tests/baselines/reference/disallowLineTerminatorBeforeArrow.types +++ b/tests/baselines/reference/disallowLineTerminatorBeforeArrow.types @@ -194,7 +194,7 @@ module m { >Enum : Enum claw = (() ->claw : Enum +>claw : Enum.claw >(() => 10)() : number >(() => 10) : () => number >() => 10 : () => number diff --git a/tests/baselines/reference/enumBasics.types b/tests/baselines/reference/enumBasics.types index bd771393b654b..ea968381f7b98 100644 --- a/tests/baselines/reference/enumBasics.types +++ b/tests/baselines/reference/enumBasics.types @@ -140,7 +140,7 @@ enum E7 { >E7 : E7 A = 'foo'['foo'] ->A : E7 +>A : E7.A >'foo'['foo'] : error >'foo' : "foo" >'foo' : "foo" @@ -151,7 +151,7 @@ enum E8 { >E8 : E8 B = 'foo'['foo'] ->B : E8 +>B : E8.B >'foo'['foo'] : error >'foo' : "foo" >'foo' : "foo" @@ -172,8 +172,8 @@ enum E9 { // (refer to .js to validate) // Enum constant members are propagated var doNotPropagate = [ ->doNotPropagate : (E8 | E7 | E4.Z | E3)[] ->[ E8.B, E7.A, E4.Z, E3.X, E3.Y, E3.Z] : (E8 | E7 | E4.Z | E3)[] +>doNotPropagate : (E8 | E7 | E4 | E3)[] +>[ E8.B, E7.A, E4.Z, E3.X, E3.Y, E3.Z] : (E8 | E7 | E4 | E3)[] E8.B, E7.A, E4.Z, E3.X, E3.Y, E3.Z >E8.B : E8 diff --git a/tests/baselines/reference/enumErrors.types b/tests/baselines/reference/enumErrors.types index ca87dfbb2df8e..45aed1d555706 100644 --- a/tests/baselines/reference/enumErrors.types +++ b/tests/baselines/reference/enumErrors.types @@ -17,7 +17,7 @@ enum E5 { >E5 : E5 C = new Number(30) ->C : E5 +>C : E5.C >new Number(30) : Number >Number : NumberConstructor >30 : 30 diff --git a/tests/baselines/reference/enumMerging.types b/tests/baselines/reference/enumMerging.types index af81a4c93d20f..73baf33121f8e 100644 --- a/tests/baselines/reference/enumMerging.types +++ b/tests/baselines/reference/enumMerging.types @@ -111,8 +111,8 @@ module M2 { } var x = [EComp2.A, EComp2.B, EComp2.C, EComp2.D, EComp2.E, EComp2.F]; ->x : (EComp2.A | EComp2.B | EComp2.C | EComp2.D | EComp2.E | EComp2.F)[] ->[EComp2.A, EComp2.B, EComp2.C, EComp2.D, EComp2.E, EComp2.F] : (EComp2.A | EComp2.B | EComp2.C | EComp2.D | EComp2.E | EComp2.F)[] +>x : EComp2[] +>[EComp2.A, EComp2.B, EComp2.C, EComp2.D, EComp2.E, EComp2.F] : EComp2[] >EComp2.A : EComp2.A >EComp2 : typeof EComp2 >A : EComp2.A diff --git a/tests/baselines/reference/enumWithExport.types b/tests/baselines/reference/enumWithExport.types index cfcf773ff8349..e616e9d4e1f86 100644 --- a/tests/baselines/reference/enumWithExport.types +++ b/tests/baselines/reference/enumWithExport.types @@ -10,6 +10,6 @@ enum x { >x : x z = y ->z : x +>z : x.z >y : any } diff --git a/tests/baselines/reference/methodContainingLocalFunction.types b/tests/baselines/reference/methodContainingLocalFunction.types index 91e8a8263e0f1..7d1ba7a45144e 100644 --- a/tests/baselines/reference/methodContainingLocalFunction.types +++ b/tests/baselines/reference/methodContainingLocalFunction.types @@ -105,7 +105,7 @@ enum E { >E : E A = (() => { ->A : E +>A : E.A >(() => { function localFunction() { } var x: { (): void; }; x = localFunction; return 0; })() : number >(() => { function localFunction() { } var x: { (): void; }; x = localFunction; return 0; }) : () => number >() => { function localFunction() { } var x: { (): void; }; x = localFunction; return 0; } : () => number diff --git a/tests/baselines/reference/moduleLocalImportNotIncorrectlyRedirected.types b/tests/baselines/reference/moduleLocalImportNotIncorrectlyRedirected.types index 3770534c7ca5f..9ca1db661323d 100644 --- a/tests/baselines/reference/moduleLocalImportNotIncorrectlyRedirected.types +++ b/tests/baselines/reference/moduleLocalImportNotIncorrectlyRedirected.types @@ -15,5 +15,5 @@ export declare enum Position { >Position : Position top, ->top : Position +>top : Position.top } diff --git a/tests/baselines/reference/numericEnumMappedType.types b/tests/baselines/reference/numericEnumMappedType.types index 56d4815af72c2..21417ba357812 100644 --- a/tests/baselines/reference/numericEnumMappedType.types +++ b/tests/baselines/reference/numericEnumMappedType.types @@ -91,7 +91,7 @@ enum N2 { C = val(), D = val() } >val : () => number type T1 = { [K in N1 | N2]: K }; ->T1 : { [x: number]: N1.A | N1.B | N2.C | N2.D; } +>T1 : { [x: number]: N1 | N2; } // Enum types with string valued members are always literal enum types and therefore // ONE and TWO below are not computed members but rather just numerically valued members diff --git a/tests/baselines/reference/this_inside-enum-should-not-be-allowed.types b/tests/baselines/reference/this_inside-enum-should-not-be-allowed.types index b675c69efc3b2..da9f7d0a5c8ca 100644 --- a/tests/baselines/reference/this_inside-enum-should-not-be-allowed.types +++ b/tests/baselines/reference/this_inside-enum-should-not-be-allowed.types @@ -3,7 +3,7 @@ enum TopLevelEnum { >TopLevelEnum : TopLevelEnum ThisWasAllowedButShouldNotBe = this // Should not be allowed ->ThisWasAllowedButShouldNotBe : TopLevelEnum +>ThisWasAllowedButShouldNotBe : TopLevelEnum.ThisWasAllowedButShouldNotBe >this : any } @@ -14,7 +14,7 @@ module ModuleEnum { >EnumInModule : EnumInModule WasADifferentError = this // this was handled as if this was in a module ->WasADifferentError : EnumInModule +>WasADifferentError : EnumInModule.WasADifferentError >this : any } } From a84ac81fcd3e20fb988f686bca37cc8e8ab14741 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 31 Jan 2023 17:05:57 -0800 Subject: [PATCH 3/6] Add tests --- .../reference/computedEnumTypeWidening.js | 157 +++++++++++ .../computedEnumTypeWidening.symbols | 258 +++++++++++++++++ .../reference/computedEnumTypeWidening.types | 263 ++++++++++++++++++ .../compiler/computedEnumTypeWidening.ts | 67 +++++ 4 files changed, 745 insertions(+) create mode 100644 tests/baselines/reference/computedEnumTypeWidening.js create mode 100644 tests/baselines/reference/computedEnumTypeWidening.symbols create mode 100644 tests/baselines/reference/computedEnumTypeWidening.types create mode 100644 tests/cases/compiler/computedEnumTypeWidening.ts diff --git a/tests/baselines/reference/computedEnumTypeWidening.js b/tests/baselines/reference/computedEnumTypeWidening.js new file mode 100644 index 0000000000000..4f9171f963337 --- /dev/null +++ b/tests/baselines/reference/computedEnumTypeWidening.js @@ -0,0 +1,157 @@ +//// [computedEnumTypeWidening.ts] +declare function computed(x: number): number; + +enum E { + A = computed(0), + B = computed(1), + C = computed(2), + D = computed(3), +} + +function f1() { + const c1 = E.B; // Fresh E.B + let v1 = c1; // E + const c2 = c1; // Fresh E.B + let v2 = c2; // E + const c3: E.B = E.B; // E.B + let v3 = c3; // E.B + const c4: E.B = c1; // E.B + let v4 = c4; // E.B +} + +function f2(cond: boolean) { + const c1 = cond ? E.A : E.B; // Fresh E.A | fresh E.B + const c2: E.A | E.B = c1; // E.A | E.B + const c3 = cond ? c1 : c2; // E.A | E.B + const c4 = cond ? c3 : E.C; // E.A | E.B | fresh E.C + const c5: E.A | E.B | E.C = c4; // E.A | E.B | E.C + let v1 = c1; // E + let v2 = c2; // E.A | E.B + let v3 = c3; // E.A | E.B + let v4 = c4; // E + let v5 = c5; // E.A | E.B | E.C +} + +function f3() { + const c1 = E.B; + let v1 = c1; // E + const c2: E.B = E.B; + let v2 = c2; // E.B + const c3 = E.B as E.B; + let v3 = c3; // E.B + const c4 = E.B; + let v4 = c4; // E.B + const c5 = E.B as const; + let v5 = c5; // E.B +} + +declare enum E2 { A, B, C, D } + +function f4() { + const c1 = E2.B; // Fresh E2.B + let v1 = E.B; // E2 +} + +// Repro from #52531 + +enum MyEnum { A, B, C } + +let val1 = MyEnum.A; +val1 = MyEnum.B; + +declare enum MyDeclaredEnum { A, B, C } + +let val2 = MyDeclaredEnum.A; +val2 = MyDeclaredEnum.B; + + +//// [computedEnumTypeWidening.js] +"use strict"; +var E; +(function (E) { + E[E["A"] = computed(0)] = "A"; + E[E["B"] = computed(1)] = "B"; + E[E["C"] = computed(2)] = "C"; + E[E["D"] = computed(3)] = "D"; +})(E || (E = {})); +function f1() { + var c1 = E.B; // Fresh E.B + var v1 = c1; // E + var c2 = c1; // Fresh E.B + var v2 = c2; // E + var c3 = E.B; // E.B + var v3 = c3; // E.B + var c4 = c1; // E.B + var v4 = c4; // E.B +} +function f2(cond) { + var c1 = cond ? E.A : E.B; // Fresh E.A | fresh E.B + var c2 = c1; // E.A | E.B + var c3 = cond ? c1 : c2; // E.A | E.B + var c4 = cond ? c3 : E.C; // E.A | E.B | fresh E.C + var c5 = c4; // E.A | E.B | E.C + var v1 = c1; // E + var v2 = c2; // E.A | E.B + var v3 = c3; // E.A | E.B + var v4 = c4; // E + var v5 = c5; // E.A | E.B | E.C +} +function f3() { + var c1 = E.B; + var v1 = c1; // E + var c2 = E.B; + var v2 = c2; // E.B + var c3 = E.B; + var v3 = c3; // E.B + var c4 = E.B; + var v4 = c4; // E.B + var c5 = E.B; + var v5 = c5; // E.B +} +function f4() { + var c1 = E2.B; // Fresh E2.B + var v1 = E.B; // E2 +} +// Repro from #52531 +var MyEnum; +(function (MyEnum) { + MyEnum[MyEnum["A"] = 0] = "A"; + MyEnum[MyEnum["B"] = 1] = "B"; + MyEnum[MyEnum["C"] = 2] = "C"; +})(MyEnum || (MyEnum = {})); +var val1 = MyEnum.A; +val1 = MyEnum.B; +var val2 = MyDeclaredEnum.A; +val2 = MyDeclaredEnum.B; + + +//// [computedEnumTypeWidening.d.ts] +declare function computed(x: number): number; +declare enum E { + A, + B, + C, + D +} +declare function f1(): void; +declare function f2(cond: boolean): void; +declare function f3(): void; +declare enum E2 { + A, + B, + C, + D +} +declare function f4(): void; +declare enum MyEnum { + A = 0, + B = 1, + C = 2 +} +declare let val1: MyEnum; +declare enum MyDeclaredEnum { + A, + B, + C +} +declare let val2: MyDeclaredEnum; diff --git a/tests/baselines/reference/computedEnumTypeWidening.symbols b/tests/baselines/reference/computedEnumTypeWidening.symbols new file mode 100644 index 0000000000000..5906ad542f130 --- /dev/null +++ b/tests/baselines/reference/computedEnumTypeWidening.symbols @@ -0,0 +1,258 @@ +=== tests/cases/compiler/computedEnumTypeWidening.ts === +declare function computed(x: number): number; +>computed : Symbol(computed, Decl(computedEnumTypeWidening.ts, 0, 0)) +>x : Symbol(x, Decl(computedEnumTypeWidening.ts, 0, 26)) + +enum E { +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) + + A = computed(0), +>A : Symbol(E.A, Decl(computedEnumTypeWidening.ts, 2, 8)) +>computed : Symbol(computed, Decl(computedEnumTypeWidening.ts, 0, 0)) + + B = computed(1), +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>computed : Symbol(computed, Decl(computedEnumTypeWidening.ts, 0, 0)) + + C = computed(2), +>C : Symbol(E.C, Decl(computedEnumTypeWidening.ts, 4, 20)) +>computed : Symbol(computed, Decl(computedEnumTypeWidening.ts, 0, 0)) + + D = computed(3), +>D : Symbol(E.D, Decl(computedEnumTypeWidening.ts, 5, 20)) +>computed : Symbol(computed, Decl(computedEnumTypeWidening.ts, 0, 0)) +} + +function f1() { +>f1 : Symbol(f1, Decl(computedEnumTypeWidening.ts, 7, 1)) + + const c1 = E.B; // Fresh E.B +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 10, 9)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + let v1 = c1; // E +>v1 : Symbol(v1, Decl(computedEnumTypeWidening.ts, 11, 7)) +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 10, 9)) + + const c2 = c1; // Fresh E.B +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 12, 9)) +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 10, 9)) + + let v2 = c2; // E +>v2 : Symbol(v2, Decl(computedEnumTypeWidening.ts, 13, 7)) +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 12, 9)) + + const c3: E.B = E.B; // E.B +>c3 : Symbol(c3, Decl(computedEnumTypeWidening.ts, 14, 9)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + let v3 = c3; // E.B +>v3 : Symbol(v3, Decl(computedEnumTypeWidening.ts, 15, 7)) +>c3 : Symbol(c3, Decl(computedEnumTypeWidening.ts, 14, 9)) + + const c4: E.B = c1; // E.B +>c4 : Symbol(c4, Decl(computedEnumTypeWidening.ts, 16, 9)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 10, 9)) + + let v4 = c4; // E.B +>v4 : Symbol(v4, Decl(computedEnumTypeWidening.ts, 17, 7)) +>c4 : Symbol(c4, Decl(computedEnumTypeWidening.ts, 16, 9)) +} + +function f2(cond: boolean) { +>f2 : Symbol(f2, Decl(computedEnumTypeWidening.ts, 18, 1)) +>cond : Symbol(cond, Decl(computedEnumTypeWidening.ts, 20, 12)) + + const c1 = cond ? E.A : E.B; // Fresh E.A | fresh E.B +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 21, 9)) +>cond : Symbol(cond, Decl(computedEnumTypeWidening.ts, 20, 12)) +>E.A : Symbol(E.A, Decl(computedEnumTypeWidening.ts, 2, 8)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>A : Symbol(E.A, Decl(computedEnumTypeWidening.ts, 2, 8)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + const c2: E.A | E.B = c1; // E.A | E.B +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 22, 9)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>A : Symbol(E.A, Decl(computedEnumTypeWidening.ts, 2, 8)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 21, 9)) + + const c3 = cond ? c1 : c2; // E.A | E.B +>c3 : Symbol(c3, Decl(computedEnumTypeWidening.ts, 23, 9)) +>cond : Symbol(cond, Decl(computedEnumTypeWidening.ts, 20, 12)) +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 21, 9)) +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 22, 9)) + + const c4 = cond ? c3 : E.C; // E.A | E.B | fresh E.C +>c4 : Symbol(c4, Decl(computedEnumTypeWidening.ts, 24, 9)) +>cond : Symbol(cond, Decl(computedEnumTypeWidening.ts, 20, 12)) +>c3 : Symbol(c3, Decl(computedEnumTypeWidening.ts, 23, 9)) +>E.C : Symbol(E.C, Decl(computedEnumTypeWidening.ts, 4, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>C : Symbol(E.C, Decl(computedEnumTypeWidening.ts, 4, 20)) + + const c5: E.A | E.B | E.C = c4; // E.A | E.B | E.C +>c5 : Symbol(c5, Decl(computedEnumTypeWidening.ts, 25, 9)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>A : Symbol(E.A, Decl(computedEnumTypeWidening.ts, 2, 8)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>C : Symbol(E.C, Decl(computedEnumTypeWidening.ts, 4, 20)) +>c4 : Symbol(c4, Decl(computedEnumTypeWidening.ts, 24, 9)) + + let v1 = c1; // E +>v1 : Symbol(v1, Decl(computedEnumTypeWidening.ts, 26, 7)) +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 21, 9)) + + let v2 = c2; // E.A | E.B +>v2 : Symbol(v2, Decl(computedEnumTypeWidening.ts, 27, 7)) +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 22, 9)) + + let v3 = c3; // E.A | E.B +>v3 : Symbol(v3, Decl(computedEnumTypeWidening.ts, 28, 7)) +>c3 : Symbol(c3, Decl(computedEnumTypeWidening.ts, 23, 9)) + + let v4 = c4; // E +>v4 : Symbol(v4, Decl(computedEnumTypeWidening.ts, 29, 7)) +>c4 : Symbol(c4, Decl(computedEnumTypeWidening.ts, 24, 9)) + + let v5 = c5; // E.A | E.B | E.C +>v5 : Symbol(v5, Decl(computedEnumTypeWidening.ts, 30, 7)) +>c5 : Symbol(c5, Decl(computedEnumTypeWidening.ts, 25, 9)) +} + +function f3() { +>f3 : Symbol(f3, Decl(computedEnumTypeWidening.ts, 31, 1)) + + const c1 = E.B; +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 34, 9)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + let v1 = c1; // E +>v1 : Symbol(v1, Decl(computedEnumTypeWidening.ts, 35, 7)) +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 34, 9)) + + const c2: E.B = E.B; +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 36, 9)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + let v2 = c2; // E.B +>v2 : Symbol(v2, Decl(computedEnumTypeWidening.ts, 37, 7)) +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 36, 9)) + + const c3 = E.B as E.B; +>c3 : Symbol(c3, Decl(computedEnumTypeWidening.ts, 38, 9)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + let v3 = c3; // E.B +>v3 : Symbol(v3, Decl(computedEnumTypeWidening.ts, 39, 7)) +>c3 : Symbol(c3, Decl(computedEnumTypeWidening.ts, 38, 9)) + + const c4 = E.B; +>c4 : Symbol(c4, Decl(computedEnumTypeWidening.ts, 40, 9)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + let v4 = c4; // E.B +>v4 : Symbol(v4, Decl(computedEnumTypeWidening.ts, 41, 7)) +>c4 : Symbol(c4, Decl(computedEnumTypeWidening.ts, 40, 9)) + + const c5 = E.B as const; +>c5 : Symbol(c5, Decl(computedEnumTypeWidening.ts, 42, 9)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>const : Symbol(const) + + let v5 = c5; // E.B +>v5 : Symbol(v5, Decl(computedEnumTypeWidening.ts, 43, 7)) +>c5 : Symbol(c5, Decl(computedEnumTypeWidening.ts, 42, 9)) +} + +declare enum E2 { A, B, C, D } +>E2 : Symbol(E2, Decl(computedEnumTypeWidening.ts, 44, 1)) +>A : Symbol(E2.A, Decl(computedEnumTypeWidening.ts, 46, 17)) +>B : Symbol(E2.B, Decl(computedEnumTypeWidening.ts, 46, 20)) +>C : Symbol(E2.C, Decl(computedEnumTypeWidening.ts, 46, 23)) +>D : Symbol(E2.D, Decl(computedEnumTypeWidening.ts, 46, 26)) + +function f4() { +>f4 : Symbol(f4, Decl(computedEnumTypeWidening.ts, 46, 30)) + + const c1 = E2.B; // Fresh E2.B +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 49, 9)) +>E2.B : Symbol(E2.B, Decl(computedEnumTypeWidening.ts, 46, 20)) +>E2 : Symbol(E2, Decl(computedEnumTypeWidening.ts, 44, 1)) +>B : Symbol(E2.B, Decl(computedEnumTypeWidening.ts, 46, 20)) + + let v1 = E.B; // E2 +>v1 : Symbol(v1, Decl(computedEnumTypeWidening.ts, 50, 7)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +} + +// Repro from #52531 + +enum MyEnum { A, B, C } +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 51, 1)) +>A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 55, 13)) +>B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 55, 16)) +>C : Symbol(MyEnum.C, Decl(computedEnumTypeWidening.ts, 55, 19)) + +let val1 = MyEnum.A; +>val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 57, 3)) +>MyEnum.A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 55, 13)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 51, 1)) +>A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 55, 13)) + +val1 = MyEnum.B; +>val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 57, 3)) +>MyEnum.B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 55, 16)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 51, 1)) +>B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 55, 16)) + +declare enum MyDeclaredEnum { A, B, C } +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 58, 16)) +>A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 60, 29)) +>B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 60, 32)) +>C : Symbol(MyDeclaredEnum.C, Decl(computedEnumTypeWidening.ts, 60, 35)) + +let val2 = MyDeclaredEnum.A; +>val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 62, 3)) +>MyDeclaredEnum.A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 60, 29)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 58, 16)) +>A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 60, 29)) + +val2 = MyDeclaredEnum.B; +>val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 62, 3)) +>MyDeclaredEnum.B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 60, 32)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 58, 16)) +>B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 60, 32)) + diff --git a/tests/baselines/reference/computedEnumTypeWidening.types b/tests/baselines/reference/computedEnumTypeWidening.types new file mode 100644 index 0000000000000..313432e9dfd8e --- /dev/null +++ b/tests/baselines/reference/computedEnumTypeWidening.types @@ -0,0 +1,263 @@ +=== tests/cases/compiler/computedEnumTypeWidening.ts === +declare function computed(x: number): number; +>computed : (x: number) => number +>x : number + +enum E { +>E : E + + A = computed(0), +>A : E.A +>computed(0) : number +>computed : (x: number) => number +>0 : 0 + + B = computed(1), +>B : E.B +>computed(1) : number +>computed : (x: number) => number +>1 : 1 + + C = computed(2), +>C : E.C +>computed(2) : number +>computed : (x: number) => number +>2 : 2 + + D = computed(3), +>D : E.D +>computed(3) : number +>computed : (x: number) => number +>3 : 3 +} + +function f1() { +>f1 : () => void + + const c1 = E.B; // Fresh E.B +>c1 : E.B +>E.B : E.B +>E : typeof E +>B : E.B + + let v1 = c1; // E +>v1 : E +>c1 : E.B + + const c2 = c1; // Fresh E.B +>c2 : E.B +>c1 : E.B + + let v2 = c2; // E +>v2 : E +>c2 : E.B + + const c3: E.B = E.B; // E.B +>c3 : E.B +>E : any +>E.B : E.B +>E : typeof E +>B : E.B + + let v3 = c3; // E.B +>v3 : E.B +>c3 : E.B + + const c4: E.B = c1; // E.B +>c4 : E.B +>E : any +>c1 : E.B + + let v4 = c4; // E.B +>v4 : E.B +>c4 : E.B +} + +function f2(cond: boolean) { +>f2 : (cond: boolean) => void +>cond : boolean + + const c1 = cond ? E.A : E.B; // Fresh E.A | fresh E.B +>c1 : E.A | E.B +>cond ? E.A : E.B : E.A | E.B +>cond : boolean +>E.A : E.A +>E : typeof E +>A : E.A +>E.B : E.B +>E : typeof E +>B : E.B + + const c2: E.A | E.B = c1; // E.A | E.B +>c2 : E.A | E.B +>E : any +>E : any +>c1 : E.A | E.B + + const c3 = cond ? c1 : c2; // E.A | E.B +>c3 : E.A | E.B +>cond ? c1 : c2 : E.A | E.B +>cond : boolean +>c1 : E.A | E.B +>c2 : E.A | E.B + + const c4 = cond ? c3 : E.C; // E.A | E.B | fresh E.C +>c4 : E.A | E.B | E.C +>cond ? c3 : E.C : E.A | E.B | E.C +>cond : boolean +>c3 : E.A | E.B +>E.C : E.C +>E : typeof E +>C : E.C + + const c5: E.A | E.B | E.C = c4; // E.A | E.B | E.C +>c5 : E.A | E.B | E.C +>E : any +>E : any +>E : any +>c4 : E.A | E.B | E.C + + let v1 = c1; // E +>v1 : E +>c1 : E.A | E.B + + let v2 = c2; // E.A | E.B +>v2 : E.A | E.B +>c2 : E.A | E.B + + let v3 = c3; // E.A | E.B +>v3 : E.A | E.B +>c3 : E.A | E.B + + let v4 = c4; // E +>v4 : E +>c4 : E.A | E.B | E.C + + let v5 = c5; // E.A | E.B | E.C +>v5 : E.A | E.B | E.C +>c5 : E.A | E.B | E.C +} + +function f3() { +>f3 : () => void + + const c1 = E.B; +>c1 : E.B +>E.B : E.B +>E : typeof E +>B : E.B + + let v1 = c1; // E +>v1 : E +>c1 : E.B + + const c2: E.B = E.B; +>c2 : E.B +>E : any +>E.B : E.B +>E : typeof E +>B : E.B + + let v2 = c2; // E.B +>v2 : E.B +>c2 : E.B + + const c3 = E.B as E.B; +>c3 : E.B +>E.B as E.B : E.B +>E.B : E.B +>E : typeof E +>B : E.B +>E : any + + let v3 = c3; // E.B +>v3 : E.B +>c3 : E.B + + const c4 = E.B; +>c4 : E.B +>E.B : E.B +>E : any +>E.B : E.B +>E : typeof E +>B : E.B + + let v4 = c4; // E.B +>v4 : E.B +>c4 : E.B + + const c5 = E.B as const; +>c5 : E.B +>E.B as const : E.B +>E.B : E.B +>E : typeof E +>B : E.B + + let v5 = c5; // E.B +>v5 : E.B +>c5 : E.B +} + +declare enum E2 { A, B, C, D } +>E2 : E2 +>A : E2.A +>B : E2.B +>C : E2.C +>D : E2.D + +function f4() { +>f4 : () => void + + const c1 = E2.B; // Fresh E2.B +>c1 : E2.B +>E2.B : E2.B +>E2 : typeof E2 +>B : E2.B + + let v1 = E.B; // E2 +>v1 : E +>E.B : E.B +>E : typeof E +>B : E.B +} + +// Repro from #52531 + +enum MyEnum { A, B, C } +>MyEnum : MyEnum +>A : MyEnum.A +>B : MyEnum.B +>C : MyEnum.C + +let val1 = MyEnum.A; +>val1 : MyEnum +>MyEnum.A : MyEnum.A +>MyEnum : typeof MyEnum +>A : MyEnum.A + +val1 = MyEnum.B; +>val1 = MyEnum.B : MyEnum.B +>val1 : MyEnum +>MyEnum.B : MyEnum.B +>MyEnum : typeof MyEnum +>B : MyEnum.B + +declare enum MyDeclaredEnum { A, B, C } +>MyDeclaredEnum : MyDeclaredEnum +>A : MyDeclaredEnum.A +>B : MyDeclaredEnum.B +>C : MyDeclaredEnum.C + +let val2 = MyDeclaredEnum.A; +>val2 : MyDeclaredEnum +>MyDeclaredEnum.A : MyDeclaredEnum.A +>MyDeclaredEnum : typeof MyDeclaredEnum +>A : MyDeclaredEnum.A + +val2 = MyDeclaredEnum.B; +>val2 = MyDeclaredEnum.B : MyDeclaredEnum.B +>val2 : MyDeclaredEnum +>MyDeclaredEnum.B : MyDeclaredEnum.B +>MyDeclaredEnum : typeof MyDeclaredEnum +>B : MyDeclaredEnum.B + diff --git a/tests/cases/compiler/computedEnumTypeWidening.ts b/tests/cases/compiler/computedEnumTypeWidening.ts new file mode 100644 index 0000000000000..65a000cd5950e --- /dev/null +++ b/tests/cases/compiler/computedEnumTypeWidening.ts @@ -0,0 +1,67 @@ +// @strict: true +// @declaration: true + +declare function computed(x: number): number; + +enum E { + A = computed(0), + B = computed(1), + C = computed(2), + D = computed(3), +} + +function f1() { + const c1 = E.B; // Fresh E.B + let v1 = c1; // E + const c2 = c1; // Fresh E.B + let v2 = c2; // E + const c3: E.B = E.B; // E.B + let v3 = c3; // E.B + const c4: E.B = c1; // E.B + let v4 = c4; // E.B +} + +function f2(cond: boolean) { + const c1 = cond ? E.A : E.B; // Fresh E.A | fresh E.B + const c2: E.A | E.B = c1; // E.A | E.B + const c3 = cond ? c1 : c2; // E.A | E.B + const c4 = cond ? c3 : E.C; // E.A | E.B | fresh E.C + const c5: E.A | E.B | E.C = c4; // E.A | E.B | E.C + let v1 = c1; // E + let v2 = c2; // E.A | E.B + let v3 = c3; // E.A | E.B + let v4 = c4; // E + let v5 = c5; // E.A | E.B | E.C +} + +function f3() { + const c1 = E.B; + let v1 = c1; // E + const c2: E.B = E.B; + let v2 = c2; // E.B + const c3 = E.B as E.B; + let v3 = c3; // E.B + const c4 = E.B; + let v4 = c4; // E.B + const c5 = E.B as const; + let v5 = c5; // E.B +} + +declare enum E2 { A, B, C, D } + +function f4() { + const c1 = E2.B; // Fresh E2.B + let v1 = E.B; // E2 +} + +// Repro from #52531 + +enum MyEnum { A, B, C } + +let val1 = MyEnum.A; +val1 = MyEnum.B; + +declare enum MyDeclaredEnum { A, B, C } + +let val2 = MyDeclaredEnum.A; +val2 = MyDeclaredEnum.B; From 93e72f6e3884740925de9a14737932dbbd66b344 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2023 12:12:01 -0800 Subject: [PATCH 4/6] Change to `TypeFlags.EnumLike` in a few places --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 18993ccc2cf3a..759d243de58ed 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -45907,7 +45907,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression { - const enumResult = type.flags & TypeFlags.EnumLiteral ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker) + const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker) : type === trueType ? factory.createTrue() : type === falseType && factory.createFalse(); if (enumResult) return enumResult; const literalValue = (type as LiteralType).value; @@ -47668,7 +47668,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isSimpleLiteralEnumReference(expr: Expression) { if ((isPropertyAccessExpression(expr) || (isElementAccessExpression(expr) && isStringOrNumberLiteralExpression(expr.argumentExpression))) && isEntityNameExpression(expr.expression)) { - return !!(checkExpressionCached(expr).flags & TypeFlags.EnumLiteral); + return !!(checkExpressionCached(expr).flags & TypeFlags.EnumLike); } } From 1b79c08538ba460c783f65027e8f321d2dfa3491 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2023 12:12:30 -0800 Subject: [PATCH 5/6] Add additional tests --- .../reference/computedEnumTypeWidening.js | 29 ++++++ .../computedEnumTypeWidening.symbols | 91 ++++++++++++++----- .../reference/computedEnumTypeWidening.types | 43 +++++++++ .../compiler/computedEnumTypeWidening.ts | 10 ++ 4 files changed, 149 insertions(+), 24 deletions(-) diff --git a/tests/baselines/reference/computedEnumTypeWidening.js b/tests/baselines/reference/computedEnumTypeWidening.js index 4f9171f963337..7a2c2f11bcc6d 100644 --- a/tests/baselines/reference/computedEnumTypeWidening.js +++ b/tests/baselines/reference/computedEnumTypeWidening.js @@ -52,6 +52,16 @@ function f4() { let v1 = E.B; // E2 } +const c1 = E.B; +const c2 = E.B as const; +let v1 = E.B; +let v2 = E.B as const; + +class C { + p1 = E.B; + p2 = E.B as const; +} + // Repro from #52531 enum MyEnum { A, B, C } @@ -112,6 +122,17 @@ function f4() { var c1 = E2.B; // Fresh E2.B var v1 = E.B; // E2 } +var c1 = E.B; +var c2 = E.B; +var v1 = E.B; +var v2 = E.B; +var C = /** @class */ (function () { + function C() { + this.p1 = E.B; + this.p2 = E.B; + } + return C; +}()); // Repro from #52531 var MyEnum; (function (MyEnum) { @@ -143,6 +164,14 @@ declare enum E2 { D } declare function f4(): void; +declare const c1 = E.B; +declare const c2: E.B; +declare let v1: E; +declare let v2: E.B; +declare class C { + p1: E; + p2: E.B; +} declare enum MyEnum { A = 0, B = 1, diff --git a/tests/baselines/reference/computedEnumTypeWidening.symbols b/tests/baselines/reference/computedEnumTypeWidening.symbols index 5906ad542f130..07ff2e1ac6b73 100644 --- a/tests/baselines/reference/computedEnumTypeWidening.symbols +++ b/tests/baselines/reference/computedEnumTypeWidening.symbols @@ -218,41 +218,84 @@ function f4() { >B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) } +const c1 = E.B; +>c1 : Symbol(c1, Decl(computedEnumTypeWidening.ts, 53, 5)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + +const c2 = E.B as const; +>c2 : Symbol(c2, Decl(computedEnumTypeWidening.ts, 54, 5)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>const : Symbol(const) + +let v1 = E.B; +>v1 : Symbol(v1, Decl(computedEnumTypeWidening.ts, 55, 3)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + +let v2 = E.B as const; +>v2 : Symbol(v2, Decl(computedEnumTypeWidening.ts, 56, 3)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>const : Symbol(const) + +class C { +>C : Symbol(C, Decl(computedEnumTypeWidening.ts, 56, 22)) + + p1 = E.B; +>p1 : Symbol(C.p1, Decl(computedEnumTypeWidening.ts, 58, 9)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + p2 = E.B as const; +>p2 : Symbol(C.p2, Decl(computedEnumTypeWidening.ts, 59, 11)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>const : Symbol(const) +} + // Repro from #52531 enum MyEnum { A, B, C } ->MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 51, 1)) ->A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 55, 13)) ->B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 55, 16)) ->C : Symbol(MyEnum.C, Decl(computedEnumTypeWidening.ts, 55, 19)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 61, 1)) +>A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 65, 13)) +>B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 65, 16)) +>C : Symbol(MyEnum.C, Decl(computedEnumTypeWidening.ts, 65, 19)) let val1 = MyEnum.A; ->val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 57, 3)) ->MyEnum.A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 55, 13)) ->MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 51, 1)) ->A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 55, 13)) +>val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 67, 3)) +>MyEnum.A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 65, 13)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 61, 1)) +>A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 65, 13)) val1 = MyEnum.B; ->val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 57, 3)) ->MyEnum.B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 55, 16)) ->MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 51, 1)) ->B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 55, 16)) +>val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 67, 3)) +>MyEnum.B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 65, 16)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 61, 1)) +>B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 65, 16)) declare enum MyDeclaredEnum { A, B, C } ->MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 58, 16)) ->A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 60, 29)) ->B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 60, 32)) ->C : Symbol(MyDeclaredEnum.C, Decl(computedEnumTypeWidening.ts, 60, 35)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 68, 16)) +>A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 70, 29)) +>B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 70, 32)) +>C : Symbol(MyDeclaredEnum.C, Decl(computedEnumTypeWidening.ts, 70, 35)) let val2 = MyDeclaredEnum.A; ->val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 62, 3)) ->MyDeclaredEnum.A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 60, 29)) ->MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 58, 16)) ->A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 60, 29)) +>val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 72, 3)) +>MyDeclaredEnum.A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 70, 29)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 68, 16)) +>A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 70, 29)) val2 = MyDeclaredEnum.B; ->val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 62, 3)) ->MyDeclaredEnum.B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 60, 32)) ->MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 58, 16)) ->B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 60, 32)) +>val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 72, 3)) +>MyDeclaredEnum.B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 70, 32)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 68, 16)) +>B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 70, 32)) diff --git a/tests/baselines/reference/computedEnumTypeWidening.types b/tests/baselines/reference/computedEnumTypeWidening.types index 313432e9dfd8e..c8da574ff7aea 100644 --- a/tests/baselines/reference/computedEnumTypeWidening.types +++ b/tests/baselines/reference/computedEnumTypeWidening.types @@ -221,6 +221,49 @@ function f4() { >B : E.B } +const c1 = E.B; +>c1 : E.B +>E.B : E.B +>E : typeof E +>B : E.B + +const c2 = E.B as const; +>c2 : E.B +>E.B as const : E.B +>E.B : E.B +>E : typeof E +>B : E.B + +let v1 = E.B; +>v1 : E +>E.B : E.B +>E : typeof E +>B : E.B + +let v2 = E.B as const; +>v2 : E.B +>E.B as const : E.B +>E.B : E.B +>E : typeof E +>B : E.B + +class C { +>C : C + + p1 = E.B; +>p1 : E +>E.B : E.B +>E : typeof E +>B : E.B + + p2 = E.B as const; +>p2 : E.B +>E.B as const : E.B +>E.B : E.B +>E : typeof E +>B : E.B +} + // Repro from #52531 enum MyEnum { A, B, C } diff --git a/tests/cases/compiler/computedEnumTypeWidening.ts b/tests/cases/compiler/computedEnumTypeWidening.ts index 65a000cd5950e..d3249d5f37dd2 100644 --- a/tests/cases/compiler/computedEnumTypeWidening.ts +++ b/tests/cases/compiler/computedEnumTypeWidening.ts @@ -54,6 +54,16 @@ function f4() { let v1 = E.B; // E2 } +const c1 = E.B; +const c2 = E.B as const; +let v1 = E.B; +let v2 = E.B as const; + +class C { + p1 = E.B; + p2 = E.B as const; +} + // Repro from #52531 enum MyEnum { A, B, C } From 112914437009538b640252434ade186d1cccfad7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 2 Feb 2023 07:12:25 -0800 Subject: [PATCH 6/6] Add readonly properties to tests --- .../reference/computedEnumTypeWidening.js | 6 ++ .../computedEnumTypeWidening.symbols | 61 +++++++++++-------- .../reference/computedEnumTypeWidening.types | 13 ++++ .../compiler/computedEnumTypeWidening.ts | 2 + 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/tests/baselines/reference/computedEnumTypeWidening.js b/tests/baselines/reference/computedEnumTypeWidening.js index 7a2c2f11bcc6d..e7229c15ac3e1 100644 --- a/tests/baselines/reference/computedEnumTypeWidening.js +++ b/tests/baselines/reference/computedEnumTypeWidening.js @@ -60,6 +60,8 @@ let v2 = E.B as const; class C { p1 = E.B; p2 = E.B as const; + readonly p3 = E.B; + readonly p4 = E.B as const; } // Repro from #52531 @@ -130,6 +132,8 @@ var C = /** @class */ (function () { function C() { this.p1 = E.B; this.p2 = E.B; + this.p3 = E.B; + this.p4 = E.B; } return C; }()); @@ -171,6 +175,8 @@ declare let v2: E.B; declare class C { p1: E; p2: E.B; + readonly p3 = E.B; + readonly p4: E.B; } declare enum MyEnum { A = 0, diff --git a/tests/baselines/reference/computedEnumTypeWidening.symbols b/tests/baselines/reference/computedEnumTypeWidening.symbols index 07ff2e1ac6b73..1872c0406d50f 100644 --- a/tests/baselines/reference/computedEnumTypeWidening.symbols +++ b/tests/baselines/reference/computedEnumTypeWidening.symbols @@ -258,44 +258,57 @@ class C { >E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) >E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) >B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>const : Symbol(const) + + readonly p3 = E.B; +>p3 : Symbol(C.p3, Decl(computedEnumTypeWidening.ts, 60, 20)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) + + readonly p4 = E.B as const; +>p4 : Symbol(C.p4, Decl(computedEnumTypeWidening.ts, 61, 20)) +>E.B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) +>E : Symbol(E, Decl(computedEnumTypeWidening.ts, 0, 45)) +>B : Symbol(E.B, Decl(computedEnumTypeWidening.ts, 3, 20)) >const : Symbol(const) } // Repro from #52531 enum MyEnum { A, B, C } ->MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 61, 1)) ->A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 65, 13)) ->B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 65, 16)) ->C : Symbol(MyEnum.C, Decl(computedEnumTypeWidening.ts, 65, 19)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 63, 1)) +>A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 67, 13)) +>B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 67, 16)) +>C : Symbol(MyEnum.C, Decl(computedEnumTypeWidening.ts, 67, 19)) let val1 = MyEnum.A; ->val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 67, 3)) ->MyEnum.A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 65, 13)) ->MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 61, 1)) ->A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 65, 13)) +>val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 69, 3)) +>MyEnum.A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 67, 13)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 63, 1)) +>A : Symbol(MyEnum.A, Decl(computedEnumTypeWidening.ts, 67, 13)) val1 = MyEnum.B; ->val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 67, 3)) ->MyEnum.B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 65, 16)) ->MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 61, 1)) ->B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 65, 16)) +>val1 : Symbol(val1, Decl(computedEnumTypeWidening.ts, 69, 3)) +>MyEnum.B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 67, 16)) +>MyEnum : Symbol(MyEnum, Decl(computedEnumTypeWidening.ts, 63, 1)) +>B : Symbol(MyEnum.B, Decl(computedEnumTypeWidening.ts, 67, 16)) declare enum MyDeclaredEnum { A, B, C } ->MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 68, 16)) ->A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 70, 29)) ->B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 70, 32)) ->C : Symbol(MyDeclaredEnum.C, Decl(computedEnumTypeWidening.ts, 70, 35)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 70, 16)) +>A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 72, 29)) +>B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 72, 32)) +>C : Symbol(MyDeclaredEnum.C, Decl(computedEnumTypeWidening.ts, 72, 35)) let val2 = MyDeclaredEnum.A; ->val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 72, 3)) ->MyDeclaredEnum.A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 70, 29)) ->MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 68, 16)) ->A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 70, 29)) +>val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 74, 3)) +>MyDeclaredEnum.A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 72, 29)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 70, 16)) +>A : Symbol(MyDeclaredEnum.A, Decl(computedEnumTypeWidening.ts, 72, 29)) val2 = MyDeclaredEnum.B; ->val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 72, 3)) ->MyDeclaredEnum.B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 70, 32)) ->MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 68, 16)) ->B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 70, 32)) +>val2 : Symbol(val2, Decl(computedEnumTypeWidening.ts, 74, 3)) +>MyDeclaredEnum.B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 72, 32)) +>MyDeclaredEnum : Symbol(MyDeclaredEnum, Decl(computedEnumTypeWidening.ts, 70, 16)) +>B : Symbol(MyDeclaredEnum.B, Decl(computedEnumTypeWidening.ts, 72, 32)) diff --git a/tests/baselines/reference/computedEnumTypeWidening.types b/tests/baselines/reference/computedEnumTypeWidening.types index c8da574ff7aea..c7f2e24e265ad 100644 --- a/tests/baselines/reference/computedEnumTypeWidening.types +++ b/tests/baselines/reference/computedEnumTypeWidening.types @@ -261,6 +261,19 @@ class C { >E.B as const : E.B >E.B : E.B >E : typeof E +>B : E.B + + readonly p3 = E.B; +>p3 : E.B +>E.B : E.B +>E : typeof E +>B : E.B + + readonly p4 = E.B as const; +>p4 : E.B +>E.B as const : E.B +>E.B : E.B +>E : typeof E >B : E.B } diff --git a/tests/cases/compiler/computedEnumTypeWidening.ts b/tests/cases/compiler/computedEnumTypeWidening.ts index d3249d5f37dd2..0ccdbfccc6ab1 100644 --- a/tests/cases/compiler/computedEnumTypeWidening.ts +++ b/tests/cases/compiler/computedEnumTypeWidening.ts @@ -62,6 +62,8 @@ let v2 = E.B as const; class C { p1 = E.B; p2 = E.B as const; + readonly p3 = E.B; + readonly p4 = E.B as const; } // Repro from #52531