How to fix Type 'X' is not assignable to template literal type 'Y' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 11, 2025ยท 111 views

This error occurs when TypeScript cannot verify that a string value matches a template literal type pattern. It commonly happens with template string expressions and dynamic values that TypeScript evaluates as the generic string type.

Quick fix

Fixes Type 'X' is not assignable to template literal type 'Y'

type PixelValue = `${number}px`;

// Error: Type 'string' is not assignable to type '`${number}px`'
const width: PixelValue = `22px`;

// Fix: Use type assertion
const width: PixelValue = `22px` as PixelValue;

// Or with angle bracket syntax
const height = <PixelValue>`44px`;
  1. Use type assertions to explicitly cast the value
  2. Declare string literals directly instead of using template syntax
  3. Create a helper function with proper type guards
  4. Use const assertions for literal values
typescript โ€” error
type PixelValue = `${number}px`;
// Error: Type 'string' is not assignable to type '`${number}px`'
const width: PixelValue = `22px`;
// Fix: Use type assertion
const width: PixelValue = `22px` as PixelValue;
// Or with angle bracket syntax
const height = <PixelValue>`44px`;
Type 'X' is not assignable to template literal type 'Y'

What this error means

This error appears when you try to assign a value to a variable or parameter that has a template literal type, but TypeScript cannot confirm the value matches the pattern. Template literal types, introduced in TypeScript 4.1, allow you to define precise string patterns using backticks and placeholders like `${string}` or `${number}px`. The core issue is that TypeScript often evaluates template string expressions to the generic `string` type rather than the more specific template literal type, even when the value would match at runtime. This happens because TypeScript's type system performs static analysis and cannot always infer the exact string pattern from dynamic expressions. Prior to TypeScript 4.3, this was a common limitation where arbitrary template literal types couldn't be assigned to each other. While improvements were made in 4.3 with better assignability rules, certain scenarios still trigger this error, particularly when using variables in template literals or complex nested patterns.

Typical symptoms

  • TypeScript compiler error when assigning template strings to template literal type variables
  • Error appears even though the runtime value would be valid
  • Type checking fails for string variables interpolated in template literals
  • Works with literal values but fails with const variables using "as const"
  • Complex template patterns like `${string}${number}${string}` reject valid matching strings

Common causes

  1. Template string expression is widened to generic "string" type instead of preserving the literal pattern
  2. Using variables in template literals causes TypeScript to lose type information even with const assertions
  3. TypeScript lacks sophisticated assignability rules for all template literal type combinations
  4. Multiple interpolations in template literal types create patterns TypeScript cannot verify statically
  5. Type narrowing is not applied to template string expressions in the same way as string literals

How to fix "Type 'X' is not assignable to template literal type 'Y'"

1Use type assertions to explicitly cast the value

The most direct solution is to use a type assertion when you're confident the value matches the pattern:

typescript
type PixelValue = `${number}px`;

// Error: Type 'string' is not assignable to type '`${number}px`'
const width: PixelValue = `22px`;

// Fix: Use type assertion
const width: PixelValue = `22px` as PixelValue;

// Or with angle bracket syntax
const height = <PixelValue>`44px`;

This tells TypeScript to trust that the value matches the pattern. Use this when you're certain the runtime value will always be valid.

2Declare string literals directly instead of using template syntax

If the value is truly static, use a plain string literal instead of a template literal:

typescript
type StatusMessage = `Status: ${string}`;

// Instead of this (causes error):
const message: StatusMessage = `Status: ${status}`;

// Use this if the value is static:
const message: StatusMessage = 'Status: Success';

// Or construct it differently:
function createStatusMessage(status: string): StatusMessage {
  return `Status: ${status}` as StatusMessage;
}

This approach works when you don't need dynamic interpolation at the assignment point.

3Create a helper function with proper type guards

Build a type-safe constructor function that validates and returns the template literal type:

typescript
type PixelValue = `${number}px`;

function createPixelValue(value: number): PixelValue {
  return `${value}px` as PixelValue;
}

// Type-safe usage
const width = createPixelValue(22); // PixelValue

