Higher-order function types in Typescript - Time & Space Complexity
We want to see how the time needed changes when using higher-order functions in TypeScript.
How does the program's work grow when the input gets bigger?
Analyze the time complexity of the following code snippet.
function applyToAll(arr: number[], fn: (x: number) => number): number[] {
return arr.map(fn);
}
const nums = [1, 2, 3, 4, 5];
const doubled = applyToAll(nums, x => x * 2);
This code applies a given function to each item in an array and returns a new array.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
mapmethod loops through each element of the array. - How many times: Once for every element in the input array.
As the array gets bigger, the function inside map runs more times.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 function calls |
| 100 | 100 function calls |
| 1000 | 1000 function calls |
Pattern observation: The work grows directly with the number of items.
Time Complexity: O(n)
This means the time needed grows in a straight line with the input size.
[X] Wrong: "Using a higher-order function like map makes the code slower by a lot."
[OK] Correct: The main work still depends on how many items you have, not on the function style. The overhead is small compared to looping through all items.
Understanding how higher-order functions affect time helps you explain your code clearly and shows you know how work grows with input size.
"What if the function passed to map itself contains a loop over the array? How would the time complexity change?"
Practice
Solution
Step 1: Understand function types
Function types describe the input and output of functions in TypeScript.Step 2: Define higher-order function types
Higher-order function types specifically involve functions that take other functions as parameters or return functions.Final Answer:
A function type that takes or returns another function -> Option AQuick Check:
Higher-order function = function takes/returns function [OK]
- Thinking higher-order means only returning numbers
- Confusing higher-order with no parameters
- Assuming it only works with strings
Solution
Step 1: Analyze the parameter type
The parameter is a function with no arguments returning a number, written as () => number.Step 2: Analyze the return type
The higher-order function returns void, so the full type is (fn: () => number) => void.Final Answer:
(fn: () => number) => void -> Option DQuick Check:
Parameter is function, return is void [OK]
- Missing parentheses around function parameter
- Writing arrow syntax incorrectly
- Using wrong parameter types
type Fn = (x: number) => number;
function applyTwice(f: Fn, value: number): number {
return f(f(value));
}
const double: Fn = x => x * 2;
console.log(applyTwice(double, 3));
Solution
Step 1: Understand applyTwice function
It applies function f twice: f(f(value)).Step 2: Calculate output with double function
double(3) = 6, then double(6) = 12, so result is 12.Final Answer:
12 -> Option AQuick Check:
applyTwice(double, 3) = 12 [OK]
- Calculating only one application of function
- Confusing multiplication with addition
- Expecting a syntax or runtime error
type Mapper = (fn: (x: number) => number) => number[];
const mapToArray: Mapper = fn => {
return fn.map(x => x * 2);
};
Solution
Step 1: Check type of fn parameter
fn is a function (x: number) => number, not an array.Step 2: Analyze usage of fn.map
Calling .map on fn is invalid because fn is not an array but a function.Final Answer:
fn is a function, but .map is called on it incorrectly -> Option BQuick Check:
Function cannot use .map method [OK]
- Assuming function can use array methods
- Misreading return type
- Ignoring parameter types
type Compose = <T, U, V>(f: (b: U) => V, g: (a: T) => U) => (a: T) => V;
Which implementation correctly matches this type?
Solution
Step 1: Understand Compose type
Compose takes two functions f and g, returns a function that applies g then f.Step 2: Check each implementation
const compose: Compose = (f, g) => a => f(g(a)); applies f(g(a)) which matches the type. Others do not follow the composition pattern.Final Answer:
const compose: Compose = (f, g) => a => f(g(a)); -> Option CQuick Check:
Compose = f(g(a)) [OK]
- Reversing function order
- Adding parameters incorrectly
- Using arithmetic instead of function calls
Ready to prove it?
Pass the test and this pattern moves unknown
