Mapped Types & Template Literal Types
debt(d5/e3/b3/t5)
Closest to 'specialist tool catches it' (d5). The detection_hints list TypeScript (the type checker) and ESLint as tools. The code_pattern describes manually duplicating interfaces instead of using Partial<T> or built-in utility types — TypeScript's compiler won't error on this duplication, but a specialist TypeScript-aware linter rule (e.g. @typescript-eslint) or careful review would catch redundant parallel type definitions. It won't surface as a compiler error (not d1/d3), but TypeScript itself as a type-checking tool sits at d5.
Closest to 'simple parameterised fix' (e3). The quick_fix says to use built-in utility types (Partial<T>, Required<T>, etc.) before writing custom mapped types. Replacing a manually duplicated interface with Partial<T> or another utility type is a small, localised refactor — more than a one-liner swap in practice because it may involve multiple property definitions, but it stays within one component/file, placing it at e3.
Closest to 'localised tax' (b3). Mapped types apply to web and cli contexts broadly, but their burden is scoped to the type layer of TypeScript — misuse (over-engineering or manual duplication) primarily taxes the module or component where the types are defined. Other parts of the codebase are largely unaffected unless the types are shared widely. This keeps the structural debt localised rather than system-wide.
Closest to 'notable trap' (t5). The misconception field identifies a real but learnable gotcha: developers assume mapped types are only for utility types like Partial, missing their full power to rename keys, filter by constraint, and generate derivative types. Additionally, common_mistakes include forgetting -? for Required<T>, misusing as clause, and applying template literal types to non-string unions — these are documented gotchas that most developers encounter once and learn, fitting the t5 anchor well.
Also Known As
TL;DR
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
Why It Matters
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
// 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;
};
// 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'