You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Try to preserve template-ness of string literal types where possible #41631
Now that we have template literal types, I would love to have the ability to apply them to string template literals.
Use Cases
This would be really useful in the ioBroker type declarations where we try to infer the object types returned by some methods from the given IDs. These IDs can be directly specified in the method calls, but are in reality often built from multiple parts.
A dumbed down example is shown in the following examples:
Both id4 and the string passed to the third call of takesLiteral are string constants that are created with a template literal. TypeScript should be able to preserve that literal-ness, since it already knows we're feeding a string into a template string.
This means we could work with literals of type foo.bar.${string}, not string like we currently do.
Checklist
My suggestion meets these guidelines:
This wouldn't be a breaking change in existing TypeScript/JavaScript code
This wouldn't change the runtime behavior of existing JavaScript code
This could be implemented without emitting different JS based on the types of the expressions
This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
This is already covered by #40707 with the caveat that you need to include as const to get template literal types. It would be a breaking change to do it for all template literal expressions, so I think that's the best we can do.
Anders Hejlsberg (@ahejlsberg) cool, that is good to know. Can you elaborate how that would be breaking? These literals should still be assignable to string?
The mentioned PR only applies to TypeScript though, not JavaScript. Is there any way to get the desired behavior in JS?
I can't use as const there, nor can I explain all the users of my API (often beginners) how to use JSDoc type casts (is there even one for as const?) as a workaround.
We'd end up giving more specific types to variables with types inferred from initializers, which would be breaking. However, we could consider introducing widening and non-widening template literals akin to what we do for regular literal types (see #10676 and #11126 for context).
We tried this and it turned out to be a bit too breaky and didn't really model user expectations. We can reconsider something that avoids the pain that the last one added, but it's unclear what that would be. In the meantime, you can use as const on your template strings.
Please limit discussion to useful additions, thoughts, or insights - no :+1:s or "just as a use case"s, since those won't be constructive. If you really need to do something like that, vote 👍 on the issue itself.
Note the use of as const in the assignment to id4. An alternative would be to have a `foo.bar.${string}` type annotation, but we won't infer a template literal type without some indication it is desired.
Activity
RyanCavanaugh commentedon Dec 1, 2020
Anders Hejlsberg (@ahejlsberg) thoughts?
ahejlsberg commentedon Dec 2, 2020
This is already covered by #40707 with the caveat that you need to include
as constto get template literal types. It would be a breaking change to do it for all template literal expressions, so I think that's the best we can do.AlCalzone commentedon Dec 2, 2020
Anders Hejlsberg (@ahejlsberg) cool, that is good to know. Can you elaborate how that would be breaking? These literals should still be assignable to
string?The mentioned PR only applies to TypeScript though, not JavaScript. Is there any way to get the desired behavior in JS?
I can't use
as constthere, nor can I explain all the users of my API (often beginners) how to use JSDoc type casts (is there even one foras const?) as a workaround.ahejlsberg commentedon Dec 2, 2020
We'd end up giving more specific types to variables with types inferred from initializers, which would be breaking. However, we could consider introducing widening and non-widening template literals akin to what we do for regular literal types (see #10676 and #11126 for context).
AlCalzone commentedon Dec 2, 2020
I don't quite grasp the implications of this change but this seems like it might cover most of the use cases I have in mind.
ahejlsberg commentedon Dec 9, 2020
Now implemented in #41891.
DanielRosenwasser commentedon Feb 19, 2021
We tried this and it turned out to be a bit too breaky and didn't really model user expectations. We can reconsider something that avoids the pain that the last one added, but it's unclear what that would be. In the meantime, you can use
as conston your template strings.Please limit discussion to useful additions, thoughts, or insights - no
:+1:s or "just as a use case"s, since those won't be constructive. If you really need to do something like that, vote 👍 on the issue itself.AlCalzone commentedon Feb 19, 2021
I've raised #42884 to request support for the
as constworkaround in JS, because that is currently not an option for JS devs.ahejlsberg commentedon Mar 26, 2021
In #43376 (now merged) we fix this as much as possible without introducing breaking changes:
Note the use of
as constin the assignment toid4. An alternative would be to have a`foo.bar.${string}`type annotation, but we won't infer a template literal type without some indication it is desired.