Mapped types with conditional types help you create new object types by changing properties based on conditions. This makes your code flexible and safe.
Mapped type with conditional types in Typescript
type NewType<T> = {
[P in keyof T]: T[P] extends SomeCondition ? TypeIfTrue : TypeIfFalse
};Mapped types loop over keys of a type using [P in keyof T].
Conditional types check each property type with extends and choose a type accordingly.
readonly modifier to property types only if the property type is string.type ReadonlyStrings<T> = {
[P in keyof T]: T[P] extends string ? Readonly<T[P]> : T[P]
};null to properties that are numbers.type NullableNumbers<T> = {
[P in keyof T]: T[P] extends number ? T[P] | null : T[P]
};This program creates a new type where string properties can also be undefined. The name property is allowed to be undefined because it is a string in the original type.
type User = {
id: number;
name: string;
active: boolean;
};
type OptionalStrings<T> = {
[P in keyof T]: T[P] extends string ? T[P] | undefined : T[P]
};
const user1: OptionalStrings<User> = {
id: 1,
name: undefined, // allowed because name is string type
active: true
};
console.log(user1);Conditional types run for each property separately inside the mapped type.
You can combine multiple conditions for more complex transformations.
Mapped types with conditional types help keep your types DRY and adaptable.
Mapped types loop over keys to create new types.
Conditional types choose types based on conditions.
Together, they let you transform object types smartly and safely.
Practice
type Example<T> = { [K in keyof T]: T[K] extends string ? number : boolean }Solution
Step 1: Understand mapped types
Mapped types loop over each key in the original type to create a new type with transformed properties.Step 2: Apply conditional types
The conditional type checks if the property type extends string; if yes, it changes to number, else to boolean.Final Answer:
It creates a new type where string properties become number and others become boolean. -> Option AQuick Check:
Mapped + conditional changes types based on condition [OK]
- Thinking it removes properties instead of transforming them
- Assuming all types become string
- Confusing conditional type logic
Solution
Step 1: Check mapped type syntax
The correct syntax uses square brackets with 'in' keyword: [K in keyof T].Step 2: Verify conditional type usage
The conditional type is written as T[K] extends number ? string : boolean, which is correct.Final Answer:
type NewType<T> = { [K in keyof T]: T[K] extends number ? string : boolean } -> Option BQuick Check:
Mapped type syntax = [K in keyof T] [OK]
- Using 'K in T' instead of 'K in keyof T'
- Using 'K of keyof T' which is invalid
- Missing square brackets around K in mapped type
type Flags = { a: string; b: number; c: boolean };
type Result = { [K in keyof Flags]: Flags[K] extends number ? 'num' : 'not-num' };
const test: Result = { a: 'not-num', b: 'num', c: 'not-num' };What is the type of
test.b?Solution
Step 1: Analyze the mapped type Result
For each key in Flags, if the property type is number, Result's property is 'num', else 'not-num'.Step 2: Check property b in Flags
b is number, so Result['b'] is 'num'.Final Answer:
'num' -> Option CQuick Check:
Flags['b'] is number, so Result['b'] = 'num' [OK]
- Confusing original property type with mapped type
- Assuming test.b is number instead of 'num'
- Ignoring conditional type logic
type Fix<T> = { [P in keyof T]: T[P] extends string ? number : }Solution
Step 1: Check conditional type syntax
Conditional types require both true and false branches separated by colon.Step 2: Identify missing false branch
The code ends with ':' but no type after it, causing syntax error.Final Answer:
Missing type after colon in conditional type -> Option DQuick Check:
Conditional types need both branches [OK]
- Leaving out false branch in conditional type
- Misplacing square brackets in mapped type
- Thinking keyof is wrong here
Choose the correct mapped type:
Solution
Step 1: Understand key remapping in mapped types
Using 'as' allows filtering keys by condition, replacing keys with 'never' to omit them.Step 2: Check each option
type FilterStrings<T> = { [K in keyof T as T[K] extends string ? K : never]: T[K] } correctly uses 'as' with conditional to keep keys where T[K] extends string; others become never (excluded).Final Answer:
type FilterStrings<T> = { [K in keyof T as T[K] extends string ? K : never]: T[K] } -> Option AQuick Check:
Key remapping with 'as' filters keys [OK]
- Not using 'as' for key filtering
- Returning never as value instead of key
- Confusing key and value conditions
Ready to prove it?
Pass the test and this pattern moves unknown
