Enum assignability:loosen numbers+tighten computed

1. All numbers and numeric literals are assignable to all enums and enum
literals.
2. Computed enums are no longer assignable to anything except
themselves, even if they would otherwise be "semi-structurally"
compatible.
This commit is contained in:
Nathan Shively-Sanders 2016-09-12 14:11:47 -07:00
parent f50a43734b
commit 85f9568a2b

View file

@ -6194,9 +6194,10 @@ namespace ts {
if (enumRelation[id] !== undefined) {
return enumRelation[id];
}
if (source.symbol.name !== target.symbol.name || !(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum)) {
enumRelation[id] = false;
return false;
if (source.symbol.name !== target.symbol.name ||
!(source.symbol.flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum) ||
!(source.flags & TypeFlags.Union) || !(target.flags & TypeFlags.Union)) {
return (enumRelation[id] = false);
}
const targetEnumType = getTypeOfSymbol(target.symbol);
for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) {
@ -6207,13 +6208,11 @@ namespace ts {
errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name,
typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
}
enumRelation[id] = false;
return false;
return (enumRelation[id] = false);
}
}
}
enumRelation[id] = true;
return true;
return (enumRelation[id] = true);
}
function isSimpleTypeRelatedTo(source: Type, target: Type, relation: Map<RelationComparisonResult>, errorReporter?: ErrorReporter) {
@ -6228,9 +6227,7 @@ namespace ts {
if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
if (relation === assignableRelation || relation === comparableRelation) {
if (source.flags & TypeFlags.Any) return true;
if (source.flags & TypeFlags.Number && target.flags & TypeFlags.EnumLike) return true;
if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.Enum) return true;
if (source.flags & TypeFlags.NumberLiteral && target.flags & TypeFlags.EnumLiteral && (<LiteralType>source).text === (<LiteralType>target).text) return true;
if ((source.flags & TypeFlags.Number | source.flags & TypeFlags.NumberLiteral) && target.flags & TypeFlags.EnumLike) return true;
if (source.flags & TypeFlags.EnumLiteral &&
target.flags & TypeFlags.EnumLiteral &&
(<LiteralType>source).text === (<LiteralType>target).text &&
@ -6417,14 +6414,6 @@ namespace ts {
if (result = typeRelatedToSomeType(source, <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive))) {
return result;
}
if (source.flags & TypeFlags.Enum) {
// 1. look through the target union for a literal whose base type is related to the source
const lit = find((<UnionType>target).types, t => t.flags & TypeFlags.EnumLiteral && isEnumTypeRelatedTo(<EnumType>source, (<EnumLiteralType>t).baseType));
// 2. if found, the base type is only assignable to source if all its literals are in the target union.
if (lit && (result = isRelatedTo((lit as EnumLiteralType).baseType, target, /*reportErrors*/ false))) {
return result;
}
}
}
}