// With validation
function toPixelValue(input: string): PixelValue | null {
  const match = input.match(/^(\d+)px$/);
  if (!match) return null;
  return input as PixelValue;
}

This centralizes the type assertion and can include runtime validation logic.

4Use const assertions for literal values

When working with actual string literals, use as const to preserve the exact literal type:

typescript
type EventName = `on${Capitalize<string>}`;

// This works - literal is preserved
const event1: EventName = 'onClick';

// This fails even with as const on the variable
const eventBase = 'click' as const;
const event2: EventName = `on${eventBase}`; // Error

// Fix: Use satisfies operator (TypeScript 4.9+)
const event3 = `onClick` satisfies EventName;

// Or assertion on the full expression
const event4: EventName = 'onClick' as const;

The satisfies operator provides type checking without widening the type.

5Simplify complex template literal patterns

If you're using intricate patterns like multiple interpolations, consider breaking them down:

typescript
// Complex pattern that may cause issues
type Complex = `${string}:${number}:${string}`;

// Simplify or use union types instead
type SimplePrefix = `prefix:${string}`;
type SimpleSuffix = `${string}:suffix`;
type Combined = SimplePrefix | SimpleSuffix;

// Or use a broader type
type Flexible = `${string}:${string}`;

Simpler patterns are more reliably checked by TypeScript's type system.

6Upgrade TypeScript to get improved template literal support

Many template literal type assignability issues were fixed in TypeScript 4.3 and later versions:

bash
# Check your TypeScript version
npx tsc --version

# Upgrade to latest version
npm install -D typescript@latest

# Or upgrade to specific version
npm install -D typescript@^5.0.0

Update your tsconfig.json to use the new version:

json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext"
  }
}

TypeScript 4.3 added assignability rules for template literal types, and 4.9 added the satisfies operator which helps with these scenarios.

Advanced notes

TypeScript Compiler Limitations

TypeScript's type system performs static analysis without executing code, which means it cannot evaluate template string expressions to determine their exact runtime value. When you write ${value}px, TypeScript only knows this produces a string, not specifically a string matching the ${number}px pattern.

Template Literal Type Inference

The type inference for template literal types follows specific rules. A template literal type A is assignable to template literal type B when every possible string that A can represent is also representable by B. This means user_${string} is assignable to ${string}, but not the reverse.

String Widening Behavior

TypeScript widens template string expressions containing variables to the string type even when those variables are declared with as const. This is because the template literal itself creates a new value, and TypeScript conservatively treats this as producing a general string rather than a specific pattern.

When to Use Type Assertions

Type assertions with template literal types are generally safe when:
- You control the input values and can guarantee they match the pattern
- You have runtime validation ensuring the pattern is correct
- The pattern is simple enough that manual verification is straightforward

Avoid assertions when dealing with user input or external data without validation, as this bypasses TypeScript's type safety.

Related GitHub Discussions

The TypeScript team has extensively discussed template literal type assignability in issues #43243, #41732, and #57355. PR #43361 (merged in TypeScript 4.3) improved relations and inference between template literal types, but some edge cases remain, particularly with complex nested patterns and certain forms of string interpolation.

Frequently asked questions

What does "Type 'X' is not assignable to template literal type 'Y'" mean?
This error appears when you try to assign a value to a variable or parameter that has a template literal type, but TypeScript cannot confirm the value matches the pattern. 1, allow you to define precise string patterns using backticks and placeholders like ${string} or ${number}px. The core issue is that TypeScript often evaluates template string expressions to the generic string type rather than the more specific template literal type, even when the value would match at runtime.
How do I fix "Type 'X' is not assignable to template literal type 'Y'"?
This error occurs when TypeScript cannot verify that a string value matches a template literal type pattern. It commonly happens with template string expressions and dynamic values that TypeScript evaluates as the generic string type.
What causes "Type 'X' is not assignable to template literal type 'Y'"?
Template string expression is widened to generic "string" type instead of preserving the literal pattern Using variables in template literals causes TypeScript to lose type information even with const assertions TypeScript lacks sophisticated assignability rules for all template literal type combinations
Is the "Type 'X' is not assignable to template literal type 'Y'" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading