Lesson 16 of 80
JavaScript's template literal syntax, moved into type-space — building new string literal types by combining and interpolating other literal types.
11 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 2
`type Margin = \`margin-${Direction}\`` where Direction is `"top" | "bottom"`. What type does Margin resolve to?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
type Direction = "top" | "bottom" | "left" | "right";
type Margin = `margin-${Direction}`;
// "margin-top" | "margin-bottom" | "margin-left" | "margin-right"
The syntax is literally the same ${} interpolation from JavaScript's template literals — but at the type level, TypeScript computes every combination and produces a new union of literal string types. Interpolating a union inside a template literal type distributes across every member, the same distribution behavior conditional types have over unions.
type EventName = "click" | "focus" | "blur";
type HandlerName = `on${Capitalize<EventName>}`;
// "onClick" | "onFocus" | "onBlur"
type Handlers = { [K in HandlerName]?: () => void };
// { onClick?: () => void; onFocus?: () => void; onBlur?: () => void }
Combined with a mapped type, this generates exactly the handler-prop names a component would need — onClick, onFocus, onBlur — computed from a single source list of event names, instead of hand-typing each one and risking them drifting out of sync.
type EventName = `on${Capitalize<string>}` — a type built like a template string, at the type level.
type Margin = \margin-$`` produces a set of valid string type possibilities the compiler checks against; nothing about it exists once compiled to JavaScript.type Hex = \#$`requires a string starting with#`, which is a real, checkable constraint at the type level."How would you generate a type for onClick/onFocus/onBlur handler props from a list of event names, without writing each one by hand?" is a great concrete exercise, and template literal types plus a mapped type is exactly the idiomatic answer.