Conditional types for overload replacement in Typescript - Time & Space Complexity
We want to understand how using conditional types instead of overloads affects the time it takes for TypeScript to process code.
Specifically, how does the complexity grow as the input types or conditions increase?
Analyze the time complexity of the following TypeScript conditional type used to replace function overloads.
type Result = T extends string ? number : boolean;
function example(arg: T): Result {
if (typeof arg === 'string') {
return arg.length as Result;
} else {
return (arg !== null) as Result;
}
}
This code uses a conditional type to decide the return type based on the input type instead of multiple overloads.
Look at what TypeScript does when checking this code.
- Primary operation: TypeScript evaluates the conditional type
Result<T>for each usage. - How many times: Once per unique type
Tencountered during compilation.
As the number of different input types T grows, TypeScript must evaluate the conditional type for each.
| Input Types Count (n) | Approx. Evaluations |
|---|---|
| 10 | 10 |
| 100 | 100 |
| 1000 | 1000 |
Pattern observation: The work grows linearly with the number of unique input types.
Time Complexity: O(n)
This means the time to process grows directly in proportion to how many different input types are used.
[X] Wrong: "Conditional types run once and don't add to compile time as inputs grow."
[OK] Correct: Each unique input type triggers a new evaluation, so more inputs mean more work.
Understanding how conditional types scale helps you write efficient type code and shows you think about performance beyond runtime.
What if we replaced the conditional type with multiple overloads? How would the time complexity change?
Practice
Solution
Step 1: Understand conditional types
Conditional types allow choosing a type based on a condition, like an if-else for types.Step 2: Relate to overload replacement
They replace multiple function overloads by selecting the correct return type based on input types.Final Answer:
To select a type based on a condition, replacing multiple overloads with one type -> Option CQuick Check:
Conditional types = overload replacement [OK]
- Confusing conditional types with runtime checks
- Thinking conditional types create multiple functions
- Believing conditional types convert types to strings
Solution
Step 1: Recall conditional type syntax
Conditional types use the syntax:type Result = T extends U ? X : Y;Step 2: Compare options
type Result = T extends U ? X : Y; matches the correct syntax. Options A, C, and D use invalid or incorrect syntax.Final Answer:
type Result = T extends U ? X : Y; -> Option DQuick Check:
Conditional type syntax = type Result = T extends U ? X : Y; [OK]
- Using if-else syntax inside type definitions
- Confusing ternary operator with conditional types
- Using '==' instead of 'extends' keyword
result?
type IsString<T> = T extends string ? "Yes" : "No"; let result: IsString<number>;
Solution
Step 1: Analyze the conditional type
The typeIsString<T>returns "Yes" ifTextends string, else "No".Step 2: Apply to
Sincenumbernumberdoes not extendstring, the type is "No".Final Answer:
"No" -> Option BQuick Check:
number extends string? No [OK]
- Assuming number extends string
- Confusing type with value
- Ignoring the conditional type logic
type Check<T> = T extends number ? "Num" : "NotNum";
function test<T>(value: T): Check<T> {
if (typeof value === "number") {
return "Num";
} else {
return "NotNum";
}
}Solution
Step 1: Understand conditional types vs runtime
Conditional types exist only at compile time and cannot be used to enforce runtime return types directly.Step 2: Check function return
The function tries to return a value matchingCheck<T>, but TypeScript cannot guarantee this at runtime, causing a type error.Final Answer:
Function return type does not match because conditional types are not resolved at runtime -> Option AQuick Check:
Conditional types = compile-time only [OK]
- Thinking conditional types work at runtime
- Misusing conditional type syntax
- Changing parameter type unnecessarily
function format(value: string): string;
function format(value: number): string;
function format(value: any): string {
return value.toString();
}
Choose the best conditional type signature to replace these overloads.Solution
Step 1: Understand original overloads
Both string and number inputs return a string output.Step 2: Choose conditional type matching overloads
function format<T>(value: T): T extends string | number ? string : never; restrictsTto string or number and returns string for those, else never (disallowed).Step 3: Check other options
function format<T extends string | number>(value: T): T extends string ? string : string;'s return type is redundant; function format<T>(value: T): string; allows any type; function format<T>(value: T): T extends string ? string : number; returns number incorrectly.Final Answer:
function format<T>(value: T): T extends string | number ? string : never; -> Option AQuick Check:
Conditional type restricts inputs and return string [OK]
- Allowing any input type without restriction
- Returning wrong types for some inputs
- Ignoring the need to exclude unsupported types
Ready to prove it?
Pass the test and this pattern moves unknown
