Skip to content

Commit f0aeef1

Browse files
committed
Skip comparing optional property flag when comparing against discriminant properties
1 parent a72e49e commit f0aeef1

File tree

5 files changed

+30
-4
lines changed

5 files changed

+30
-4
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16540,7 +16540,7 @@ namespace ts {
1654016540
if (!targetProperty) continue outer;
1654116541
if (sourceProperty === targetProperty) continue;
1654216542
// We compare the source property to the target in the context of a single discriminant type.
16543-
const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None);
16543+
const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
1654416544
// If the target property could not be found, or if the properties were not related,
1654516545
// then this constituent is not a match.
1654616546
if (!related) {
@@ -16638,7 +16638,7 @@ namespace ts {
1663816638
}
1663916639
}
1664016640

16641-
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
16641+
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary {
1664216642
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
1664316643
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
1664416644
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
@@ -16681,7 +16681,7 @@ namespace ts {
1668116681
return Ternary.False;
1668216682
}
1668316683
// When checking for comparability, be more lenient with optional properties.
16684-
if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
16684+
if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
1668516685
// TypeScript 1.0 spec (April 2014): 3.8.3
1668616686
// S is a subtype of a type T, and T is a supertype of S if ...
1668716687
// S' and T are object types and, for each member M in T..
@@ -16811,7 +16811,7 @@ namespace ts {
1681116811
if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
1681216812
const sourceProp = getPropertyOfType(source, name);
1681316813
if (sourceProp && sourceProp !== targetProp) {
16814-
const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
16814+
const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
1681516815
if (!related) {
1681616816
return Ternary.False;
1681716817
}
Lines changed: 7 additions & 0 deletions
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;
Lines changed: 7 additions & 0 deletions
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+
Lines changed: 10 additions & 0 deletions
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+
Lines changed: 2 additions & 0 deletions
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)