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
Concatention of string index templates ${number}${string}${number} is not additive w.r.t. accepted strings.Β #46124
This is working as intended, but I agree it may be a bit surprising. Quoting from the original PR for this feature, here's how matching works:
Type inference supports inferring from a string literal type to a template literal type. For inference to succeed the starting and ending literal character spans (if any) of the target must exactly match the starting and ending spans of the source. Inference proceeds by matching each placeholder to a substring in the source from left to right: A placeholder followed by a literal character span is matched by inferring zero or more characters from the source until the first occurrence of that literal character span in the source. A placeholder immediately followed by another placeholder is matched by inferring a single character from the source.
Note the last sentence. When placeholders are immediately next to each other, the first placeholder just infers a single character from the source. The kind of placeholder being inferred to doesn't matter for determining the inferred text, it only matters for validating the text. The rationale for the single character behavior is to provide a mechanism for picking apart string literals using inference in conditional types, as in S extends `${infer Char}${infer Rest}` ? .... It is less useful with non-generic placeholders, but the behavior is the same for consistency and because we use a single matching algorithm. That algorithm is fairly simple, but that is by design. We really don't want to turn our type system into another RegEx engine.
Thanks for the detailed answer and the pointer to the very clear documentation. Now I understand why a final ${string} can accept the empty string and can code accordingly.
Activity
ahejlsberg commentedon Sep 29, 2021
This is working as intended, but I agree it may be a bit surprising. Quoting from the original PR for this feature, here's how matching works:
Note the last sentence. When placeholders are immediately next to each other, the first placeholder just infers a single character from the source. The kind of placeholder being inferred to doesn't matter for determining the inferred text, it only matters for validating the text. The rationale for the single character behavior is to provide a mechanism for picking apart string literals using inference in conditional types, as in
S extends `${infer Char}${infer Rest}` ? .... It is less useful with non-generic placeholders, but the behavior is the same for consistency and because we use a single matching algorithm. That algorithm is fairly simple, but that is by design. We really don't want to turn our type system into another RegEx engine.craigphicks commentedon Sep 29, 2021
Thanks for the detailed answer and the pointer to the very clear documentation. Now I understand why a final ${string} can accept the empty string and can code accordingly.