Mapped Types & Template Literal Types
Also Known As
mapped types
template literal types
TypeScript type transformation
TL;DR
Mapped types transform existing types by iterating over their keys. Template literal types create string union types from combinations — together they enable powerful type-level transformations.
Explanation
Mapped types: { [K in keyof T]: NewType } — iterate over all keys of T and transform their value types. Used to build Partial, Readonly, Required, and Record. Modifiers: +/- to add/remove optional (?) and readonly. Template literal types: `${Prefix}${string}` — create string union types by combining other string types. Applications: EventName as `on${Capitalize<Event>}`, getter names as `get${Capitalize<K>}`, CSS property names. Combined: transform an object type's method names into event handler names automatically.
Common Misconception
✗ Mapped types are only for utility types like Partial — mapped types can transform any aspect of a type: rename keys, change value types, filter keys by constraint, and generate derivative types.
Why It Matters
Without mapped types, you manually maintain parallel type definitions that drift apart — mapped types derive one type from another, ensuring they always stay in sync.
Common Mistakes
- Forgetting -? to remove optionality in mapped types — Required<T> needs -? modifier.
- Not using as clause for key remapping — available in TS 4.1+ for key transformation.
- Template literal types on non-string unions — only string literal unions work.
- Over-engineering with complex mapped types when a simpler type works.
Code Examples
✗ Vulnerable
// Manually maintained parallel types — drift risk:
type User = { name: string; email: string; age: number; };
// Must update this manually every time User changes:
type UserGetters = {
getName: () => string;
getEmail: () => string;
getAge: () => number;
};
✓ Fixed
// Mapped type derives UserGetters automatically:
type User = { name: string; email: string; age: number; };
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type UserGetters = Getters<User>;
// Equivalent to:
// { getName: () => string; getEmail: () => string; getAge: () => number; }
// Template literal type for event names:
type EventName = 'click' | 'focus' | 'blur';
type Handler = `on${Capitalize<EventName>}`; // 'onClick' | 'onFocus' | 'onBlur'
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
16 Mar 2026
Edited
22 Mar 2026
Views
27
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Perplexity 8
Amazonbot 7
Google 3
Unknown AI 3
Ahrefs 2
How they use it
crawler 20
crawler_json 2
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
🟢 Low
⚙ Fix effort: Medium
⚡ Quick Fix
Use Partial<T>, Required<T>, Readonly<T>, Record<K,V>, Pick<T,K>, and Omit<T,K> from TypeScript's built-in utility types before writing your own mapped types
📦 Applies To
typescript 2.1
web
cli
🔍 Detection Hints
Manually duplicating interface with optional properties when Partial<T> would work; custom mapped type re-implementing built-in utility types
Auto-detectable:
✓ Yes
typescript
eslint
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: High
✗ Manual fix
Fix: High
Context: File