Skip to content

Commit 2888510

Browse files
authored
Dont create a union type to infer conditional type branches (#30010)
1 parent 2533d82 commit 2888510

5 files changed

+202
-1
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14519,7 +14519,8 @@ namespace ts {
1451914519
inferFromTypes(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target));
1452014520
}
1452114521
else if (target.flags & TypeFlags.Conditional) {
14522-
inferFromTypes(source, getUnionType([getTrueTypeFromConditionalType(<ConditionalType>target), getFalseTypeFromConditionalType(<ConditionalType>target)]));
14522+
inferFromTypes(source, getTrueTypeFromConditionalType(<ConditionalType>target));
14523+
inferFromTypes(source, getFalseTypeFromConditionalType(<ConditionalType>target));
1452314524
}
1452414525
else if (target.flags & TypeFlags.UnionOrIntersection) {
1452514526
for (const t of (<UnionOrIntersectionType>target).types) {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//// [conditionalTypeRelaxingConstraintAssignability.ts]
2+
export type ElChildren =
3+
| ElChildren.Void
4+
| ElChildren.Text;
5+
export namespace ElChildren {
6+
export type Void = undefined;
7+
export type Text = string;
8+
}
9+
10+
type Relax<C extends ElChildren> = C extends ElChildren.Text ? ElChildren.Text : C;
11+
12+
export class Elem<
13+
C extends ElChildren,
14+
> {
15+
constructor(
16+
private children_: Relax<C>,
17+
) {
18+
}
19+
}
20+
21+
new Elem(undefined as ElChildren.Void);
22+
new Elem('' as ElChildren.Text);
23+
new Elem('' as ElChildren.Void | ElChildren.Text); // error
24+
new Elem('' as ElChildren); // error
25+
26+
//// [conditionalTypeRelaxingConstraintAssignability.js]
27+
"use strict";
28+
exports.__esModule = true;
29+
var Elem = /** @class */ (function () {
30+
function Elem(children_) {
31+
this.children_ = children_;
32+
}
33+
return Elem;
34+
}());
35+
exports.Elem = Elem;
36+
new Elem(undefined);
37+
new Elem('');
38+
new Elem(''); // error
39+
new Elem(''); // error
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
=== tests/cases/compiler/conditionalTypeRelaxingConstraintAssignability.ts ===
2+
export type ElChildren =
3+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
4+
5+
| ElChildren.Void
6+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
7+
>Void : Symbol(ElChildren.Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
8+
9+
| ElChildren.Text;
10+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
11+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
12+
13+
export namespace ElChildren {
14+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
15+
16+
export type Void = undefined;
17+
>Void : Symbol(Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
18+
19+
export type Text = string;
20+
>Text : Symbol(Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
21+
}
22+
23+
type Relax<C extends ElChildren> = C extends ElChildren.Text ? ElChildren.Text : C;
24+
>Relax : Symbol(Relax, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 6, 1))
25+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 11))
26+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
27+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 11))
28+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
29+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
30+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
31+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
32+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 11))
33+
34+
export class Elem<
35+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
36+
37+
C extends ElChildren,
38+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 10, 18))
39+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
40+
41+
> {
42+
constructor(
43+
private children_: Relax<C>,
44+
>children_ : Symbol(Elem.children_, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 13, 14))
45+
>Relax : Symbol(Relax, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 6, 1))
46+
>C : Symbol(C, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 10, 18))
47+
48+
) {
49+
}
50+
}
51+
52+
new Elem(undefined as ElChildren.Void);
53+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
54+
>undefined : Symbol(undefined)
55+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
56+
>Void : Symbol(ElChildren.Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
57+
58+
new Elem('' as ElChildren.Text);
59+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
60+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
61+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
62+
63+
new Elem('' as ElChildren.Void | ElChildren.Text); // error
64+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
65+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
66+
>Void : Symbol(ElChildren.Void, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 3, 29))
67+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
68+
>Text : Symbol(ElChildren.Text, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 4, 31))
69+
70+
new Elem('' as ElChildren); // error
71+
>Elem : Symbol(Elem, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 8, 83))
72+
>ElChildren : Symbol(ElChildren, Decl(conditionalTypeRelaxingConstraintAssignability.ts, 0, 0), Decl(conditionalTypeRelaxingConstraintAssignability.ts, 2, 20))
73+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
=== tests/cases/compiler/conditionalTypeRelaxingConstraintAssignability.ts ===
2+
export type ElChildren =
3+
>ElChildren : ElChildren
4+
5+
| ElChildren.Void
6+
>ElChildren : any
7+
8+
| ElChildren.Text;
9+
>ElChildren : any
10+
11+
export namespace ElChildren {
12+
export type Void = undefined;
13+
>Void : undefined
14+
15+
export type Text = string;
16+
>Text : string
17+
}
18+
19+
type Relax<C extends ElChildren> = C extends ElChildren.Text ? ElChildren.Text : C;
20+
>Relax : Relax<C>
21+
>ElChildren : any
22+
>ElChildren : any
23+
24+
export class Elem<
25+
>Elem : Elem<C>
26+
27+
C extends ElChildren,
28+
> {
29+
constructor(
30+
private children_: Relax<C>,
31+
>children_ : Relax<C>
32+
33+
) {
34+
}
35+
}
36+
37+
new Elem(undefined as ElChildren.Void);
38+
>new Elem(undefined as ElChildren.Void) : Elem<undefined>
39+
>Elem : typeof Elem
40+
>undefined as ElChildren.Void : undefined
41+
>undefined : undefined
42+
>ElChildren : any
43+
44+
new Elem('' as ElChildren.Text);
45+
>new Elem('' as ElChildren.Text) : Elem<string>
46+
>Elem : typeof Elem
47+
>'' as ElChildren.Text : string
48+
>'' : ""
49+
>ElChildren : any
50+
51+
new Elem('' as ElChildren.Void | ElChildren.Text); // error
52+
>new Elem('' as ElChildren.Void | ElChildren.Text) : Elem<ElChildren>
53+
>Elem : typeof Elem
54+
>'' as ElChildren.Void | ElChildren.Text : ElChildren
55+
>'' : ""
56+
>ElChildren : any
57+
>ElChildren : any
58+
59+
new Elem('' as ElChildren); // error
60+
>new Elem('' as ElChildren) : Elem<ElChildren>
61+
>Elem : typeof Elem
62+
>'' as ElChildren : ElChildren
63+
>'' : ""
64+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// @strict: true
2+
export type ElChildren =
3+
| ElChildren.Void
4+
| ElChildren.Text;
5+
export namespace ElChildren {
6+
export type Void = undefined;
7+
export type Text = string;
8+
}
9+
10+
type Relax<C extends ElChildren> = C extends ElChildren.Text ? ElChildren.Text : C;
11+
12+
export class Elem<
13+
C extends ElChildren,
14+
> {
15+
constructor(
16+
private children_: Relax<C>,
17+
) {
18+
}
19+
}
20+
21+
new Elem(undefined as ElChildren.Void);
22+
new Elem('' as ElChildren.Text);
23+
new Elem('' as ElChildren.Void | ElChildren.Text); // error
24+
new Elem('' as ElChildren); // error

0 commit comments

Comments
 (0)