Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CompilerNodeToWrappedType sometimes resolves to any #507

Closed
dsherret opened this issue Dec 2, 2018 · 3 comments
Closed

CompilerNodeToWrappedType sometimes resolves to any #507

dsherret opened this issue Dec 2, 2018 · 3 comments
Labels

Comments

@dsherret
Copy link
Owner

dsherret commented Dec 2, 2018

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: microsoft/TypeScript#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.

@Gerrit0
Copy link
Contributor

Gerrit0 commented Dec 3, 2018

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

@dsherret
Copy link
Owner Author

dsherret commented Dec 4, 2018

@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!

@dsherret dsherret removed the blocked label Dec 4, 2018
@dsherret
Copy link
Owner Author

dsherret commented Dec 4, 2018

This is released in 19.1.0. Thanks again @Gerrit0!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants