Issue
In the code below, inputs and outputs are chained together. Each node in the chain only cares about its predecessor's Output and considers it as Input. With the code below I assume typescript is building a really long type - hence the compiler slows down to being unusable - which ultimately results in Type instantiation is excessively deep and possibly infinite.(2589). In this simplified code it takes 6 nodes to hit that limit, however, in my actual code, it hits it already 2 nodes in.
I have a few related questions:
- is there any solution to this problem? - I assume from this the answer is no.
- can anyone suggest an alternative approach that may achieve something similar?
- is it possible to flatten a type so that Typescript doesn't end up building really long, complex types?
type LMerge<T1, T2> = {
[k in keyof T1]: k extends keyof T2 ? T2[k] : T1[k]
}
type ChainNodePossibleGenerics = { Output?: unknown }
type ChainNodeGenerics = {
Output: unknown
Input: unknown
Depth: unknown
}
type RecursionNext = [1, 2, 3, 4, 5, 6, 7, 8, 9, never]
type CurrentDepth<Node extends ChainNodeGenerics> = Node['Depth'] extends number
? RecursionNext[Node['Depth']]
: [Node['Depth']] extends [never]
? never
: 0
type NextNode<
Node extends ChainNodeGenerics,
Child extends ChainNodePossibleGenerics,
DefaultsApplied = LMerge<{ Input: Node['Output']; Output: unknown }, Child>,
NormalisedChild extends ChainNodeGenerics = LMerge<ChainNodeGenerics, DefaultsApplied>,
MergedType extends ChainNodeGenerics = LMerge<
NormalisedChild,
{
Depth: CurrentDepth<Node>
}
>,
> = MergedType
type ChainNode<Node extends ChainNodeGenerics> = {
<T extends ChainNodePossibleGenerics = {}, Child extends ChainNodeGenerics = NextNode<Node, T>>(
asyncFn: any,
): ChainNode<Child>
depth: Node['Depth']
input: Node['Input']
output: Node['Output']
}
/* ***** EXAMPLE USAGE *************** */
let cN0: ChainNode<LMerge<ChainNodeGenerics, { Output: 'stringI' }>>
// @ts-ignore
const cN1 = cN0<{ Output: 'A' }>('a')
const d = cN1.depth // 0
const cN1Input = cN1.input // 'stringI'
const cN1Output = cN1.output // 'A'
const cN2 = cN1<{ Output: 'B' }>('b')
const d2 = cN2.depth // 1
const cN2Input = cN2.input // 'A''
const cN2Output = cN2.output // 'B'
const cN3 = cN2<{ Output: 'C' }>('c')
const d3 = cN3.depth // 2
const cN3Input = cN3.input // 'B'
const cN3Output = cN3.output // 'C'
const cN4 = cN3<{ Output: 'D' }>('d')
const d4 = cN4.depth // 3
const cN4Input = cN4.input // 'C'
const cN4Output = cN4.output // 'D'
const cN5 = cN4<{ Output: 'E' }>('e')
const d5 = cN5.depth // 4
const cN5Input = cN5.input // 'D'
const cN5Output = cN5.output // 'E'
const cN6 = cN5<{ Output: 'F' }>('f') // Type instantiation is excessively deep and possibly infinite.(2589)
const d6 = cN6.depth // any!!!!
const cN6Input = cN6.input // any
const cN6Output = cN6.output // any
const cN7 = cN6<{ Output: 'G' }>('g')
const d7 = cN7.depth // any!!!!
const cN7Input = cN7.input // any
const cN7Output = cN7.output // any
Solution
I asked the same question in a slightly different way here and it provided the solution
Answered By - TrevTheDev
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.