diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e2515c1e386..1bc9ef3e67c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3686,7 +3686,7 @@ namespace ts { if (symbol.flags & SymbolFlags.TypeAlias) { return getDeclaredTypeOfTypeAlias(symbol); } - if (symbol.flags & SymbolFlags.Enum) { + if (symbol.flags & (SymbolFlags.Enum | SymbolFlags.EnumMember)) { return getDeclaredTypeOfEnum(symbol); } if (symbol.flags & SymbolFlags.TypeParameter) { @@ -4643,7 +4643,7 @@ namespace ts { // will result in a different declaration kind. if (!signature.isolatedSignatureType) { const isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature; - const type = createObjectType(TypeFlags.Anonymous | TypeFlags.FromSignature); + const type = createObjectType(TypeFlags.Anonymous); type.members = emptySymbols; type.properties = emptyArray; type.callSignatures = !isConstructor ? [signature] : emptyArray; @@ -6569,9 +6569,12 @@ namespace ts { } function enumRelatedTo(source: Type, target: Type, reportErrors?: boolean) { + if (source.symbol.flags & SymbolFlags.EnumMember && source.symbol.parent === target.symbol) { + return Ternary.True; + } if (source.symbol.name !== target.symbol.name || - source.symbol.flags & SymbolFlags.ConstEnum || - target.symbol.flags & SymbolFlags.ConstEnum) { + !(source.symbol.flags & SymbolFlags.RegularEnum) || + !(target.symbol.flags & SymbolFlags.RegularEnum)) { return Ternary.False; } const targetEnumType = getTypeOfSymbol(target.symbol); @@ -6844,6 +6847,7 @@ namespace ts { function isLiteralUnionType(type: Type): boolean { return type.flags & TypeFlags.Literal ? true : + type.flags & TypeFlags.Enum ? (type.symbol.flags & SymbolFlags.EnumMember) !== 0 : type.flags & TypeFlags.Union ? forEach((type).types, isLiteralUnionType) : false; } @@ -6852,6 +6856,7 @@ namespace ts { return type.flags & TypeFlags.StringLiteral ? stringType : type.flags & TypeFlags.NumberLiteral ? numberType : type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.Enum && type.symbol.flags & SymbolFlags.EnumMember ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)) : type.flags & TypeFlags.Union ? getUnionType(map((type).types, getBaseTypeOfLiteralType)) : type; } @@ -7728,7 +7733,7 @@ namespace ts { // If all case clauses specify expressions that have unit types, we return an array // of those unit types. Otherwise we return an empty array. const types = map(switchStatement.caseBlock.clauses, getTypeOfSwitchClause); - links.switchTypes = forEach(types, t => !t || t.flags & TypeFlags.StringLiteral) ? types : emptyArray; + links.switchTypes = forEach(types, t => !t || isLiteralUnionType(t)) ? types : emptyArray; } return links.switchTypes; } @@ -8046,7 +8051,7 @@ namespace ts { if (assumeTrue) { return filterType(type, t => areTypesComparable(getTypeOfPropertyOfType(t, propName), discriminantType)); } - if (discriminantType.flags & TypeFlags.StringLiteral) { + if (isLiteralUnionType(discriminantType) && !(discriminantType.flags & TypeFlags.Union)) { return filterType(type, t => getTypeOfPropertyOfType(t, propName) !== discriminantType); } return type; @@ -10186,7 +10191,8 @@ namespace ts { checkClassPropertyAccess(node, left, apparentType, prop); } - const propType = getTypeOfSymbol(prop); + const propType = prop.flags & SymbolFlags.EnumMember && getParentOfSymbol(prop).flags & SymbolFlags.ConstEnum && + isLiteralTypeContext(node) ? getDeclaredTypeOfSymbol(prop) : getTypeOfSymbol(prop); // Only compute control flow type if this is a property access expression that isn't an // assignment target, and the referenced property was declared as a variable, property, // accessor, or optional method. diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 04027042c2d..dbd89391132 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2056,8 +2056,8 @@ namespace ts { Enum = RegularEnum | ConstEnum, Variable = FunctionScopedVariable | BlockScopedVariable, Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor, - Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias, - Namespace = ValueModule | NamespaceModule, + Type = Class | Interface | Enum | EnumMember | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias, + Namespace = ValueModule | NamespaceModule | ConstEnum, Module = ValueModule | NamespaceModule, Accessor = GetAccessor | SetAccessor, @@ -2071,7 +2071,7 @@ namespace ts { ParameterExcludes = Value, PropertyExcludes = None, - EnumMemberExcludes = Value, + EnumMemberExcludes = Value | Type, FunctionExcludes = Value & ~(Function | ValueModule), ClassExcludes = (Value | Type) & ~(ValueModule | Interface), // class-interface mergability done in checker.ts InterfaceExcludes = Type & ~(Interface | Class), @@ -2221,18 +2221,17 @@ namespace ts { Anonymous = 1 << 20, // Anonymous Instantiated = 1 << 21, // Instantiated anonymous type /* @internal */ - FromSignature = 1 << 22, // Created for signature assignment check - ObjectLiteral = 1 << 23, // Originates in an object literal + ObjectLiteral = 1 << 22, // Originates in an object literal /* @internal */ - FreshObjectLiteral = 1 << 24, // Fresh object literal type + FreshObjectLiteral = 1 << 23, // Fresh object literal type /* @internal */ - ContainsWideningType = 1 << 25, // Type is or contains undefined or null widening type + ContainsWideningType = 1 << 24, // Type is or contains undefined or null widening type /* @internal */ - ContainsObjectLiteral = 1 << 26, // Type is or contains object literal type + ContainsObjectLiteral = 1 << 25, // Type is or contains object literal type /* @internal */ - ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type - ThisType = 1 << 28, // This type - ObjectLiteralPatternWithComputedProperties = 1 << 29, // Object literal type implied by binding pattern has computed properties + ContainsAnyFunctionType = 1 << 26, // Type is or contains object literal type + ThisType = 1 << 27, // This type + ObjectLiteralPatternWithComputedProperties = 1 << 28, // Object literal type implied by binding pattern has computed properties /* @internal */ Nullable = Undefined | Null,