@@ -334,6 +334,7 @@ namespace ts {
334
334
const assignableRelation = createMap<RelationComparisonResult>();
335
335
const comparableRelation = createMap<RelationComparisonResult>();
336
336
const identityRelation = createMap<RelationComparisonResult>();
337
+ const enumRelation = createMap<boolean>();
337
338
338
339
// This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
339
340
let _displayBuilder: SymbolDisplayBuilder;
@@ -6203,7 +6204,12 @@ namespace ts {
6203
6204
if (source === target) {
6204
6205
return true;
6205
6206
}
6207
+ const id = source.id + "," + target.id;
6208
+ if (enumRelation[id] !== undefined) {
6209
+ return enumRelation[id];
6210
+ }
6206
6211
if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum)) {
6212
+ enumRelation[id] = false;
6207
6213
return false;
6208
6214
}
6209
6215
const targetEnumType = getTypeOfSymbol(target.symbol);
@@ -6215,10 +6221,12 @@ namespace ts {
6215
6221
errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name,
6216
6222
typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
6217
6223
}
6224
+ enumRelation[id] = false;
6218
6225
return false;
6219
6226
}
6220
6227
}
6221
6228
}
6229
+ enumRelation[id] = true;
6222
6230
return true;
6223
6231
}
6224
6232
@@ -6234,13 +6242,18 @@ namespace ts {
6234
6242
if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
6235
6243
if (relation === assignableRelation || relation === comparableRelation) {
6236
6244
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;
6238
6247
if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.EnumLiteral && (<LiteralType>source).text === (<LiteralType>target).text) return true;
6239
6248
if (source.flags & TypeFlags.EnumLiteral &&
6240
6249
target.flags & TypeFlags.EnumLiteral &&
6241
6250
(<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)) {
6244
6257
return true;
6245
6258
}
6246
6259
}
@@ -6418,6 +6431,14 @@ namespace ts {
6418
6431
if (result = typeRelatedToSomeType(source, <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive))) {
6419
6432
return result;
6420
6433
}
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
+ }
6421
6442
}
6422
6443
}
6423
6444
0 commit comments