Description
Somehow, while writing real code, I stumbled upon this combination of constructs that seems to quickly produce huge types that hang or crash the compiler. I suggest that there should be some limit on type size at which the compiler gives up rather than potentially hanging/crashing, in the spirit of the limit of 100 on the depth of some existing operations in the checker.
TypeScript Version: master (2e89dbd)
Search Terms: keyof type parameter variable large type hang crash out of memory
Code
interface JSONableArray extends Array<JSONable> {}
interface JSONableDict {
[key: string]: JSONable;
}
type JSONable = number | string | boolean | JSONableArray | JSONableDict;
function foo<T>(t: T): Pick<T, Exclude<keyof T, "foo">> & JSONable {
throw new Error("not implemented");
}
function test<T>(t: T) {
let t1 = foo(t);
let t2 = foo(t1);
let t3 = foo(t2);
let y: number = "hello";
}
Expected behavior: Compiler hits some safety limit on t3
and goes on to report the error on y
.
Actual behavior: Compiler runs out of memory. In VS Code, the language service runs out of memory, crashes, restarts, runs out of memory, crashes, etc., and never reports the error on y
. This is a poor user experience.
Playground Link: may crash your browser
Related Issues: #24223. I originally thought my case was covered by #24223, but it isn't: #24223 is about a better algorithm to simplify a type that ends up being reasonable in size, while in my case, the fully simplified type is huge.