Skip to content

Interpolating values matching template literal type interpolations does not necessarily result in a string assignable to the template literal type #62625

@TomerAberbach

Description

@TomerAberbach

🔎 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

https://www.typescriptlang.org/play/?ts=5.9.3#code/PTAEHUHsCcGsGcBQBjSA7eAXUAzAltFgFyhbR5oDmoAvKAOSgC09K6WpApqmgCYloArgFsARp2i1QABjYZsmABYF+pTOSpT6AQ1Y8O2kgAMAJAG8yFSgF9moc0LETbTexfVXrRqabP5CmC5u8NzovEHmSipeiIggoAAikJzwoGiQ2ADuMLCgABScAG6caKBKkIKUiqBG-lgAjEYANDUhPLyNLdp8NVHQHd7a0JykgqKYAJ4ADimgkDg1dZjNraF8K928vcr9K8PwM8iYeMUANhMAlHIcS-VazHrs2G1hd3Sy+go7HVq619iiYzmSxUCJmRziaBgkE2bx0Xy3aFrDpgvoooz-UDIIHuDQ2OwOESQ6EeUFwmrmRgsMHSME6egxT6gVS+GFgiHOAm4zzkql2aR2AAerCAA

💻 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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions