Control flow analysis behavior in Typescript - Time & Space Complexity
We want to understand how the program's steps grow as the input changes when using control flow analysis.
How does the program decide which parts to run and how often?
Analyze the time complexity of the following code snippet.
function processItems(items: number[]): number {
let total = 0;
for (const item of items) {
if (item > 0) {
total += item;
} else {
break;
}
}
return total;
}
This code sums positive numbers in an array until it finds a non-positive number, then stops.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through the array items one by one.
- How many times: Up to the first non-positive number or the whole array length.
Execution grows with the number of positive items before a non-positive one or the full array length if none found.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 10 checks and additions |
| 100 | Up to 100 checks and additions |
| 1000 | Up to 1000 checks and additions |
Pattern observation: The work grows roughly in a straight line with input size until a stopping point.
Time Complexity: O(n)
This means the program's steps grow directly with the number of items it checks.
[X] Wrong: "The loop always runs for the entire array length no matter what."
[OK] Correct: The loop stops early when it finds a non-positive number, so it may run less than the full length.
Understanding how control flow affects steps helps you explain how your code behaves with different inputs clearly and confidently.
"What if we changed the break to continue? How would the time complexity change?"
Practice
What does TypeScript's control flow analysis primarily help with?
Solution
Step 1: Understand control flow analysis purpose
Control flow analysis tracks how variables change types through different code paths.Step 2: Identify its main benefit
This helps TypeScript catch type errors before running the program.Final Answer:
Tracking variable types through code paths to catch errors early -> Option BQuick Check:
Control flow analysis = type tracking [OK]
- Confusing control flow analysis with code execution speed
- Thinking it fixes syntax errors automatically
- Believing it compiles TypeScript to JavaScript
Which of the following TypeScript code snippets correctly narrows a variable's type using control flow analysis?
let value: string | number = 5;
if (typeof value === 'string') {
console.log(value.toUpperCase());
}Solution
Step 1: Check the type guard condition
The conditiontypeof value === 'string'narrowsvalueto string inside the if block.Step 2: Confirm safe method call
Sincevalueis string here, callingtoUpperCase()is safe and valid.Final Answer:
The code is correct and safe to calltoUpperCase()inside the if block -> Option DQuick Check:
Type guard narrows type = safe method call [OK]
- Calling string methods without type narrowing
- Confusing typeof with instanceof for primitives
- Assuming type assertions are always needed
What will be the output of this TypeScript code?
function checkValue(x: string | number) {
if (typeof x === 'number') {
return x.toFixed(2);
} else {
return x.toUpperCase();
}
}
console.log(checkValue('hello'));
console.log(checkValue(3.14159));Solution
Step 1: Analyze the first call with string
For'hello', the else block runs, returning'HELLO'aftertoUpperCase().Step 2: Analyze the second call with number
For3.14159, the if block runs, returning'3.14'aftertoFixed(2).Final Answer:
"HELLO" and "3.14" -> Option CQuick Check:
Type guards produce correct string outputs [OK]
- Assuming toFixed returns a number, not string
- Ignoring type narrowing in if-else
- Mixing up output formatting
Identify the error in this TypeScript code related to control flow analysis:
function process(input: string | null) {
if (input) {
console.log(input.toLowerCase());
} else {
console.log(input.toLowerCase());
}
}Solution
Step 1: Check the else block usage
In the else block,inputisnull, so callingtoLowerCase()causes a runtime error.Step 2: Understand control flow limitation
Control flow analysis narrowsinputin the if block but not in else, so unsafe call happens.Final Answer:
CallingtoLowerCase()onnullin the else block causes a runtime error -> Option AQuick Check:
Null check needed before method call [OK]
- Assuming if(input) excludes null everywhere
- Expecting TypeScript to fix runtime errors
- Using loose null checks without safe calls
Given this TypeScript code, what is the best way to fix the control flow analysis issue to avoid errors?
function formatInput(input: string | number | null) {
if (typeof input === 'string') {
return input.trim();
} else if (typeof input === 'number') {
return input.toFixed(1);
}
return input.trim();
}Solution
Step 1: Identify the problem with last return
The lastreturn input.trim()runs wheninputisnull, causing an error.Step 2: Fix by adding null check
Adding a check likeif (input !== null)before callingtrim()prevents errors.Final Answer:
Add a null check before the lastreturnto avoid callingtrim()on null -> Option AQuick Check:
Null checks prevent unsafe method calls [OK]
- Ignoring null possibility in union types
- Assuming last return is unreachable
- Using type assertions without safety
Ready to prove it?
Pass the test and this pattern moves unknown
