-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
Instantiable tuple labels #55452
base: main
Are you sure you want to change the base?
Instantiable tuple labels #55452
Conversation
The TypeScript team hasn't accepted the linked issue #44939. If you can get it accepted, this PR will have a better chance of being reviewed. |
Looks like you're introducing a change to the public API surface area. If this includes breaking changes, please document them on our wiki's API Breaking Changes page. Also, please make sure @DanielRosenwasser and @RyanCavanaugh are aware of the changes, just as a heads up. |
20fac08
to
f6e2298
Compare
const index = pos - paramCount; | ||
const associatedName = associatedNames?.[index]; | ||
const isRestTupleElement = !!associatedName?.dotDotDotToken; | ||
|
||
if (associatedName) { | ||
Debug.assert(isIdentifier(associatedName.name)); | ||
// TODO: figure out the non-identifier case here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MariaSolOs what kind of inlay hint interactivity is expected out of a parameter name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expected behaviour is to be able to click on an argument of a function call and have that be a "go to definition" to the respective parameter in the function signature.
@typescript-bot pack this |
Heya @jakebailey, I've started to run the tarball bundle task on this PR at f6e2298. You can monitor the build here. |
Hey @jakebailey, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running There is also a playground for this build and an npm module you can use via |
f6e2298
to
b362f84
Compare
b362f84
to
724dc6c
Compare
@typescript-bot pack this |
Heya @DanielRosenwasser, I've started to run the tarball bundle task on this PR at 724dc6c. You can monitor the build here. |
Hey @DanielRosenwasser, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running There is also a playground for this build and an npm module you can use via |
@DanielRosenwasser this is still a draft that I put up since I wanted to share this with some people who asked for this feature. Since then I tested this more and it's not working correctly yet for some recursive cases etc. I have some work in progress locally that fixes some of those issues. While investigating them I learned a bunch of new things about how type references, mappers, etc are implemented under the hood 😉 Those learnings make it harder to implement this feature - or to rephrase: I've hoped for a simpler implementation but at the end of the day I can't avoid instantiating those labels sooner. This raises some data structure/internal API questions. Since those things are also consumed programmatically I'd like to ensure that an implementation design won't be too disruptive for those consumers. I have some ideas/some open questions related to that. If the team would be open to discussing those concerns before I sit down to implement an enhanced proof of concept - I would highly appreciate it. It would be also quite nice if the team could comment on general level of your interest in this feature :) |
Yeah, I think that's why I packed it - I want to gauge appetite/interest. Of course, even if we're interested, a big part of this will hinge on the complexity/maintainability/limitations of the implementation. |
Actually, I'm having a hard time imagining a reasonable implementation of |
I can't truly comment on type ToNamedTuple<
TAbiParameters extends readonly { name: string; type: unknown }[],
Results extends any[] = [],
> = TAbiParameters extends readonly [
infer Head extends { name: string; type: unknown },
...infer Tail extends readonly { name: string; type: unknown }[],
]
? ToNamedTuple<
Tail,
[...Results, `${Head['name']}`: Head['type']]
>
: Results
type Result = ToNamedTuple<
[
{ name: 'foo'; type: string },
{ name: 'bar'; type: bigint },
{ name: 'baz'; type: number },
]
> This is definitely implementable, just a matter of juggling type parameters and things. In the beginning, I thought that Then I tried to store a global mapping between the types and mappers but that didn't pan out because it turned out that types are heavily cached backed on their type arguments. So that made the labels to "leak" between tuple instantiations with the same element types. There is no good caching unit that would allow me to keep labels/mappers around - other than the type itself. Currently labels of tuples are Types created based on template literal types at labels positions should be somehow included in the type's ID. This way new types could be created based on different label instantiations and things would "just work". This has an obvious drawback of creating more tuple types with the same element types. I don't think that's a big issue from the memory PoV but the checker should learn how to compare such tuple tupes effectively - labels are purely decorative and they shouldn't affect the assignability rules between same element tuples. Alternatively, wrapper types could be introduced with |
Got some other motivating examples for you (potentially). I ran into a similar issue where I think I could benefit from the changes in this PR and from something such as Here are the examples:
What do you think?
|
Looking forward to this feature, my use case is converting function parameters to an object. |
closes #44939
A somewhat big drawback of this feature is that an instantiated label is only usable if it instantiates to a string literal type. This means that instantiations that end up being template literal types and even unions of strings are just discarded. I'm open to discussing other possible designs.
I think it's a reasonable tradeoff since this feature is primarily an editor experience improvement. Labels don't have any effect on type checking itself.