Skip to content

Commit 4a5eeb0

Browse files
authored
Skip comparing optional property flag when comparing against discriminant properties (#38101)
1 parent 1b8c68d commit 4a5eeb0

File tree

5 files changed

+30
-4
lines changed

5 files changed

+30
-4
lines changed

src/compiler/checker.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -16639,7 +16639,7 @@ namespace ts {
1663916639
if (!targetProperty) continue outer;
1664016640
if (sourceProperty === targetProperty) continue;
1664116641
// We compare the source property to the target in the context of a single discriminant type.
16642-
const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None);
16642+
const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
1664316643
// If the target property could not be found, or if the properties were not related,
1664416644
// then this constituent is not a match.
1664516645
if (!related) {
@@ -16737,7 +16737,7 @@ namespace ts {
1673716737
}
1673816738
}
1673916739

16740-
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
16740+
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary {
1674116741
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
1674216742
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
1674316743
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
@@ -16780,7 +16780,7 @@ namespace ts {
1678016780
return Ternary.False;
1678116781
}
1678216782
// When checking for comparability, be more lenient with optional properties.
16783-
if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
16783+
if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
1678416784
// TypeScript 1.0 spec (April 2014): 3.8.3
1678516785
// S is a subtype of a type T, and T is a supertype of S if ...
1678616786
// S' and T are object types and, for each member M in T..
@@ -16910,7 +16910,7 @@ namespace ts {
1691016910
if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
1691116911
const sourceProp = getPropertyOfType(source, name);
1691216912
if (sourceProp && sourceProp !== targetProp) {
16913-
const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
16913+
const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
1691416914
if (!related) {
1691516915
return Ternary.False;
1691616916
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [unionRelationshipCheckPasses.ts]
2+
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };
3+
4+
5+
//// [unionRelationshipCheckPasses.js]
6+
"use strict";
7+
var item = null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
=== tests/cases/compiler/unionRelationshipCheckPasses.ts ===
2+
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };
3+
>item : Symbol(item, Decl(unionRelationshipCheckPasses.ts, 0, 5))
4+
>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 13))
5+
>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 35))
6+
>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 68))
7+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/compiler/unionRelationshipCheckPasses.ts ===
2+
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };
3+
>item : { foo?: undefined; } | { foo: number; }
4+
>foo : undefined
5+
>foo : number
6+
>null as any as { foo?: number | undefined } : { foo?: number | undefined; }
7+
>null as any : any
8+
>null : null
9+
>foo : number | undefined
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// @strict: true
2+
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };

0 commit comments

Comments
 (0)