Skip to content

Commit d61ca6c

Browse files
weswighamtypescript-bot
authored andcommitted
Cherry-pick PR microsoft#36663 into release-3.8
Component commits: 6aaf984 Allow intersections (and substitutions) to be checks against discriminable unions
1 parent fb86896 commit d61ca6c

5 files changed

+126
-3
lines changed

Diff for: src/compiler/checker.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15842,7 +15842,7 @@ namespace ts {
1584215842
// with respect to T. We do not report errors here, as we will use the existing
1584315843
// error result from checking each constituent of the union.
1584415844
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Union) {
15845-
const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object);
15845+
const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Substitution);
1584615846
if (objectOnlyTarget.flags & TypeFlags.Union) {
1584715847
const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as UnionType);
1584815848
if (result) {
@@ -15939,7 +15939,7 @@ namespace ts {
1593915939
// NOTE: See ~/tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatWithDiscriminatedUnion.ts
1594015940
// for examples.
1594115941

15942-
const sourceProperties = getPropertiesOfObjectType(source);
15942+
const sourceProperties = getPropertiesOfType(source);
1594315943
const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target);
1594415944
if (!sourcePropertiesFiltered) return Ternary.False;
1594515945

@@ -15978,7 +15978,7 @@ namespace ts {
1597815978
outer: for (const type of target.types) {
1597915979
for (let i = 0; i < sourcePropertiesFiltered.length; i++) {
1598015980
const sourceProperty = sourcePropertiesFiltered[i];
15981-
const targetProperty = getPropertyOfObjectType(type, sourceProperty.escapedName);
15981+
const targetProperty = getPropertyOfType(type, sourceProperty.escapedName);
1598215982
if (!targetProperty) continue outer;
1598315983
if (sourceProperty === targetProperty) continue;
1598415984
// 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)