Skip to content

Commit 7ff97d1

Browse files
authored
Merge pull request #31572 from microsoft/normalizedIntersectionLimiter
Limit size of union types resulting from intersection type normalization
2 parents b460d8c + 01d1514 commit 7ff97d1

6 files changed

+542
-0
lines changed

src/compiler/checker.ts

+6
Original file line numberDiff line numberDiff line change
@@ -9912,6 +9912,12 @@ namespace ts {
99129912
else {
99139913
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
99149914
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
9915+
// If the estimated size of the resulting union type exceeds 100000 constituents, report an error.
9916+
const size = reduceLeft(typeSet, (n, t) => n * (t.flags & TypeFlags.Union ? (<UnionType>t).types.length : 1), 1);
9917+
if (size >= 100000) {
9918+
error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent);
9919+
return errorType;
9920+
}
99159921
const unionIndex = findIndex(typeSet, t => (t.flags & TypeFlags.Union) !== 0);
99169922
const unionType = <UnionType>typeSet[unionIndex];
99179923
result = getUnionType(map(unionType.types, t => getIntersectionType(replaceElement(typeSet, unionIndex, t))),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
tests/cases/compiler/normalizedIntersectionTooComplex.ts(36,14): error TS2590: Expression produces a union type that is too complex to represent.
2+
tests/cases/compiler/normalizedIntersectionTooComplex.ts(36,40): error TS7006: Parameter 'x' implicitly has an 'any' type.
3+
4+
5+
==== tests/cases/compiler/normalizedIntersectionTooComplex.ts (2 errors) ====
6+
// Repro from #30050
7+
8+
interface Obj<T> {
9+
ref: T;
10+
}
11+
interface Func<T> {
12+
(x: T): void;
13+
}
14+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
15+
type CtorOf<T> = (arg: UnionToIntersection<T>) => T;
16+
17+
interface Big {
18+
"0": { common?: string; "0"?: number, ref?: Obj<Big["0"]> | Func<Big["0"]>; }
19+
"1": { common?: string; "1"?: number, ref?: Obj<Big["1"]> | Func<Big["1"]>; }
20+
"2": { common?: string; "2"?: number, ref?: Obj<Big["2"]> | Func<Big["2"]>; }
21+
"3": { common?: string; "3"?: number, ref?: Obj<Big["3"]> | Func<Big["3"]>; }
22+
"4": { common?: string; "4"?: number, ref?: Obj<Big["4"]> | Func<Big["4"]>; }
23+
"5": { common?: string; "5"?: number, ref?: Obj<Big["5"]> | Func<Big["5"]>; }
24+
"6": { common?: string; "6"?: number, ref?: Obj<Big["6"]> | Func<Big["6"]>; }
25+
"7": { common?: string; "7"?: number, ref?: Obj<Big["7"]> | Func<Big["7"]>; }
26+
"8": { common?: string; "8"?: number, ref?: Obj<Big["8"]> | Func<Big["8"]>; }
27+
"9": { common?: string; "9"?: number, ref?: Obj<Big["9"]> | Func<Big["9"]>; }
28+
"10": { common?: string; "10"?: number, ref?: Obj<Big["10"]> | Func<Big["10"]>; }
29+
"11": { common?: string; "11"?: number, ref?: Obj<Big["11"]> | Func<Big["11"]>; }
30+
"12": { common?: string; "12"?: number, ref?: Obj<Big["12"]> | Func<Big["12"]>; }
31+
"13": { common?: string; "13"?: number, ref?: Obj<Big["13"]> | Func<Big["13"]>; }
32+
"14": { common?: string; "14"?: number, ref?: Obj<Big["14"]> | Func<Big["14"]>; }
33+
"15": { common?: string; "15"?: number, ref?: Obj<Big["15"]> | Func<Big["15"]>; }
34+
"16": { common?: string; "16"?: number, ref?: Obj<Big["16"]> | Func<Big["16"]>; }
35+
"17": { common?: string; "17"?: number, ref?: Obj<Big["17"]> | Func<Big["17"]>; }
36+
}
37+
declare function getCtor<T extends keyof Big>(comp: T): CtorOf<Big[T]>
38+
39+
declare var all: keyof Big;
40+
const ctor = getCtor(all);
41+
const comp = ctor({ common: "ok", ref: x => console.log(x) });
42+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43+
!!! error TS2590: Expression produces a union type that is too complex to represent.
44+
~
45+
!!! error TS7006: Parameter 'x' implicitly has an 'any' type.
46+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [normalizedIntersectionTooComplex.ts]
2+
// Repro from #30050
3+
4+
interface Obj<T> {
5+
ref: T;
6+
}
7+
interface Func<T> {
8+
(x: T): void;
9+
}
10+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
11+
type CtorOf<T> = (arg: UnionToIntersection<T>) => T;
12+
13+
interface Big {
14+
"0": { common?: string; "0"?: number, ref?: Obj<Big["0"]> | Func<Big["0"]>; }
15+
"1": { common?: string; "1"?: number, ref?: Obj<Big["1"]> | Func<Big["1"]>; }
16+
"2": { common?: string; "2"?: number, ref?: Obj<Big["2"]> | Func<Big["2"]>; }
17+
"3": { common?: string; "3"?: number, ref?: Obj<Big["3"]> | Func<Big["3"]>; }
18+
"4": { common?: string; "4"?: number, ref?: Obj<Big["4"]> | Func<Big["4"]>; }
19+
"5": { common?: string; "5"?: number, ref?: Obj<Big["5"]> | Func<Big["5"]>; }
20+
"6": { common?: string; "6"?: number, ref?: Obj<Big["6"]> | Func<Big["6"]>; }
21+
"7": { common?: string; "7"?: number, ref?: Obj<Big["7"]> | Func<Big["7"]>; }
22+
"8": { common?: string; "8"?: number, ref?: Obj<Big["8"]> | Func<Big["8"]>; }
23+
"9": { common?: string; "9"?: number, ref?: Obj<Big["9"]> | Func<Big["9"]>; }
24+
"10": { common?: string; "10"?: number, ref?: Obj<Big["10"]> | Func<Big["10"]>; }
25+
"11": { common?: string; "11"?: number, ref?: Obj<Big["11"]> | Func<Big["11"]>; }
26+
"12": { common?: string; "12"?: number, ref?: Obj<Big["12"]> | Func<Big["12"]>; }
27+
"13": { common?: string; "13"?: number, ref?: Obj<Big["13"]> | Func<Big["13"]>; }
28+
"14": { common?: string; "14"?: number, ref?: Obj<Big["14"]> | Func<Big["14"]>; }
29+
"15": { common?: string; "15"?: number, ref?: Obj<Big["15"]> | Func<Big["15"]>; }
30+
"16": { common?: string; "16"?: number, ref?: Obj<Big["16"]> | Func<Big["16"]>; }
31+
"17": { common?: string; "17"?: number, ref?: Obj<Big["17"]> | Func<Big["17"]>; }
32+
}
33+
declare function getCtor<T extends keyof Big>(comp: T): CtorOf<Big[T]>
34+
35+
declare var all: keyof Big;
36+
const ctor = getCtor(all);
37+
const comp = ctor({ common: "ok", ref: x => console.log(x) });
38+
39+
40+
//// [normalizedIntersectionTooComplex.js]
41+
"use strict";
42+
// Repro from #30050
43+
var ctor = getCtor(all);
44+
var comp = ctor({ common: "ok", ref: function (x) { return console.log(x); } });

0 commit comments

Comments
 (0)