Inferring types with infer keyword in Typescript - Time & Space Complexity
We want to understand how the time it takes to infer types using the infer keyword changes as the input type grows.
Specifically, how does the process scale when working with different type structures?
Analyze the time complexity of the following TypeScript type inference using infer.
type ElementType<T> = T extends (infer U)[] ? U : T;
// Example usage:
type A = ElementType<string[]>; // string
type B = ElementType<number>; // number
This code extracts the element type from an array type or returns the type itself if it is not an array.
Look for repeated checks or pattern matches in the type inference.
- Primary operation: Conditional type check with
inferto extract inner type. - How many times: Once per type checked; no loops or recursion here.
The inference happens once per type checked, so the time does not grow with the size of the array type.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 1 check |
| 100 | 1 check |
| 1000 | 1 check |
Pattern observation: The operation count stays the same regardless of input size.
Time Complexity: O(1)
This means the inference takes the same amount of time no matter how big the input type is.
[X] Wrong: "The infer keyword loops over all elements of the array type to find the inner type."
[OK] Correct: The infer keyword works by pattern matching the type structure once, not by iterating over elements.
Understanding how TypeScript infers types quickly helps you write better type-safe code and explain your reasoning clearly in interviews.
What if we changed the type to infer nested arrays like number[][]? How would the time complexity change?
Practice
infer keyword do in TypeScript conditional types?Solution
Step 1: Understand the role of
Theinferinferkeyword is used inside conditional types to let TypeScript guess a type variable from a given type.Step 2: Identify what
It extracts parts of complex types, like the return type of a function or the element type of an array.inferextractsFinal Answer:
It allows TypeScript to guess and extract a type inside a conditional type. -> Option BQuick Check:
inferextracts types = A [OK]
- Thinking infer declares variables in functions
- Confusing infer with interface creation
- Assuming infer imports types
F using infer?Solution
Step 1: Analyze the conditional type structure
The correct syntax usesF extends (...args: any[]) => infer Rto extract the return typeR.Step 2: Check each option for correct infer usage
type ReturnType<F> = F extends (...args: any[]) => infer R ? R : never; correctly placesinfer Rafter the arrow function parameters and before the return type.Final Answer:
type ReturnType<F> = F extends (...args: any[]) => infer R ? R : never; -> Option AQuick Check:
Correct infer syntax for return type = A [OK]
infer R right after function args in extends [OK]- Placing infer outside the extends clause
- Using infer on the wrong part of the function type
- Confusing parameter inference with return type inference
ElementType?
type ElementType<T> = T extends (infer U)[] ? U : T; type Result = ElementType;
Solution
Step 1: Understand the conditional type with infer
The type checks ifTextends an array of some typeU. If yes, it extractsU.Step 2: Apply the type to
Sincestring[]string[]extends(infer U)[],Uisstring. So,ElementType<string[]>isstring.Final Answer:
string -> Option AQuick Check:
Extracted element type = string [OK]
- Confusing the whole array type with element type
- Assuming infer returns the original type
- Ignoring the conditional fallback
type ArgType<T> = T extends (arg: infer A) => void ? A : never; type Test = ArgType<() => number>;
Solution
Step 1: Analyze the function type used
The function type() => numberhas no arguments.Step 2: Understand infer behavior with no matching argument
The conditional type tries to infer argumentA, but since there is no argument, the condition fails and returnsnever.Final Answer:
The function type has no arguments, so infer fails and returns never. -> Option CQuick Check:
Infer fails with no matching argument = C [OK]
- Assuming infer always succeeds
- Misplacing infer keyword syntax
- Confusing argument and return type inference
Flatten<T> that extracts the element type from nested arrays using infer. For example, Flatten<number[][]> should be number[]. Which of the following correctly implements this?Solution
Step 1: Understand the goal of Flatten
We want to recursively unwrap nested arrays until we reach a non-array element, then wrap it back as a single array.Step 2: Analyze type Flatten<T> = T extends (infer U)[] ? U extends any[] ? Flatten<U> : U[] : T;'s recursive conditional
type Flatten<T> = T extends (infer U)[] ? U extends any[] ? Flatten<U> : U[] : T; checks ifTis an array ofU. IfUis itself an array, it recursively callsFlatten<U>. Otherwise, it returnsU[]. This matches the requirement.Final Answer:
type Flatten<T> = T extends (infer U)[] ? U extends any[] ? Flatten<U> : U[] : T; -> Option DQuick Check:
Recursive infer for nested arrays = B [OK]
- Not handling recursion for nested arrays
- Returning wrong type shape after unwrapping
- Misplacing infer or conditional checks
Ready to prove it?
Pass the test and this pattern moves unknown
