Skip to content

Commit 676d8af

Browse files
committed
Only infer from constituents with matching discriminants in unions
1 parent 07dbc56 commit 676d8af

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

src/compiler/checker.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12473,10 +12473,10 @@ namespace ts {
1247312473
return propertiesIdenticalTo(source, target);
1247412474
}
1247512475
const requireOptionalProperties = relation === subtypeRelation && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source) && !isTupleType(source);
12476-
const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties);
12476+
const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false);
1247712477
if (unmatchedProperty) {
1247812478
if (reportErrors) {
12479-
const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties));
12479+
const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false));
1248012480
if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code &&
1248112481
headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) {
1248212482
suppressNextError = true; // Retain top-level error for interface implementing issues, otherwise omit it
@@ -13900,20 +13900,29 @@ namespace ts {
1390013900
return getTypeFromInference(inference);
1390113901
}
1390213902

13903-
function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean) {
13903+
function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean) {
1390413904
const properties = target.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(<IntersectionType>target) : getPropertiesOfObjectType(target);
1390513905
for (const targetProp of properties) {
1390613906
if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional)) {
1390713907
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
1390813908
if (!sourceProp) {
1390913909
yield targetProp;
1391013910
}
13911+
else if (matchDiscriminantProperties) {
13912+
const targetType = getTypeOfSymbol(targetProp);
13913+
if (targetType.flags & TypeFlags.Unit) {
13914+
const sourceType = getTypeOfSymbol(sourceProp);
13915+
if (!(sourceType.flags & TypeFlags.Any || getRegularTypeOfLiteralType(sourceType) === getRegularTypeOfLiteralType(targetType))) {
13916+
yield targetProp;
13917+
}
13918+
}
13919+
}
1391113920
}
1391213921
}
1391313922
}
1391413923

13915-
function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean): Symbol | undefined {
13916-
return getUnmatchedProperties(source, target, requireOptionalProperties).next().value;
13924+
function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): Symbol | undefined {
13925+
return getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties).next().value;
1391713926
}
1391813927

1391913928
function tupleTypesDefinitelyUnrelated(source: TupleTypeReference, target: TupleTypeReference) {
@@ -13925,7 +13934,8 @@ namespace ts {
1392513934
// Two tuple types with incompatible arities are definitely unrelated.
1392613935
// Two object types that each have a property that is unmatched in the other are definitely unrelated.
1392713936
return isTupleType(source) && isTupleType(target) && tupleTypesDefinitelyUnrelated(source, target) ||
13928-
!!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false) && !!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false);
13937+
!!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ true) &&
13938+
!!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ true);
1392913939
}
1393013940

1393113941
function getTypeFromInference(inference: InferenceInfo) {

0 commit comments

Comments
 (0)