-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Better support for typing tree traversals #35012
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
Comments
Hi TypeScript team & community. I'm so so curious whether the above is doable. Any thoughts would be greatly appreciated! Thank you!!! |
Is this a suggestion to add utility types to the core lib? If so, what you’re looking for is probably too specific. There’s no reason those types couldn’t be published to npm or DefinitelyTyped, though. The utility types that ship with the language are extremely general-purpose and tend toward low-level, preferring people to compose them into larger utilities in user-land or 3rd-party-lib-land (just look how long we went before caving to requests for If this is a question on how to write those types (or why the ones you’ve got so far aren’t working), you’ll probably have better luck on StackOverflow. |
@andrewbranch this question is more so about whether this kind of typing is possible... which it very well might not be. I appreciate how often you must get “how do I type this” questions... I don’t believe this to be one of them. |
At some point the problem space becomes complex enough that the only way to answer “is such a type possible” is to try to answer “how do I type this.” I gave it a shot; this is as close as I could get. (I inlined the It seems like it might not be possible, because you need to infer By the way, the suggestion to go to StackOverflow isn’t dismissive to the question or the complexity of the question. We have community members who are much better than I am at writing crazy complex types, and you’re more likely to get their attention there than here. |
You can represent anything in the type system and have it checked. (As long as it's computable) The problem is that you may not be able to get the kind of type inference you want, and that the representation may not be convenient. For example, you can technically have type-level arithmetic and range checks for numbers above the quadrillion range. The representation, however, isn't as easy as It's more like, In your case, without trying it yet, my intuition is that you can get TS to check it with recursive types, but you will not be able to get inference, as @andrewbranch pointed out. So, when answering the question, "Can TS check this complex thing?" The answer is almost always, "Yes, but maybe not the exact representation you want, and you may not get inference" That said, if you're willing to use overloads, this should be an easier problem. I'm not too sure yet, though. I'll have to find some time to play with it. |
That’s a good point of clarification—when I said “might not be possible,” I was referring specifically to getting inference on those |
@andrewbranch @AnyhowStep thank you both for taking the time to think through this problem and provide feedback. I'm glad to hear that representing this type is possible, even if I can't get the kind of inference behavior that I'd like. Your help is much appreciated! |
Search Terms
pipe, generic, function, return, type, into, arguments, self, mutative, visitor, tree, traversal
Suggestion
In the description below, this is the
Visitor
type to which I refer:It doesn't seem that many (or really any) utility types exist for easily writing typed, (potentially-mutative) traversal of objects whose types are known. A visitor's
pre
could mutate a node, which could be later encountered by the visitor'spost
. Multiple visitors results in another type-safety problem: the order in which visitors mutate a given node.To start out with, the
PreNodeIn
should probably be a union of all nodes of the given object. To get this type, we can do something along the following lines, passing the given object asRoot
:PostNodeIn
, on the other hand, needs to account for visitors'pre
and should therefore be a union ofPreNodeIn
andPreNodeOut
.I'm not sure if this would be possible... but the given utility should also account for the order in which visitors are to be executed. As the
pre
andpost
visitors––amongst themselves––could fire off sequentially to alter the same node (and should therefore have a differentPreNodeIn
orPostNodeIn
argument relative to one another:One last complication: visitors could return a falsy value, indicating to the traversal function that the node is to be left unchanged. If we adjust the example above to the following...
... we should then get an error, as the 2nd visitor's
post
function doesn't accept{_: "d"} | {_: "c"}
... it only accepts{_: "d"}
.Ideally we could scrap the annotations and let
traverse
infer the correct constraints for visitor arguments (or reject incompatibly-typed visitors):Use Cases
Any traversal of an object whose type is known. For pluggable APIs which allow users to write visitors, this feature would enable a level of type-safety that could prove useful to both the plugin developer and end developer, who could observe conflict between traversals (which incompatibly mutate the same node).
Examples
I've attempted to do some of this (piping visitor return types back into visitor node type arguments)... I don't get an error... but it does not work as is expected:
If there's a way to support safer traversals, that would be so so sweet.
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: