Combining utility types in Typescript - Time & Space Complexity
When we combine utility types in TypeScript, we want to know how the time to create the new type grows as the input types get bigger.
We ask: How does the work to build the combined type change with input size?
Analyze the time complexity of the following code snippet.
type Person = { name: string; age: number };
type Contact = { email: string; phone: string };
type PersonContact = Person & Contact;
// PersonContact now has all properties from Person and Contact
This code combines two types into one using intersection, merging their properties.
Look for how many properties TypeScript processes when combining types.
- Primary operation: Merging properties from each input type.
- How many times: Once for each property in both types.
As the number of properties in each type grows, the work to combine them grows too.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 property merges |
| 100 | About 200 property merges |
| 1000 | About 2000 property merges |
Pattern observation: The work grows roughly by adding the properties from both types, so it grows linearly with the total number of properties.
Time Complexity: O(n)
This means the time to combine types grows in a straight line as the total number of properties increases.
[X] Wrong: "Combining two types takes constant time no matter their size."
[OK] Correct: Because TypeScript must look at each property to merge them, so more properties mean more work.
Understanding how utility types combine helps you reason about type operations and their cost, a useful skill when designing complex types in real projects.
"What if we combined three or more types instead of two? How would the time complexity change?"
Practice
Solution
Step 1: Understand Partial and Readonly
Partial<T>makes all properties optional, andReadonly<T>makes all properties readonly.Step 2: Combine utility types correctly
WrappingPartial<T>insideReadonly<>makes all optional properties readonly as well.Final Answer:
Readonly<Partial<T>> -> Option AQuick Check:
Readonly + Partial = Readonly<Partial<T>> [OK]
- Reversing the order of Partial and Readonly
- Using Pick or Omit instead of Partial/Readonly
- Assuming Pick makes properties optional
Solution
Step 1: Understand Omit and Readonly
Omit<T, 'a' | 'b'>removes properties 'a' and 'b' from T.Readonly<>makes all properties readonly.Step 2: Apply Readonly after Omit
ApplyingReadonlyto the result ofOmitmakes the remaining properties readonly.Final Answer:
Readonly<Omit<T, 'a' | 'b'>> -> Option CQuick Check:
Omit then Readonly = Readonly<Omit<T, 'a' | 'b'>> [OK]
- Applying Omit after Readonly (wrong order)
- Using Pick instead of Omit
- Forgetting to use quotes around property names
type T = { a: number; b: string; c: boolean; }, what is the resulting type of Partial<Pick<T, 'a' | 'c'>>?Solution
Step 1: Apply Pick to select properties
Pick<T, 'a' | 'c'>selects only properties 'a' and 'c' from T.Step 2: Apply Partial to make selected properties optional
Partial<>makes 'a' and 'c' optional, so the type becomes{ a?: number; c?: boolean; }.Final Answer:
{ a?: number; c?: boolean; } -> Option AQuick Check:
Partial + Pick = optional picked props [OK]
- Including property 'b' which was not picked
- Forgetting Partial makes properties optional
- Assuming Partial affects all original properties
type U = Partial<Readonly<Omit<T, 'x'>>>Solution
Step 1: Analyze the order of utility types
The type appliesOmitfirst, removing property 'x', thenReadonlyto make remaining props readonly, thenPartialto make them optional.Step 2: Check if this order is valid
This order is valid and results in optional readonly properties except 'x' which is omitted.Final Answer:
No error; the type combination is valid -> Option BQuick Check:
Omit -> Readonly -> Partial is valid [OK]
- Thinking Partial cannot follow Readonly
- Assuming Omit must be last
- Confusing order of utility types
T that has only properties 'id' and 'name' readonly, and all other properties optional. Which combination achieves this?Solution
Step 1: Make 'id' and 'name' readonly
UseReadonly<Pick<T, 'id' | 'name'>>to select and make these properties readonly.Step 2: Make all other properties optional
UsePartial<Omit<T, 'id' | 'name'>>to make the rest optional.Step 3: Combine with intersection (&)
Use intersection&to merge both types into one.Final Answer:
Readonly<Pick<T, 'id' | 'name'>> & Partial<Omit<T, 'id' | 'name'>> -> Option DQuick Check:
Readonly Pick & Partial Omit = desired type [OK]
- Using logical AND (&&) instead of intersection (&)
- Applying Partial to readonly properties
- Omitting intersection operator
Ready to prove it?
Pass the test and this pattern moves unknown
