@@ -2127,7 +2127,7 @@ namespace ts {
21272127 else if (type.flags & TypeFlags.Reference) {
21282128 writeTypeReference(<TypeReference>type, nextFlags);
21292129 }
2130- else if (type.flags & (TypeFlags.Class | TypeFlags.Interface | TypeFlags.Enum | TypeFlags.TypeParameter)) {
2130+ else if (type.flags & (TypeFlags.Class | TypeFlags.Interface | TypeFlags.EnumLike | TypeFlags.TypeParameter)) {
21312131 // The specified symbol flags need to be reinterpreted as type flags
21322132 buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
21332133 }
@@ -3743,23 +3743,72 @@ namespace ts {
37433743 return links.declaredType;
37443744 }
37453745
3746- function createEnumType(symbol: Symbol): Type {
3747- const type = createType(TypeFlags.Enum);
3748- type.symbol = symbol;
3749- return type;
3746+ function isLiteralEnumMember(symbol: Symbol, member: EnumMember) {
3747+ const expr = member.initializer;
3748+ if (!expr) {
3749+ return !isInAmbientContext(member);
3750+ }
3751+ return expr.kind === SyntaxKind.NumericLiteral ||
3752+ expr.kind === SyntaxKind.PrefixUnaryExpression && (<PrefixUnaryExpression>expr).operator === SyntaxKind.MinusToken &&
3753+ (<PrefixUnaryExpression>expr).operand.kind === SyntaxKind.NumericLiteral ||
3754+ expr.kind === SyntaxKind.Identifier && hasProperty(symbol.exports, (<Identifier>expr).text);
37503755 }
37513756
3752- function getEnumMemberType(symbol: Symbol): Type {
3753- const links = getSymbolLinks(getParentOfSymbol(symbol));
3754- const map = links.enumMemberTypes || (links.enumMemberTypes = {});
3755- const value = "" + getEnumMemberValue(<EnumMember>symbol.valueDeclaration);
3756- return map[value] || (map[value] = createEnumType(symbol));
3757+ function enumHasLiteralMembers(symbol: Symbol) {
3758+ for (const declaration of symbol.declarations) {
3759+ if (declaration.kind === SyntaxKind.EnumDeclaration) {
3760+ for (const member of (<EnumDeclaration>declaration).members) {
3761+ if (!isLiteralEnumMember(symbol, member)) {
3762+ return false;
3763+ }
3764+ }
3765+ }
3766+ }
3767+ return true;
37573768 }
37583769
37593770 function getDeclaredTypeOfEnum(symbol: Symbol): Type {
37603771 const links = getSymbolLinks(symbol);
37613772 if (!links.declaredType) {
3762- links.declaredType = symbol.flags & SymbolFlags.EnumMember ? getEnumMemberType(symbol) : createEnumType(symbol);
3773+ const enumType = links.declaredType = <EnumType>createType(TypeFlags.Enum);
3774+ enumType.symbol = symbol;
3775+ if (enumHasLiteralMembers(symbol)) {
3776+ const memberTypeList: Type[] = [];
3777+ const memberTypes: Map<EnumLiteralType> = {};
3778+ for (const declaration of enumType.symbol.declarations) {
3779+ if (declaration.kind === SyntaxKind.EnumDeclaration) {
3780+ computeEnumMemberValues(<EnumDeclaration>declaration);
3781+ for (const member of (<EnumDeclaration>declaration).members) {
3782+ const memberSymbol = getSymbolOfNode(member);
3783+ const value = getEnumMemberValue(member);
3784+ if (!memberTypes[value]) {
3785+ const memberType = memberTypes[value] = <EnumLiteralType>createType(TypeFlags.EnumLiteral);
3786+ memberType.symbol = memberSymbol;
3787+ memberType.baseType = enumType;
3788+ memberType.text = "" + value;
3789+ memberTypeList.push(memberType);
3790+ }
3791+ }
3792+ }
3793+ }
3794+ enumType.memberTypes = memberTypes;
3795+ if (memberTypeList.length > 1) {
3796+ enumType.flags |= TypeFlags.Union;
3797+ (<EnumType & UnionType>enumType).types = memberTypeList;
3798+ unionTypes[getTypeListId(memberTypeList)] = <EnumType & UnionType>enumType;
3799+ }
3800+ }
3801+ }
3802+ return links.declaredType;
3803+ }
3804+
3805+ function getDeclaredTypeOfEnumMember(symbol: Symbol): Type {
3806+ const links = getSymbolLinks(symbol);
3807+ if (!links.declaredType) {
3808+ const enumType = <EnumType>getDeclaredTypeOfEnum(getParentOfSymbol(symbol));
3809+ links.declaredType = enumType.flags & TypeFlags.Union ?
3810+ enumType.memberTypes[getEnumMemberValue(<EnumDeclaration>symbol.valueDeclaration)] :
3811+ enumType;
37633812 }
37643813 return links.declaredType;
37653814 }
@@ -3793,12 +3842,15 @@ namespace ts {
37933842 if (symbol.flags & SymbolFlags.TypeAlias) {
37943843 return getDeclaredTypeOfTypeAlias(symbol);
37953844 }
3796- if (symbol.flags & (SymbolFlags.Enum | SymbolFlags.EnumMember)) {
3797- return getDeclaredTypeOfEnum(symbol);
3798- }
37993845 if (symbol.flags & SymbolFlags.TypeParameter) {
38003846 return getDeclaredTypeOfTypeParameter(symbol);
38013847 }
3848+ if (symbol.flags & SymbolFlags.Enum) {
3849+ return getDeclaredTypeOfEnum(symbol);
3850+ }
3851+ if (symbol.flags & SymbolFlags.EnumMember) {
3852+ return getDeclaredTypeOfEnumMember(symbol);
3853+ }
38023854 if (symbol.flags & SymbolFlags.Alias) {
38033855 return getDeclaredTypeOfAlias(symbol);
38043856 }
@@ -5998,8 +6050,8 @@ namespace ts {
59986050 }
59996051 }
60006052
6001- function isEnumTypeRelatedTo(source: Type , target: Type , errorReporter?: ErrorReporter) {
6002- if (source.symbol.flags & SymbolFlags.EnumMember && source.symbol.parent === target.symbol ) {
6053+ function isEnumTypeRelatedTo(source: EnumType , target: EnumType , errorReporter?: ErrorReporter) {
6054+ if (source === target) {
60036055 return true;
60046056 }
60056057 if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum)) {
@@ -6027,12 +6079,14 @@ namespace ts {
60276079 if (source.flags & TypeFlags.StringLike && target.flags & TypeFlags.String) return true;
60286080 if (source.flags & TypeFlags.NumberLike && target.flags & TypeFlags.Number) return true;
60296081 if (source.flags & TypeFlags.BooleanLike && target.flags & TypeFlags.Boolean) return true;
6030- if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(source, target, errorReporter)) return true;
6082+ if (source.flags & TypeFlags.EnumLiteral && target.flags & TypeFlags.Enum && (<EnumLiteralType>source).baseType === target) return true;
6083+ if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(<EnumType>source, <EnumType>target, errorReporter)) return true;
60316084 if (source.flags & TypeFlags.Undefined && (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void))) return true;
60326085 if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
60336086 if (relation === assignableRelation || relation === comparableRelation) {
60346087 if (source.flags & TypeFlags.Any) return true;
6035- if (source.flags & TypeFlags.Number && target.flags & TypeFlags.Enum) return true;
6088+ if (source.flags & (TypeFlags.Number | TypeFlags.NumberLiteral) && target.flags & TypeFlags.Enum) return true;
6089+ if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.EnumLiteral && (<LiteralType>source).text === (<LiteralType>target).text) return true;
60366090 }
60376091 return false;
60386092 }
@@ -6070,8 +6124,8 @@ namespace ts {
60706124 relation: Map<RelationComparisonResult>,
60716125 errorNode: Node,
60726126 headMessage?: DiagnosticMessage,
6073- containingMessageChain?: DiagnosticMessageChain): boolean {
6074-
6127+ containingMessageChain?: DiagnosticMessageChain): boolean
6128+ {
60756129 let errorInfo: DiagnosticMessageChain;
60766130 let sourceStack: ObjectType[];
60776131 let targetStack: ObjectType[];
@@ -7018,22 +7072,21 @@ namespace ts {
70187072 }
70197073
70207074 function isUnitType(type: Type): boolean {
7021- return type.flags & (TypeFlags.Literal | TypeFlags.Undefined | TypeFlags.Null) ||
7022- type.flags & TypeFlags.Enum && type.symbol.flags & SymbolFlags.EnumMember ? true : false;
7075+ return (type.flags & (TypeFlags.Literal | TypeFlags.Undefined | TypeFlags.Null)) !== 0;
70237076 }
70247077
70257078 function isUnitUnionType(type: Type): boolean {
70267079 return type.flags & TypeFlags.Boolean ? true :
7027- type.flags & TypeFlags.Union ? !forEach((<UnionType>type).types, t => !isUnitType(t)) :
7080+ type.flags & TypeFlags.Union ? type.flags & TypeFlags.Enum ? true : !forEach((<UnionType>type).types, t => !isUnitType(t)) :
70287081 isUnitType(type);
70297082 }
70307083
70317084 function getBaseTypeOfUnitType(type: Type): Type {
70327085 return type.flags & TypeFlags.StringLiteral ? stringType :
70337086 type.flags & TypeFlags.NumberLiteral ? numberType :
70347087 type.flags & TypeFlags.BooleanLiteral ? booleanType :
7035- type.flags & TypeFlags.Enum && type.symbol.flags & SymbolFlags.EnumMember ? getDeclaredTypeOfSymbol(getParentOfSymbol( type.symbol)) :
7036- type.flags & TypeFlags.Union ? getUnionType(map((<UnionType>type).types, getBaseTypeOfUnitType)) :
7088+ type.flags & TypeFlags.EnumLiteral ? (<EnumLiteralType> type).baseType :
7089+ type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(map((<UnionType>type).types, getBaseTypeOfUnitType), /*noSubtypeReduction*/ true ) :
70377090 type;
70387091 }
70397092
@@ -7330,7 +7383,7 @@ namespace ts {
73307383 }
73317384
73327385 function inferFromTypes(source: Type, target: Type) {
7333- if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
7386+ if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && !(source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) ||
73347387 source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
73357388 // Source and target are both unions or both intersections. If source and target
73367389 // are the same type, just relate each constituent type to itself.
@@ -7758,13 +7811,11 @@ namespace ts {
77587811 type === emptyStringType ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts :
77597812 type === emptyStringType ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts;
77607813 }
7761- if (flags & TypeFlags.Number || type.flags & TypeFlags.Enum && !(type.symbol.flags & SymbolFlags.EnumMember )) {
7814+ if (flags & ( TypeFlags.Number | TypeFlags.Enum)) {
77627815 return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts;
77637816 }
7764- if (flags & TypeFlags.NumberLike) {
7765- const isZero = type === zeroType ||
7766- type.flags & TypeFlags.Enum && type.symbol.flags & SymbolFlags.EnumMember &&
7767- getEnumMemberValue(<EnumMember>type.symbol.valueDeclaration) === 0;
7817+ if (flags & (TypeFlags.NumberLiteral | TypeFlags.EnumLiteral)) {
7818+ const isZero = type === zeroType || type.flags & TypeFlags.EnumLiteral && (<LiteralType>type).text === "0";
77687819 return strictNullChecks ?
77697820 isZero ? TypeFacts.ZeroStrictFacts : TypeFacts.NonZeroStrictFacts :
77707821 isZero ? TypeFacts.ZeroFacts : TypeFacts.NonZeroFacts;
@@ -10459,7 +10510,7 @@ namespace ts {
1045910510 }
1046010511
1046110512 let propType = getTypeOfSymbol(prop);
10462- if (prop.flags & SymbolFlags.EnumMember && getParentOfSymbol(prop).flags & SymbolFlags.ConstEnum && isLiteralContextForType(<Expression>node, propType)) {
10513+ if (prop.flags & SymbolFlags.EnumMember && isLiteralContextForType(<Expression>node, propType)) {
1046310514 propType = getDeclaredTypeOfSymbol(prop);
1046410515 }
1046510516
@@ -13057,16 +13108,16 @@ namespace ts {
1305713108 return getUnionType([type1, type2]);
1305813109 }
1305913110
13060- function typeContainsEnumLiteral (type: Type, enumType: Type ) {
13111+ function typeContainsLiteralFromEnum (type: Type, enumType: EnumType ) {
1306113112 if (type.flags & TypeFlags.Union) {
1306213113 for (const t of (<UnionType>type).types) {
13063- if (t.flags & TypeFlags.Enum && t.symbol.flags & SymbolFlags.EnumMember && t.symbol.parent === enumType.symbol ) {
13114+ if (t.flags & TypeFlags.EnumLiteral && (<EnumLiteralType>t).baseType === enumType) {
1306413115 return true;
1306513116 }
1306613117 }
1306713118 }
13068- if (type.flags & TypeFlags.Enum ) {
13069- return type.symbol.flags & SymbolFlags.EnumMember && type.symbol.parent === enumType.symbol ;
13119+ if (type.flags & TypeFlags.EnumLiteral ) {
13120+ return (<EnumLiteralType> type).baseType === enumType;
1307013121 }
1307113122 return false;
1307213123 }
@@ -13091,13 +13142,13 @@ namespace ts {
1309113142 return maybeTypeOfKind(contextualType, TypeFlags.StringLiteral);
1309213143 }
1309313144 if (type.flags & TypeFlags.Number) {
13094- return maybeTypeOfKind(contextualType, TypeFlags.NumberLiteral);
13145+ return maybeTypeOfKind(contextualType, ( TypeFlags.NumberLiteral | TypeFlags.EnumLiteral) );
1309513146 }
1309613147 if (type.flags & TypeFlags.Boolean) {
1309713148 return maybeTypeOfKind(contextualType, TypeFlags.BooleanLiteral) && !isTypeAssignableTo(booleanType, contextualType);
1309813149 }
13099- if (type.flags & TypeFlags.Enum && type.symbol.flags & SymbolFlags.ConstEnum ) {
13100- return typeContainsEnumLiteral (contextualType, type);
13150+ if (type.flags & TypeFlags.Enum) {
13151+ return typeContainsLiteralFromEnum (contextualType, <EnumType> type);
1310113152 }
1310213153 }
1310313154 return false;
@@ -13889,6 +13940,9 @@ namespace ts {
1388913940 checkTypeArgumentConstraints(typeParameters, node.typeArguments);
1389013941 }
1389113942 }
13943+ if (type.flags & TypeFlags.Enum && !(<EnumType>type).memberTypes && getNodeLinks(node).resolvedSymbol.flags & SymbolFlags.EnumMember) {
13944+ error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type));
13945+ }
1389213946 }
1389313947 }
1389413948
@@ -18400,9 +18454,6 @@ namespace ts {
1840018454 }
1840118455 }
1840218456
18403- // The built-in boolean type is 'true | false', also mark 'false | true' as a boolean type
18404- createBooleanType([falseType, trueType]);
18405-
1840618457 // Setup global builtins
1840718458 addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
1840818459
0 commit comments