Why type narrowing is needed in Typescript - Performance Analysis
When we write code that checks types, the time it takes depends on how many checks happen.
We want to see how type narrowing affects the number of operations as input grows.
Analyze the time complexity of the following code snippet.
function process(value: string | number | boolean) {
if (typeof value === 'string') {
return value.toUpperCase();
} else if (typeof value === 'number') {
return value.toFixed(2);
} else {
return value ? 'Yes' : 'No';
}
}
This code checks the type of value and runs different code based on the narrowed type.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The type checks using
typeofhappen once per call. - How many times: Each call does a fixed number of checks (up to 2), no loops or recursion.
Explain the growth pattern intuitively.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 2 type checks |
| 100 | Up to 2 type checks |
| 1000 | Up to 2 type checks |
Pattern observation: The number of operations is constant (up to 2 checks), independent of input size.
Time Complexity: O(1)
This means the time to run stays constant as the input size grows.
[X] Wrong: "Type narrowing adds extra loops or slows down the program a lot."
[OK] Correct: Type narrowing just checks types once per input and helps the program run the right code, so it does not add loops or big delays.
Understanding how type narrowing affects performance helps you write clear and efficient code, a skill that shows you know how to balance safety and speed.
"What if the type checks were inside a loop over an array of values? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of type narrowing
Type narrowing helps TypeScript know the exact type of a variable at a certain point in code.Step 2: Recognize the benefit for code safety
Knowing the exact type allows TypeScript to check for errors and prevent bugs before running the code.Final Answer:
To tell TypeScript the exact type so it can check code safety -> Option AQuick Check:
Type narrowing = safer code [OK]
- Thinking it speeds up runtime
- Believing it allows dynamic type changes
- Assuming it removes need for type annotations
Solution
Step 1: Identify type narrowing syntax
Usingtypeofchecks liketypeof value === 'string'narrows the type inside the block.Step 2: Check other options for correctness
value = 'string' as number; forces wrong type withas, let value: any = 5; value = 'hello'; usesanywithout narrowing, function test(value: number | string) { return value; } does not narrow inside function.Final Answer:
if (typeof value === 'string') { /* value is string here */ } -> Option DQuick Check:
typeof check narrows type [OK]
- Using 'as' to force wrong types
- Not using any type checks
- Confusing type assertion with narrowing
function printLength(x: string | number) {
if (typeof x === 'string') {
return x.length;
} else {
return x.toFixed(2);
}
}
console.log(printLength('hello'));
console.log(printLength(3.14159));Solution
Step 1: Analyze the type narrowing in the function
Theifchecks ifxis a string, then returns its length (5 for 'hello'). Else, it treatsxas number and callstoFixed(2).Step 2: Evaluate the outputs for given inputs
For 'hello', output is 5. For 3.14159,toFixed(2)returns '3.14'.Final Answer:
5 and 3.14 -> Option CQuick Check:
Type narrowing enables correct method calls [OK]
- Expecting full decimal for number output
- Assuming length works on number
- Ignoring type narrowing effect
function process(value: string | number) {
console.log(value.length);
}Solution
Step 1: Understand the union type usage
The parametervaluecan be string or number, butlengthexists only on string.Step 2: Identify why narrowing is needed
Without checking type, accessinglengthon number causes error. Type narrowing is needed to safely accesslength.Final Answer:
Error: number type has no 'length' property, need narrowing -> Option BQuick Check:
Accessing properties needs type narrowing [OK]
- Ignoring union types
- Assuming all types have same properties
- Not using if or typeof checks
string | number | null. You want to safely return the string length or number fixed to 1 decimal, or 0 if null. Which code correctly uses type narrowing?Solution
Step 1: Check handling of null
function format(x: string | number | null) { if (x === null) return 0; if (typeof x === 'string') return x.length; return x.toFixed(1); } explicitly returns 0 ifxis null, which is correct.Step 2: Verify type narrowing for string and number
function format(x: string | number | null) { if (x === null) return 0; if (typeof x === 'string') return x.length; return x.toFixed(1); } usestypeofto check string and number separately, calling correct methods safely.Step 3: Identify errors in other options
function format(x: string | number | null) { if (x) return x.length || x.toFixed(1); return 0; } incorrectly usesx.length || x.toFixed(1)without narrowing; function format(x: string | number | null) { return x.length ?? x.toFixed(1) ?? 0; } uses nullish coalescing incorrectly; function format(x: string | number | null) { if (typeof x === 'number') return x.length; else if (typeof x === 'string') return x.toFixed(1); else return 0; } swaps methods for types.Final Answer:
function format(x: string | number | null) { if (x === null) return 0; if (typeof x === 'string') return x.length; return x.toFixed(1); } -> Option AQuick Check:
Explicit checks safely narrow types [OK]
- Not checking null before accessing properties
- Mixing up string and number methods
- Using || or ?? without narrowing
Ready to prove it?
Pass the test and this pattern moves unknown
