Description
🔎 Search Terms
Template Literal Types, assignability, generics
🕗 Version & Regression Information
- Between versions 4.3.5 and 4.2.3 more cases like this started being supported (
x.${Name}
became assignable to${string}.${Name}
for example), however thex.y.${Name}
case has not bees assignable in any version since template support was added up to and including current nightly ( 5.9.0-dev.20250702 )
⏯ Playground Link
💻 Code
/**
* Compile time assert that A is assignable to (extends) B.
* To use, simply define a type:
* `type _check = requireAssignableTo<T, Expected>;`
*/
export type requireAssignableTo<_A extends B, B> = true;
type worksSinceTypeScript4_3<Name extends string> = requireAssignableTo<
`x.${Name}`,
`${string}.${Name}`
>;
type fails<Name extends string> = requireAssignableTo<
// Type '`x.y.${Name}`' does not satisfy the constraint '`${string}.${Name}`'.(2344)
`x.y.${Name}`,
`${string}.${Name}`
>;
type nonGenericWorks = requireAssignableTo<
`x.y.z`,
`${string}.z`
>;
🙁 Actual behavior
A compile error:
Type '
x.y.${Name}
' does not satisfy the constraint '${string}.${Name}
'.(2344)
🙂 Expected behavior
No compile error. The .${Name}
portion of the type matches exactly, so this can be reduced to checking if "x.y"
is assignable to string
should be allowed.
Additional information about the issue
I understand that in general not all cases like that are practical to support: perfect assignability checking of template strings is likely infeasible but I decided to report this case as I think this one suggest an algorithm that would be practical to implement and efficient: running a greedy algorithm to remove common constant substrings from the beginning and end of the string, including generic values, might be a viable approach, and would improve handling of this case.