The code below is a chain of linked items with the type being progressively built up. Typescript quickly becomes unusable in handling this kind of type. What performance optimization can be implemented to improve how typescript handles this kind of type, without sacrificing functionality?
type LMerge<T1, T2> = {
[k in keyof T1]: k extends keyof T2 ? T2[k] : T1[k]
}
type PossibleGenerics = {
Output?: unknown
Error?: unknown
ResultResolverController?: unknown
ErrorResolverController?: unknown
}
type Generics = Required<PossibleGenerics>
// T - is the generics from Generics that are set
// Defaults - are default Generics that are applied to children
type NodeItem<T extends Generics, Defaults extends Generics> = {
// S - is a subset of generics from Generics that are set, including none: {}
// NewDefaults - any changes to Defaults.
<
S extends PossibleGenerics = {}, // specify generics
NewDefaults extends PossibleGenerics = {}, // specify any changes to the Defaults
UpdatedDefaults extends Generics = LMerge<Defaults, NewDefaults>, // updated Defaults after changes
Child extends Generics = LMerge<UpdatedDefaults, S>, // generics and Defaults applied
>(): NodeItem<Child, UpdatedDefaults>
NodeItem: T
}
const example = {} as NodeItem<
{
Output: string
Error: string
ResultResolverController: string
ErrorResolverController: string
},
Generics
>
const exampleUsage1 = example<{ Output: number }, { Error: Error }>()
const exampleUsage2 = exampleUsage1<{ Output: number }>()
...
const exampleUsage21 = exampleUsage20<{ Output: number }>() // Type instantiation is excessively deep and possibly infinite.(2589)
CodePudding user response:
You need to collapse LMerge
as soon as it's created:
type LMerge<T1, T2> = {
[k in keyof T1]: k extends keyof T2 ? T2[k] : T1[k]
} extends infer O ? { [K in keyof O]: O[K] } : never;
Now you force TypeScript to compute the result and store it in an object.