This is the same behavior/problem as microsoft/TypeScript#63197.
type Strip<Path extends string> = Path extends `${infer Rest}x` ? Strip<Rest> : Path;
Attempting to compile this single type results in a memory leak with no compiler error, eventually causing a system OOM.
tsconfig.json:
{
"compilerOptions": {
"lib": ["ESNext"],
"module": "NodeNext",
"target": "esnext",
"moduleResolution": "NodeNext",
"noImplicitThis": true,
"noEmit": true,
"declaration": true,
"strict": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
My use case is somewhat more complicated:
/**
* Flatten an object structure into a set of "keys".
*
* @example
* ```ts
* type example = FlattenKeys<{ h: { s: { l: 1; v: 2 } } }>;
* type result = "h" | "h.s" | "h.s.l" | "h.s.v";
* ```
*/
export type FlattenKeys<O> = {
[K in keyof O & (string | number)]: O[K] extends Record<any, any>
? K | `${K}.${FlattenKeys<O[K]>}`
: K;
}[O extends readonly any[]
? keyof O & `${number}`
: keyof O & (string | number)];
export type KeySeparator = '.' | '[' | ']';
/**
* Get a value using a path of property keys.
*/
export type GetByString<
Data,
Path extends string | number = FlattenKeys<Data>,
> = Path extends `__proto__${`${KeySeparator}${string | number}` | ''}`
? never
: Path extends `${KeySeparator}${infer Rest}`
? GetByString<Data, Rest>
: Path extends `${infer Rest}${KeySeparator}`
? GetByString<Data, Rest>
: Path extends `${infer Key extends keyof Data & (string | number)}${KeySeparator}${infer Rest}`
? GetByString<Data[Key], Rest>
: Path extends keyof Data & (string | number)
? Data[Path]
: undefined;
interface Duck {
taxonomy: {
genus: 'anas';
species: 'platyrhynchos';
};
}
type DuckSpecies = GetByString<Duck, 'taxonomy.species'>; // 'platyrhynchos'
This is the same behavior/problem as microsoft/TypeScript#63197.
Attempting to compile this single type results in a memory leak with no compiler error, eventually causing a system OOM.
tsconfig.json:
{ "compilerOptions": { "lib": ["ESNext"], "module": "NodeNext", "target": "esnext", "moduleResolution": "NodeNext", "noImplicitThis": true, "noEmit": true, "declaration": true, "strict": true }, "include": ["src/**/*.ts"], "exclude": ["node_modules"] }My use case is somewhat more complicated: