Type-safe API response handling in Typescript - Time & Space Complexity
When handling API responses in TypeScript, we often check and process data safely using types. Understanding how the time needed grows as the response size grows helps us write better code.
We want to know: how does the time to handle the response change when the response has more items?
Analyze the time complexity of the following code snippet.
interface ApiResponse {
data: { id: number; value: string }[];
}
function processResponse(response: ApiResponse) {
return response.data.map(item => {
if (typeof item.id === 'number' && typeof item.value === 'string') {
return item.value.toUpperCase();
}
return null;
});
}
This code takes an API response with a list of items, checks each item's type, and converts the value to uppercase if valid.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
mapmethod loops over each item in thedataarray. - How many times: Once for every item in the response array.
Explain the growth pattern intuitively.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks and conversions |
| 100 | About 100 checks and conversions |
| 1000 | About 1000 checks and conversions |
Pattern observation: The work grows directly with the number of items. Double the items, double the work.
Time Complexity: O(n)
This means the time to process the response grows in a straight line with the number of items.
[X] Wrong: "Type checks inside the loop don't affect time complexity much."
[OK] Correct: Even simple checks happen for every item, so they add up and affect total time as the list grows.
Understanding how your code scales with input size shows you can write efficient and reliable programs, a skill valued in many coding challenges and real projects.
"What if we replaced map with a nested loop over two arrays? How would the time complexity change?"
Practice
Solution
Step 1: Understand type safety purpose
Type-safe handling means defining what data should look like before using it.Step 2: Identify the benefit
This helps catch mistakes early, like missing or wrong data types, before running the program.Final Answer:
It helps catch errors early by defining expected data shapes. -> Option DQuick Check:
Type safety = Early error detection [OK]
- Thinking type safety improves API speed
- Believing it fixes bugs automatically
- Assuming it replaces testing
Solution
Step 1: Understand generic function syntax
Generic functions use <T> to represent a type parameter, allowing flexible typing.Step 2: Check return type for async fetch
Fetching data returns a Promise of type T, so the return type must be Promise<T>.Final Answer:
function fetchData<T>(url: string): Promise<T> { /* ... */ } -> Option BQuick Check:
Generic + Promise = function fetchData<T>(url: string): Promise<T> { /* ... */ } [OK]
- Returning T directly instead of Promise<T>
- Missing generic <T> in function definition
- Using Promise<any> loses type safety
interface User { id: number; name: string; }
async function getUser(): Promise<User> {
return { id: 1, name: "Alice" };
}
getUser().then(user => console.log(user.name));Solution
Step 1: Analyze the getUser function
It returns a Promise resolving to an object with id 1 and name "Alice".Step 2: Check the then callback
The callback logs user.name, which is "Alice".Final Answer:
"Alice" -> Option CQuick Check:
user.name = "Alice" [OK]
- Logging user instead of user.name
- Confusing id with name
- Expecting entire object printed
interface ApiResponse { success: boolean; data: string; }
async function fetchApi(): Promise<ApiResponse> {
const response = await fetch('https://api.example.com');
const json = await response.json();
return json;
}Solution
Step 1: Check how json is handled
json is returned directly without confirming it matches ApiResponse shape.Step 2: Understand type safety requirement
TypeScript needs either a type assertion or runtime validation to ensure json fits ApiResponse.Final Answer:
Missing type assertion or validation for json before returning. -> Option AQuick Check:
Validate json shape before return [OK]
- Assuming fetch json is automatically typed
- Ignoring need for runtime checks
- Misunderstanding async/await usage
Solution
Step 1: Define User interface including 'active' property
To filter by active status, the User type must include an 'active' boolean field.Step 2: Fetch data as Promise<User[]> and filter
Fetching with correct type ensures type safety; filtering users by active keeps the result accurate and typed.Final Answer:
Define interface User with 'active' boolean, fetch data as Promise<User[]>, then filter users by active before returning. -> Option AQuick Check:
Correct interface + typed fetch + filter = Define interface User with 'active' boolean, fetch data as Promise, then filter users by active before returning. [OK]
- Casting any to User[] without checks
- Filtering on missing properties in interface
- Returning unfiltered data losing requirements
Ready to prove it?
Pass the test and this pattern moves unknown
