Ts-morph: CompilerNodeToWrappedType sometimes resolves to any

Created on 2 Dec 2018  路  3Comments  路  Source: dsherret/ts-morph

Right now the CompilerNodeToWrappedType type will sometimes resolve to any:

https://github.com/dsherret/ts-simple-ast/blob/698ca54707f5ee2908f04e87427d70cfc67c7d73/lib/ts-simple-ast.d.ts#L4775

The reason for this is a limitation in the typescript compiler where you cannot nest more than 50 conditional types: https://github.com/Microsoft/TypeScript/issues/28663

I spent a decent amount of time yesterday trying to come up with some workarounds, but unfortunately it seems like doing a long conditional type like this is the only thing that will work.

bug

All 3 comments

Since compiler nodes have the kind property set to enable differentiated union behavior, could you do something like this?

export enum SyntaxKind {
    ArrayBindingPattern,
    ObjectBindingPattern,
    SomeUnknownKind
}

interface Node {
    kind: SyntaxKind
}

interface WrappedNode {
    z: number
}

interface ArrayNode {
    kind: SyntaxKind.ArrayBindingPattern
    a: string
}

interface WrappedArrayNode { a: number, itemType: string }

interface ObjectNode {
    kind: SyntaxKind.ObjectBindingPattern
    b: string
}

interface WrappedObjectNode { b: string, itemType: string }

interface CompilerToWrappedMap {
    [SyntaxKind.ArrayBindingPattern]: WrappedArrayNode;
    [SyntaxKind.ObjectBindingPattern]: WrappedObjectNode
}

type CompilerNodeToWrappedType<T extends Node> =
    T['kind'] extends keyof CompilerToWrappedMap ?
    CompilerToWrappedMap[T['kind']] :
    WrappedNode

type Arr = CompilerNodeToWrappedType<ArrayNode> // => WrappedArrayNode

@Gerrit0 you just made my day!!! 馃槃

I had tried that in the past, but ran into issues I didn't understand... so I didn't consider it again. I ran into issues this time too, but now I had my npm run code-verification validate-compiler-node-to-wrapped-type script to run each time to validate all the possible passed in types. With the help of that, I was able to come up with the following type that falls below the max depth of 50.

export type CompilerNodeToWrappedType<T extends ts.Node> =
    T extends ts.ObjectDestructuringAssignment ? compiler.ObjectDestructuringAssignment :
    T extends ts.ArrayDestructuringAssignment ? compiler.ArrayDestructuringAssignment :
    T extends ts.SuperElementAccessExpression ? compiler.SuperElementAccessExpression :
    T extends ts.SuperPropertyAccessExpression ? compiler.SuperPropertyAccessExpression :
    T extends ts.AssignmentExpression<infer U> ? compiler.AssignmentExpression<ts.AssignmentExpression<U>, U> :
    T['kind'] extends keyof ImplementedKindToNodeMappings ? ImplementedKindToNodeMappings[T['kind']] :
    T extends ts.SyntaxList ? compiler.SyntaxList :
    T extends ts.TypeNode ? compiler.TypeNode :
    T extends ts.TypeElement ? compiler.TypeElement :
    T extends ts.JSDocTag ? compiler.JSDocTag :
    T extends ts.LiteralExpression ? compiler.LiteralExpression :
    T extends ts.PrimaryExpression ? compiler.PrimaryExpression :
    T extends ts.MemberExpression ? compiler.MemberExpression :
    T extends ts.LeftHandSideExpression ? compiler.LeftHandSideExpression :
    T extends ts.UpdateExpression ? compiler.UpdateExpression :
    T extends ts.UnaryExpression ? compiler.UnaryExpression :
    T extends ts.Expression ? compiler.Expression :
    T extends ts.IterationStatement ? compiler.IterationStatement :
    T extends ts.Statement ? compiler.Statement :
    compiler.Node<T>;

I'll do a release sometime today or tomorrow with this fix (need to run some errands and then clean up some scripts a bit).

Awesome!

This is released in 19.1.0. Thanks again @Gerrit0!

Was this page helpful?
0 / 5 - 0 ratings