-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
🔎 Search Terms
template type, template literal, substitution, mental model, parity, roundtrip, assignable, interpolation, string, constant
🕗 Version & Regression Information
This is the behavior in every version I tried, and I reviewed the FAQ for entries about... I couldn't find any FAQ entry about template literal types.
⏯ Playground Link
💻 Code
// Works
const first: string = ' -'
const second: number = 0
const third: string = 'a'
const a: `${string} - ${number} - ${string}` = `${first} - ${second} - ${third}`
// Does not work (even though `first1`, `second1`, and `third1` are subtypes of `first`, `second`, and `third`, respectively)
const first1 = ' -'
const second1 = 0
const third1 = 'a'
const b: `${string} - ${number} - ${string}` = `${first1} - ${second1} - ${third1}`
const c: `${string} - ${number} - ${string}` = `${' -'} - ${0} - ${'a'}`
const d: `${string} - ${number} - ${string}` = ' - - 0 - x'
🙁 Actual behavior
The last block of assignments does not typecheck.
That's wrong because each of the template string interpolation types (string
, number
, and string
) was replaced with a value that's assignable to the interpolation type.
It's also wrong that making the types of first
, second
, and third
more specific (i.e. subtypes) makes the code not typecheck anymore. That's a violation of the Liskov substitution principle.
🙂 Expected behavior
The last two assignments should typecheck for the reasons stated before.
Additional information about the issue
My mental model of template literal types is "if I replace each interpolated type placeholder with a value that is assignable to it, then I will end up with a string that matches the template literal type".
This seems to not be generally true, but I don't really know what other mental model would make sense. If that's not the mental model, then what is? How do I know if a given string value is assignable to a given template literal type?