mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 01:04:49 -05:00
* Fix "Union types are not being narrowed down correctly in 4.3 #44401" * On undefined constraint, add the original type to constraints.
This commit is contained in:
@@ -18363,7 +18363,7 @@ namespace ts {
|
||||
// parameter 'T extends 1 | 2', the intersection 'T & 1' should be reduced to '1' such that it doesn't
|
||||
// appear to be comparable to '2'.
|
||||
if (relation === comparableRelation && target.flags & TypeFlags.Primitive) {
|
||||
const constraints = sameMap((source as IntersectionType).types, t => t.flags & TypeFlags.Primitive ? t : getBaseConstraintOfType(t) || unknownType);
|
||||
const constraints = sameMap((source as IntersectionType).types, getBaseConstraintOrType);
|
||||
if (constraints !== (source as IntersectionType).types) {
|
||||
source = getIntersectionType(constraints);
|
||||
if (!(source.flags & TypeFlags.Intersection)) {
|
||||
|
||||
26
tests/baselines/reference/intersectionOfUnionNarrowing.js
Normal file
26
tests/baselines/reference/intersectionOfUnionNarrowing.js
Normal file
@@ -0,0 +1,26 @@
|
||||
//// [intersectionOfUnionNarrowing.ts]
|
||||
interface X {
|
||||
a?: { aProp: string };
|
||||
b?: { bProp: string };
|
||||
}
|
||||
type AorB = { a: object; b: undefined } | { a: undefined; b: object };
|
||||
|
||||
declare const q: X & AorB;
|
||||
|
||||
if (q.a !== undefined) {
|
||||
q.a.aProp;
|
||||
} else {
|
||||
// q.b is previously incorrectly inferred as potentially undefined
|
||||
q.b.bProp;
|
||||
}
|
||||
|
||||
|
||||
//// [intersectionOfUnionNarrowing.js]
|
||||
"use strict";
|
||||
if (q.a !== undefined) {
|
||||
q.a.aProp;
|
||||
}
|
||||
else {
|
||||
// q.b is previously incorrectly inferred as potentially undefined
|
||||
q.b.bProp;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
=== tests/cases/conformance/types/intersection/intersectionOfUnionNarrowing.ts ===
|
||||
interface X {
|
||||
>X : Symbol(X, Decl(intersectionOfUnionNarrowing.ts, 0, 0))
|
||||
|
||||
a?: { aProp: string };
|
||||
>a : Symbol(X.a, Decl(intersectionOfUnionNarrowing.ts, 0, 13))
|
||||
>aProp : Symbol(aProp, Decl(intersectionOfUnionNarrowing.ts, 1, 7))
|
||||
|
||||
b?: { bProp: string };
|
||||
>b : Symbol(X.b, Decl(intersectionOfUnionNarrowing.ts, 1, 24))
|
||||
>bProp : Symbol(bProp, Decl(intersectionOfUnionNarrowing.ts, 2, 7))
|
||||
}
|
||||
type AorB = { a: object; b: undefined } | { a: undefined; b: object };
|
||||
>AorB : Symbol(AorB, Decl(intersectionOfUnionNarrowing.ts, 3, 1))
|
||||
>a : Symbol(a, Decl(intersectionOfUnionNarrowing.ts, 4, 13))
|
||||
>b : Symbol(b, Decl(intersectionOfUnionNarrowing.ts, 4, 24))
|
||||
>a : Symbol(a, Decl(intersectionOfUnionNarrowing.ts, 4, 43))
|
||||
>b : Symbol(b, Decl(intersectionOfUnionNarrowing.ts, 4, 57))
|
||||
|
||||
declare const q: X & AorB;
|
||||
>q : Symbol(q, Decl(intersectionOfUnionNarrowing.ts, 6, 13))
|
||||
>X : Symbol(X, Decl(intersectionOfUnionNarrowing.ts, 0, 0))
|
||||
>AorB : Symbol(AorB, Decl(intersectionOfUnionNarrowing.ts, 3, 1))
|
||||
|
||||
if (q.a !== undefined) {
|
||||
>q.a : Symbol(a, Decl(intersectionOfUnionNarrowing.ts, 0, 13), Decl(intersectionOfUnionNarrowing.ts, 4, 13), Decl(intersectionOfUnionNarrowing.ts, 0, 13), Decl(intersectionOfUnionNarrowing.ts, 4, 43))
|
||||
>q : Symbol(q, Decl(intersectionOfUnionNarrowing.ts, 6, 13))
|
||||
>a : Symbol(a, Decl(intersectionOfUnionNarrowing.ts, 0, 13), Decl(intersectionOfUnionNarrowing.ts, 4, 13), Decl(intersectionOfUnionNarrowing.ts, 0, 13), Decl(intersectionOfUnionNarrowing.ts, 4, 43))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
q.a.aProp;
|
||||
>q.a.aProp : Symbol(aProp, Decl(intersectionOfUnionNarrowing.ts, 1, 7))
|
||||
>q.a : Symbol(a, Decl(intersectionOfUnionNarrowing.ts, 0, 13), Decl(intersectionOfUnionNarrowing.ts, 4, 13))
|
||||
>q : Symbol(q, Decl(intersectionOfUnionNarrowing.ts, 6, 13))
|
||||
>a : Symbol(a, Decl(intersectionOfUnionNarrowing.ts, 0, 13), Decl(intersectionOfUnionNarrowing.ts, 4, 13))
|
||||
>aProp : Symbol(aProp, Decl(intersectionOfUnionNarrowing.ts, 1, 7))
|
||||
|
||||
} else {
|
||||
// q.b is previously incorrectly inferred as potentially undefined
|
||||
q.b.bProp;
|
||||
>q.b.bProp : Symbol(bProp, Decl(intersectionOfUnionNarrowing.ts, 2, 7))
|
||||
>q.b : Symbol(b, Decl(intersectionOfUnionNarrowing.ts, 1, 24), Decl(intersectionOfUnionNarrowing.ts, 4, 57))
|
||||
>q : Symbol(q, Decl(intersectionOfUnionNarrowing.ts, 6, 13))
|
||||
>b : Symbol(b, Decl(intersectionOfUnionNarrowing.ts, 1, 24), Decl(intersectionOfUnionNarrowing.ts, 4, 57))
|
||||
>bProp : Symbol(bProp, Decl(intersectionOfUnionNarrowing.ts, 2, 7))
|
||||
}
|
||||
|
||||
44
tests/baselines/reference/intersectionOfUnionNarrowing.types
Normal file
44
tests/baselines/reference/intersectionOfUnionNarrowing.types
Normal file
@@ -0,0 +1,44 @@
|
||||
=== tests/cases/conformance/types/intersection/intersectionOfUnionNarrowing.ts ===
|
||||
interface X {
|
||||
a?: { aProp: string };
|
||||
>a : { aProp: string; } | undefined
|
||||
>aProp : string
|
||||
|
||||
b?: { bProp: string };
|
||||
>b : { bProp: string; } | undefined
|
||||
>bProp : string
|
||||
}
|
||||
type AorB = { a: object; b: undefined } | { a: undefined; b: object };
|
||||
>AorB : AorB
|
||||
>a : object
|
||||
>b : undefined
|
||||
>a : undefined
|
||||
>b : object
|
||||
|
||||
declare const q: X & AorB;
|
||||
>q : X & AorB
|
||||
|
||||
if (q.a !== undefined) {
|
||||
>q.a !== undefined : boolean
|
||||
>q.a : ({ aProp: string; } & object) | undefined
|
||||
>q : X & AorB
|
||||
>a : ({ aProp: string; } & object) | undefined
|
||||
>undefined : undefined
|
||||
|
||||
q.a.aProp;
|
||||
>q.a.aProp : string
|
||||
>q.a : { aProp: string; } & object
|
||||
>q : X & { a: object; b: undefined; }
|
||||
>a : { aProp: string; } & object
|
||||
>aProp : string
|
||||
|
||||
} else {
|
||||
// q.b is previously incorrectly inferred as potentially undefined
|
||||
q.b.bProp;
|
||||
>q.b.bProp : string
|
||||
>q.b : { bProp: string; } & object
|
||||
>q : X & { a: undefined; b: object; }
|
||||
>b : { bProp: string; } & object
|
||||
>bProp : string
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// @strict: true
|
||||
|
||||
interface X {
|
||||
a?: { aProp: string };
|
||||
b?: { bProp: string };
|
||||
}
|
||||
type AorB = { a: object; b: undefined } | { a: undefined; b: object };
|
||||
|
||||
declare const q: X & AorB;
|
||||
|
||||
if (q.a !== undefined) {
|
||||
q.a.aProp;
|
||||
} else {
|
||||
// q.b is previously incorrectly inferred as potentially undefined
|
||||
q.b.bProp;
|
||||
}
|
||||
Reference in New Issue
Block a user