Why mapped types are needed in Typescript - Performance Analysis
We want to see how the time it takes to create new types grows when using mapped types in TypeScript.
How does the process scale as the number of properties increases?
Analyze the time complexity of the following code snippet.
type Options = {
width: number;
height: number;
color: string;
};
type ReadonlyOptions = {
readonly [K in keyof Options]: Options[K];
};
This code creates a new type by making all properties of an existing type readonly using a mapped type.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Iterating over each property key in the original type.
- How many times: Once for each property in the type (e.g., width, height, color).
As the number of properties grows, the time to create the mapped type grows proportionally.
| Input Size (number of properties) | Approx. Operations |
|---|---|
| 3 | 3 operations (one per property) |
| 10 | 10 operations |
| 100 | 100 operations |
Pattern observation: The work grows in a straight line with the number of properties.
Time Complexity: O(n)
This means the time to create the mapped type grows directly with the number of properties.
[X] Wrong: "Mapped types create all properties instantly, so time does not grow with more properties."
[OK] Correct: Each property must be processed one by one, so more properties mean more work.
Understanding how mapped types scale helps you explain how TypeScript handles type transformations efficiently.
"What if we nested mapped types inside each other? How would the time complexity change?"
Practice
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 AQuick Check:
Mapped types = transform all properties easily [OK]
- Confusing mapped types with functions or classes
- Thinking mapped types handle async code
- Believing mapped types define private members
T readonly?Solution
Step 1: Analyze mapped type syntax
The correct syntax uses[P in keyof T]to iterate over keys and appliesreadonlybefore the property name.Step 2: Identify errors in other options
type Readonly<T> = { [P in keyof T]: readonly T[P] } incorrectly placesreadonlyafter 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 DQuick Check:
Mapped type syntax = readonly before [P in keyof T] [OK]
- Placing readonly after the property type
- Using wrong iteration syntax like [P in T]
- Misordering readonly and the mapped key
OptionalUser?
type User = { id: number; name: string; };
type OptionalUser = { [P in keyof User]?: User[P] };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 CQuick Check:
Mapped type with ? = all properties optional [OK]
- Confusing optional properties with union types
- Thinking original type remains unchanged
- Assuming syntax error in mapped types
type ReadonlyUser<T> = { [P in keyof T] T[P] readonly }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 BQuick Check:
readonly before [P in keyof T] fixes syntax [OK]
- Putting readonly after the property type
- Confusing property name and type order
- Ignoring mapped type syntax rules
T to strings, regardless of their original type. Which mapped type correctly achieves this?Solution
Step 1: Understand the goal
We want all properties to become typestring, ignoring original types.Step 2: Analyze each option
type Stringify<T> = { [P in keyof T]: string } sets every property tostringdirectly. type Stringify<T> = { [P in keyof T]: T[P] extends string ? string : never } uses conditional types but returnsneverfor 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 } useskeyof stringwhich is invalid.Final Answer:
type Stringify<T> = { [P in keyof T]: string } -> Option AQuick Check:
Assign string directly to all properties [OK]
- Using conditional types incorrectly
- Trying to intersect types instead of replacing
- Misusing keyof operator on primitive types
Ready to prove it?
Pass the test and this pattern moves unknown
