-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Completions from template literal types #59794
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
base: main
Are you sure you want to change the base?
Completions from template literal types #59794
Conversation
@@ -297,6 +310,22 @@ function convertStringLiteralCompletions( | |||
} | |||
} | |||
|
|||
function getStringLiteralCompletionFromTemplateLiteralTypeAndTextOfNode(type: TemplateLiteralType, tokenTextContent: string, quoteChar: CharacterCodes.backtick | CharacterCodes.singleQuote | CharacterCodes.doubleQuote) { |
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.
There is an existing algorithm for matching strings against template literal types that you can find in isTypeMatchedByTemplateLiteralType
. Instead of trying to implement a custom one, I'd recommend looking into how you could reuse that one. You can expose some checker functionality on the TypeChecker
using new methods annotated with /** @internal */
.
Perhaps you will have to focus on the algorithm in inferFromLiteralPartsToTemplateLiteral
. It could return a number for the last segment matched successfully instead of undefined
. Using this number you could look at the text after it and suggest that as autocompletion.
Note that this is just a rough idea, I don't know how feasible it will be in practice 😉
It could be nice to use the same algorithm to autocomplete properties coming from index signatures with template literal keys. You don't have to implement this as part of this PR though. One thing at a time 😅
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.
Hmm, this matching works in the escaped string (source code) space, while the checker's works in raw string content space. Shouldn't be the biggest issue though, instead of escaping the type.text, we would need to unescape token.content. Especially for future generalisations, this is probably a good direction to take but this version is so simple, that I didn't feel the need to use the checker.
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.
Also, inferFromLiteralPartsToTemplateLiteral
starts by first checking that both the starts and the ends of the source and the target are compatible, which is not what we need here. (Ok but that seems to be just for a perf reason? and could be skipped with a flag.)
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.
Actually, I don't think that function is very useful for matching of the partial string. I think that this requires a different algorithm by nature.
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.
Could u expand on that? At the very least the rules there could guide u how to handle number interpolations and more
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.
Sure, there are functions like isValidTypeForTemplateLiteralPlaceholder
that could certainly prove usefule, but I'm not sure the overall algorithm that finds the target text parts in the source type is that reuseable. And
it's much less clear to me how they should work
meant less "I don't know how to do it" and more "I don't know what it should be doing". Like in
const x: `a${number}` = "a/**/
what is the completion? I guess nothing? How about
const x: `a${number}` = "ab/**/
Maybe replacement of "ab
with "a
?
Implements completions from types of the form
, that is, from template literal types where
string
is the only placeholder. For the other cases (prefix${number}
), it's much less clear to me how they should work.The completions implemented in this PR suggest appending the "next" (the first that is not already included) text part of the template literal type. For example
suggests
a_b
.Closes #59698
Please verify that:
Backlog
milestone (required)main
branchhereby runtests
locally