📖 Scenario: Imagine you have a list of user settings in a web app. Each setting can be turned on or off. You want to create a new version of these settings where all options are optional, so users can change only what they want.
🎯 Goal: Learn how to use mapped types in TypeScript to create a new type where all properties of an existing type become optional.
📋 What You'll Learn
Create a type called UserSettings with exact properties: theme, notifications, and autoSave all of type boolean
Create a mapped type called OptionalSettings that makes all properties of UserSettings optional
Create a variable called mySettings of type OptionalSettings with only theme set to true
Print the mySettings variable
💡 Why This Matters
🌍 Real World
Mapped types help when you want to create new versions of existing data shapes, like making settings optional or readonly, without rewriting all properties.
💼 Career
Understanding mapped types is important for TypeScript developers to write flexible and reusable code, especially in large projects with complex data models.
Progress0 / 4 steps
1
Create the initial type for user settings
Create a type called UserSettings with these exact properties: theme, notifications, and autoSave, all of type boolean.
Typescript
Hint
Use type UserSettings = { ... } and list the properties with their types.
2
Create a mapped type to make all properties optional
Create a mapped type called OptionalSettings that makes all properties of UserSettings optional using keyof and in syntax.
Typescript
Hint
Use [K in keyof UserSettings]?: UserSettings[K] to make properties optional.
3
Create a variable using the mapped type
Create a variable called mySettings of type OptionalSettings and set only the theme property to true.
Write a console.log statement to print the mySettings variable.
Typescript
Hint
Use console.log(mySettings) to show the variable.
Practice
(1/5)
1. Why are mapped types needed in TypeScript?
easy
A. To create new types by transforming all properties of an existing type easily
B. To write functions that return multiple values
C. To define classes with private members
D. To handle asynchronous operations
Solution
Step 1: Understand the purpose of mapped types
Mapped types allow you to take an existing type and create a new type by changing all its properties in a consistent way.
Step 2: Compare with other options
Options B, C, and D relate to other TypeScript or JavaScript features but do not describe mapped types.
Final Answer:
To create new types by transforming all properties of an existing type easily -> Option A
Quick Check:
Mapped types = transform all properties easily [OK]
Hint: Mapped types transform all properties of a type at once [OK]
Common Mistakes:
Confusing mapped types with functions or classes
Thinking mapped types handle async code
Believing mapped types define private members
2. Which of the following is the correct syntax to create a mapped type that makes all properties of T readonly?
easy
A. type Readonly<T> = { [P in T]: readonly T[P] }
B. type Readonly<T> = { [P in keyof T]: readonly T[P] }
C. type Readonly<T> = { readonly T[P] in keyof T }
D. type Readonly<T> = { readonly [P in keyof T]: T[P] }
Solution
Step 1: Analyze mapped type syntax
The correct syntax uses [P in keyof T] to iterate over keys and applies readonly before the property name.
Step 2: Identify errors in other options
type Readonly<T> = { [P in keyof T]: readonly T[P] } incorrectly places readonly after the colon. type Readonly<T> = { [P in T]: readonly T[P] } uses [P in T] which is invalid. type Readonly<T> = { readonly T[P] in keyof T } has incorrect order and syntax.
Final Answer:
type Readonly<T> = { readonly [P in keyof T]: T[P] } -> Option D
Quick Check:
Mapped type syntax = readonly before [P in keyof T] [OK]
Hint: Use 'readonly [P in keyof T]' to make properties readonly [OK]
Common Mistakes:
Placing readonly after the property type
Using wrong iteration syntax like [P in T]
Misordering readonly and the mapped key
3. Given the code below, what is the type of OptionalUser?
type User = { id: number; name: string; };
type OptionalUser = { [P in keyof User]?: User[P] };
medium
A. { id: number; name: string; }
B. { id: number | undefined; name: string | undefined; }
C. { id?: number; name?: string; }
D. Error: Invalid mapped type syntax
Solution
Step 1: Understand the mapped type with optional modifier
The ? after [P in keyof User] makes each property optional.
Step 2: Compare with options
{ id?: number; name?: string; } correctly shows all properties optional. { id: number; name: string; } is original type. { id: number | undefined; name: string | undefined; } uses union with undefined which is different. Error: Invalid mapped type syntax is incorrect as syntax is valid.
Final Answer:
{ id?: number; name?: string; } -> Option C
Quick Check:
Mapped type with ? = all properties optional [OK]
Hint: Adding ? after [P in keyof T] makes properties optional [OK]
Common Mistakes:
Confusing optional properties with union types
Thinking original type remains unchanged
Assuming syntax error in mapped types
4. Identify the error in the following mapped type and fix it:
type ReadonlyUser<T> = { [P in keyof T] T[P] readonly }
medium
A. Remove readonly modifier completely
B. The readonly modifier should come before the property name: { readonly [P in keyof T]: T[P] }
C. Change keyof T to keyof User
D. Add a semicolon after T[P]
Solution
Step 1: Check mapped type syntax
The readonly modifier must be placed before the property name in mapped types.
Step 2: Correct the syntax
Rewrite as { readonly [P in keyof T]: T[P] } to fix the error.
Final Answer:
The readonly modifier should come before the property name: { readonly [P in keyof T]: T[P] } -> Option B
Quick Check:
readonly before [P in keyof T] fixes syntax [OK]
Hint: Place readonly before the mapped key, not after the type [OK]
Common Mistakes:
Putting readonly after the property type
Confusing property name and type order
Ignoring mapped type syntax rules
5. You want to create a mapped type that converts all properties of a type T to strings, regardless of their original type. Which mapped type correctly achieves this?
hard
A. type Stringify<T> = { [P in keyof T]: string }
B. type Stringify<T> = { [P in keyof T]: T[P] extends string ? string : never }
C. type Stringify<T> = { [P in keyof T]: T[P] & string }
D. type Stringify<T> = { [P in keyof T]: keyof string }
Solution
Step 1: Understand the goal
We want all properties to become type string, ignoring original types.
Step 2: Analyze each option
type Stringify<T> = { [P in keyof T]: string } sets every property to string directly. type Stringify<T> = { [P in keyof T]: T[P] extends string ? string : never } uses conditional types but returns never for non-string types, which is incorrect. type Stringify<T> = { [P in keyof T]: T[P] & string } intersects with string, which does not convert types. type Stringify<T> = { [P in keyof T]: keyof string } uses keyof string which is invalid.
Final Answer:
type Stringify<T> = { [P in keyof T]: string } -> Option A
Quick Check:
Assign string directly to all properties [OK]
Hint: Assign string type directly to all keys in mapped type [OK]
Common Mistakes:
Using conditional types incorrectly
Trying to intersect types instead of replacing
Misusing keyof operator on primitive types
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.