Skip to content

Commit 6aaf984

Browse files
committed
Allow intersections (and substitutions) to be checks against discriminable unions
1 parent b8b5948 commit 6aaf984

5 files changed

+126
-3
lines changed

Diff for: src/compiler/checker.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15901,7 +15901,7 @@ namespace ts {
1590115901
// with respect to T. We do not report errors here, as we will use the existing
1590215902
// error result from checking each constituent of the union.
1590315903
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Union) {
15904-
const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object);
15904+
const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Substitution);
1590515905
if (objectOnlyTarget.flags & TypeFlags.Union) {
1590615906
const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as UnionType);
1590715907
if (result) {
@@ -15998,7 +15998,7 @@ namespace ts {
1599815998
// NOTE: See ~/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts
1599915999
// for examples.
1600016000

16001-
const sourceProperties = getPropertiesOfObjectType(source);
16001+
const sourceProperties = getPropertiesOfType(source);
1600216002
const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target);
1600316003
if (!sourcePropertiesFiltered) return Ternary.False;
1600416004

@@ -16037,7 +16037,7 @@ namespace ts {
1603716037
outer: for (const type of target.types) {
1603816038
for (let i = 0; i < sourcePropertiesFiltered.length; i++) {
1603916039
const sourceProperty = sourcePropertiesFiltered[i];
16040-
const targetProperty = getPropertyOfObjectType(type, sourceProperty.escapedName);
16040+
const targetProperty = getPropertyOfType(type, sourceProperty.escapedName);
1604116041
if (!targetProperty) continue outer;
1604216042
if (sourceProperty === targetProperty) continue;
1604316043
// We compare the source property to the target in the context of a single discriminant type.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//// [discriminableUnionWithIntersectedMembers.ts]
2+
// regression test for https://github.com/microsoft/TypeScript/issues/33243
3+
type X =
4+
| { x: 'x', y: number } & { y: number }
5+
| { x: 'y', y: number, z?: boolean } & { y: number }
6+
7+
// error
8+
const x: X = 4 as any as { x: 'x' | 'y', y: number };
9+
10+
type Y =
11+
| { x: 'x', y: number }
12+
| { x: 'y', y: number, z?: boolean }
13+
14+
// no error
15+
const y: Y = 4 as any as { x: 'x' | 'y', y: number };
16+
17+
//// [discriminableUnionWithIntersectedMembers.js]
18+
// error
19+
var x = 4;
20+
// no error
21+
var y = 4;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/compiler/discriminableUnionWithIntersectedMembers.ts ===
2+
// regression test for https://github.com/microsoft/TypeScript/issues/33243
3+
type X =
4+
>X : Symbol(X, Decl(discriminableUnionWithIntersectedMembers.ts, 0, 0))
5+
6+
| { x: 'x', y: number } & { y: number }
7+
>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 2, 4))
8+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 2, 12))
9+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 2, 28))
10+
11+
| { x: 'y', y: number, z?: boolean } & { y: number }
12+
>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 4))
13+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 12))
14+
>z : Symbol(z, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 23))
15+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 3, 41))
16+
17+
// error
18+
const x: X = 4 as any as { x: 'x' | 'y', y: number };
19+
>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 5))
20+
>X : Symbol(X, Decl(discriminableUnionWithIntersectedMembers.ts, 0, 0))
21+
>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 26))
22+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 40))
23+
24+
type Y =
25+
>Y : Symbol(Y, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 53))
26+
27+
| { x: 'x', y: number }
28+
>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 9, 4))
29+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 9, 12))
30+
31+
| { x: 'y', y: number, z?: boolean }
32+
>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 10, 4))
33+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 10, 12))
34+
>z : Symbol(z, Decl(discriminableUnionWithIntersectedMembers.ts, 10, 23))
35+
36+
// no error
37+
const y: Y = 4 as any as { x: 'x' | 'y', y: number };
38+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 13, 5))
39+
>Y : Symbol(Y, Decl(discriminableUnionWithIntersectedMembers.ts, 6, 53))
40+
>x : Symbol(x, Decl(discriminableUnionWithIntersectedMembers.ts, 13, 26))
41+
>y : Symbol(y, Decl(discriminableUnionWithIntersectedMembers.ts, 13, 40))
42+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
=== tests/cases/compiler/discriminableUnionWithIntersectedMembers.ts ===
2+
// regression test for https://github.com/microsoft/TypeScript/issues/33243
3+
type X =
4+
>X : X
5+
6+
| { x: 'x', y: number } & { y: number }
7+
>x : "x"
8+
>y : number
9+
>y : number
10+
11+
| { x: 'y', y: number, z?: boolean } & { y: number }
12+
>x : "y"
13+
>y : number
14+
>z : boolean
15+
>y : number
16+
17+
// error
18+
const x: X = 4 as any as { x: 'x' | 'y', y: number };
19+
>x : X
20+
>4 as any as { x: 'x' | 'y', y: number } : { x: "x" | "y"; y: number; }
21+
>4 as any : any
22+
>4 : 4
23+
>x : "x" | "y"
24+
>y : number
25+
26+
type Y =
27+
>Y : Y
28+
29+
| { x: 'x', y: number }
30+
>x : "x"
31+
>y : number
32+
33+
| { x: 'y', y: number, z?: boolean }
34+
>x : "y"
35+
>y : number
36+
>z : boolean
37+
38+
// no error
39+
const y: Y = 4 as any as { x: 'x' | 'y', y: number };
40+
>y : Y
41+
>4 as any as { x: 'x' | 'y', y: number } : { x: "x" | "y"; y: number; }
42+
>4 as any : any
43+
>4 : 4
44+
>x : "x" | "y"
45+
>y : number
46+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// regression test for https://github.com/microsoft/TypeScript/issues/33243
2+
type X =
3+
| { x: 'x', y: number } & { y: number }
4+
| { x: 'y', y: number, z?: boolean } & { y: number }
5+
6+
// error
7+
const x: X = 4 as any as { x: 'x' | 'y', y: number };
8+
9+
type Y =
10+
| { x: 'x', y: number }
11+
| { x: 'y', y: number, z?: boolean }
12+
13+
// no error
14+
const y: Y = 4 as any as { x: 'x' | 'y', y: number };

0 commit comments

Comments
 (0)