Mapped Types and Conditional Types
Build mapped types to transform all properties of a type and use conditional types with infer for advanced type-level logic.
Mapped Types and Conditional Types is a free Frontend Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Mapped Types — Transform Every Property
Mapped types iterate over the keys of a type and transform them. They're the foundation of Partial, Readonly, and Record utility types.
// Partial implemented as a mapped type:
type MyPartial<T> = {
[K in keyof T]?: T[K];
};
// Readonly:
type MyReadonly<T> = {
readonly [K in keyof T]: T[K];
};Remapping Keys with as
Use as in the mapping clause to remap key names. Combine with template literal types for powerful transformations.
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type UserGetters = Getters<{ name: string; age: number }>;
// { getName: () => string; getAge: () => number }Filtering Properties with never
Return never from a key remapping to remove that property from the resulting type.
// Keep only function-valued properties:
type FunctionProperties<T> = {
[K in keyof T as T[K] extends Function ? K : never]: T[K];
};Conditional Types — if/else for Types
Conditional types use the pattern T extends U ? TrueType : FalseType. Evaluated at the type level, not at runtime.
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
type Flatten<T> = T extends Array<infer E> ? E : T;
type StrArr = Flatten<string[]>; // string
type Num = Flatten<number>; // numberDistributive Conditional Types
When T is a union, conditional types distribute over each member. string | number extends string ? ... checks each separately: (string extends string ? ...) | (number extends string ? ...).
type ToArray<T> = T extends any ? T[] : never;
type StringOrNumberArray = ToArray<string | number>;
// string[] | number[] (not (string | number)[])Using infer to Extract Types
infer R introduces a type variable that TypeScript fills in. It lets you capture parts of a type structure.
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type Resolved = UnwrapPromise<Promise<string>>; // string
type Direct = UnwrapPromise<number>; // numberTemplate Literal Types
Template literal types use the same backtick syntax as template literals but at the type level, creating union types from combinations of string literals.
type Side = 'top' | 'right' | 'bottom' | 'left';
type PaddingKey = `padding-${Side}`;
// 'padding-top' | 'padding-right' | 'padding-bottom' | 'padding-left'
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<'click'>; // 'onClick'Combining Mapped and Conditional Types
The most powerful TypeScript patterns combine both. The built-in required, partial, readonly, and record types are all mapped types.
// Make all functions in an object async:
type Asyncify<T> = {
[K in keyof T]: T[K] extends (...args: infer A) => infer R
? (...args: A) => Promise<R>
: T[K];
};DeepPartial — Recursive Utility Type
The built-in Partial only goes one level deep. A DeepPartial recurses into nested objects.
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};Real-World Use: API Response Types
Mapped and conditional types enable powerful API type derivations — e.g., extract only the JSON-serialisable properties of an object.
Avoid Over-Engineering
Complex type gymnastics can make code hard to understand. Always ask: is a simpler type alias or interface clearer? Types should document intent, not demonstrate TypeScript mastery.
Quick Check
What does T extends U ? A : B evaluate to when T is a union type?
Recap: Mapped and Conditional Types
Mapped types iterate over keys with [K in keyof T]. Use as to remap keys. Return never to filter. Conditional types: T extends U ? A : B. infer extracts type variables. Template literal types build string unions. Combine both for powerful type transformations like DeepPartial and Asyncify.
Frequently asked questions
Is the “Mapped Types and Conditional Types” lesson free?
Yes — the full text of “Mapped Types and Conditional Types” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.
What will I learn in “Mapped Types and Conditional Types”?
Build mapped types to transform all properties of a type and use conditional types with infer for advanced type-level logic. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Frontend Academy?
No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Mapped Types and Conditional Types” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Frontend Academy lesson?
Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Generics: T extends and constraints
- Utility Types: Partial Required Pick Omit
- Mapped Types and Conditional Types
- Narrowing: typeof instanceof discriminated unions