Skip to content

Commit 8f40620

Browse files
committed
Address PR comments
1. Cache results of isEnumTypeRelatedTo 2. Make numeric literal assignment stricter again. 3. Use isEnumRelatedTo for comparing enums to each other. This provides the previous semi-structural semantics. 4. Because of the new distinction between computed enums (no union members) and union enums (no computed values => a union of enum literals), some semi-structural code moves out to the body of `isRelatedTo`.
1 parent 5f0ada1 commit 8f40620

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ namespace ts {
334334
const assignableRelation = createMap<RelationComparisonResult>();
335335
const comparableRelation = createMap<RelationComparisonResult>();
336336
const identityRelation = createMap<RelationComparisonResult>();
337+
const enumRelation = createMap<boolean>();
337338

338339
// This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
339340
let _displayBuilder: SymbolDisplayBuilder;
@@ -6203,7 +6204,12 @@ namespace ts {
62036204
if (source === target) {
62046205
return true;
62056206
}
6207+
const id = source.id + "," + target.id;
6208+
if (enumRelation[id] !== undefined) {
6209+
return enumRelation[id];
6210+
}
62066211
if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum)) {
6212+
enumRelation[id] = false;
62076213
return false;
62086214
}
62096215
const targetEnumType = getTypeOfSymbol(target.symbol);
@@ -6215,10 +6221,12 @@ namespace ts {
62156221
errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name,
62166222
typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
62176223
}
6224+
enumRelation[id] = false;
62186225
return false;
62196226
}
62206227
}
62216228
}
6229+
enumRelation[id] = true;
62226230
return true;
62236231
}
62246232

@@ -6234,13 +6242,18 @@ namespace ts {
62346242
if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
62356243
if (relation === assignableRelation || relation === comparableRelation) {
62366244
if (source.flags & TypeFlags.Any) return true;
6237-
if (source.flags & (TypeFlags.Number | TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true;
6245+
if (source.flags & TypeFlags.Number && target.flags & TypeFlags.EnumLike) return true;
6246+
if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.Enum) return true;
62386247
if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.EnumLiteral && (<LiteralType>source).text === (<LiteralType>target).text) return true;
62396248
if (source.flags & TypeFlags.EnumLiteral &&
62406249
target.flags & TypeFlags.EnumLiteral &&
62416250
(<LiteralType>source).text === (<LiteralType>target).text &&
6242-
(<EnumLiteralType>source).baseType.symbol.name === (<EnumLiteralType>target).baseType.symbol.name &&
6243-
!isConstEnumSymbol((<EnumLiteralType>source).baseType.symbol) && !isConstEnumSymbol((<EnumLiteralType>target).baseType.symbol)) {
6251+
isEnumTypeRelatedTo((<EnumLiteralType>source).baseType, (<EnumLiteralType>target).baseType, errorReporter)) {
6252+
return true;
6253+
}
6254+
if (source.flags & TypeFlags.EnumLiteral &&
6255+
target.flags & TypeFlags.Enum &&
6256+
isEnumTypeRelatedTo(<EnumType>target, (<EnumLiteralType>source).baseType, errorReporter)) {
62446257
return true;
62456258
}
62466259
}
@@ -6418,6 +6431,14 @@ namespace ts {
64186431
if (result = typeRelatedToSomeType(source, <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive))) {
64196432
return result;
64206433
}
6434+
if (source.flags & TypeFlags.Enum) {
6435+
// 1. look through the target union for a literal whose base type is related to the source
6436+
let lit = find((<UnionType>target).types, t => t.flags & TypeFlags.EnumLiteral && isEnumTypeRelatedTo(<EnumType>source, (<EnumLiteralType>t).baseType));
6437+
// 2. if found, the base type is only assignable to source if all its literals are in the target union.
6438+
if (lit && (result = isRelatedTo((lit as EnumLiteralType).baseType, target, false))) {
6439+
return result;
6440+
}
6441+
}
64216442
}
64226443
}
64236444

0 commit comments

Comments
 (0)