Literal types for const enum members

This commit is contained in:
Anders Hejlsberg 2016-06-20 20:24:54 -07:00
parent 3ccd68bbe4
commit a91f71488b
2 changed files with 23 additions and 18 deletions

View File

@ -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 = <ResolvedType>createObjectType(TypeFlags.Anonymous | TypeFlags.FromSignature);
const type = <ResolvedType>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((<UnionType>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((<UnionType>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(<Expression>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.

View File

@ -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,