Fix for relating covered discriminants in unions (#39393)

This commit is contained in:
Ron Buckton
2020-07-07 13:11:55 -07:00
committed by GitHub
6 changed files with 104 additions and 4 deletions

View File

@@ -17279,7 +17279,11 @@ namespace ts {
result &= signaturesRelatedTo(source, type, SignatureKind.Construct, /*reportStructuralErrors*/ false);
if (result) {
result &= indexTypesRelatedTo(source, type, IndexKind.String, /*sourceIsPrimitive*/ false, /*reportStructuralErrors*/ false, IntersectionState.None);
if (result) {
// Comparing numeric index types when both `source` and `type` are tuples is unnecessary as the
// element types should be sufficiently covered by `propertiesRelatedTo`. It also causes problems
// with index type assignability as the types for the excluded discriminants are still included
// in the index type.
if (result && !(isTupleType(source) && isTupleType(type))) {
result &= indexTypesRelatedTo(source, type, IndexKind.Number, /*sourceIsPrimitive*/ false, /*reportStructuralErrors*/ false, IntersectionState.None);
}
}
@@ -17504,6 +17508,7 @@ namespace ts {
for (let i = 0; i < maxArity; i++) {
const targetFlags = i < targetArity ? target.target.elementFlags[i] : targetRestFlag;
const sourceFlags = isTupleType(source) && i < sourceArity ? source.target.elementFlags[i] : sourceRestFlag;
let canExcludeDiscriminants = !!excludedProperties;
if (sourceFlags && targetFlags) {
if (targetFlags & ElementFlags.Variadic && !(sourceFlags & ElementFlags.Variadic) ||
(sourceFlags & ElementFlags.Variadic && !(targetFlags & ElementFlags.Variable))) {
@@ -17520,6 +17525,15 @@ namespace ts {
return Ternary.False;
}
}
// We can only exclude discriminant properties if we have not yet encountered a variable-length element.
if (canExcludeDiscriminants) {
if (sourceFlags & ElementFlags.Variable || targetFlags & ElementFlags.Variable) {
canExcludeDiscriminants = false;
}
if (canExcludeDiscriminants && excludedProperties?.has(("" + i) as __String)) {
continue;
}
}
const sourceType = getTypeArguments(source)[Math.min(i, sourceArity - 1)];
const targetType = getTypeArguments(target)[Math.min(i, targetArity - 1)];
const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) : targetType;