Start learning free

LESSON 118 OF 348 · WHILE LOOPS & FOR LOOPS

Infinite while Loops in TypeScript and How to Fix Them

Lesson Read the full explanation

Loops bring great power but also great responsability. The biggest danger when using loops is writing an infinite loop.

An infinite loop is a loop that never terminates. For example, if we forget to increment i in our previous example:

let i = 1;
while(i < 5) {
	console.log(i);
	// i++; => forgot this
}

This program will never terminate as i will always have value 1 and thus the condition i < 5 will always be satisfied.

The program would basically print 1 forever never exiting the while loop.


Pro Tip:

As programmers, we want to make sure we never write infinite loops as they make our program run forever and completely unusable.


Assignment
Follow the Coding Tutorial and practice with infinite while loops!


Hint
Look at the examples above if you get stuck.


STEP 1 OF 1
    Ctrl + Enter to check

    TYPESCRIPT · WHILE LOOPS & FOR LOOPS

    Infinite While Loops in TypeScript, explained

    What an infinite loop is

    A while loop runs as long as its condition is true. If nothing inside the loop can ever make the condition false, the loop never ends. That is an infinite loop. The program keeps running, usually printing the same values over and over, and nothing after the loop is ever reached.

    The simplest cause is a forgotten update:

    let i = 1;
    while (i < 5) {
        console.log(i);
        // i++ is missing
    }
    

    Here i is always 1, so i < 5 is always true, and the program prints 1 without end. Compiling the code gives no complaint. The types are all correct, and nothing in the language checks that a loop can finish. When you test code like this in a terminal, you stop it with Ctrl+C.

    A subtler cause: a condition that can be skipped over

    The exercise starts with a loop that should print the odd numbers from 15 down to 1 and then stop. It prints 15, 13, 11 and so on, but it does not stop after 1:

    let counter: number = 15;
    while (counter != 0) {
        console.log(counter);
        counter -= 2;
    }
    

    The update is fine and the direction is fine. The problem is the condition. The loop is waiting for counter to be exactly 0, but the counter takes the values 15, 13, 11, 9, 7, 5, 3, 1, -1, -3, and so on. Starting from an odd number and subtracting 2 never gives an even number, so 0 never appears. After 1 comes -1, which steps over 0, and counter != 0 remains true for every value from then on.

    Following the values

    Tracing the variable by hand is the best way to find this kind of bug. Write down the value of counter at the top of each pass and look at the last few rows:

    • Pass with counter equal to 3: the condition is true, so 3 is printed and the counter becomes 1.
    • Pass with counter equal to 1: the condition is true, so 1 is printed and the counter becomes -1.
    • Pass with counter equal to -1: the condition is still true, because -1 is not 0. The loop carries on forever.

    The fix

    Replace the exact-match test with a range test. The loop should continue while the counter is still positive:

    let counter: number = 15;
    while (counter > 0) {
        console.log(counter);
        counter -= 2;
    }
    

    This prints 15, 13, 11, 9, 7, 5, 3 and 1. After 1 is printed, the counter is -1, the condition -1 > 0 is false, and the loop ends. The range test works even though the counter jumps over 0, because it only asks which side of 0 the counter is on.

    Why a range check is safer than != or ===

    A test for one exact value is fragile when the step is larger than 1. It only works if the counter lands precisely on that value, so a change to the start or the step can break it. With an odd start and a step of 2, an exact test for an even number can never succeed. Comparisons such as >, >=, < and <= stay correct for any step, because once the counter passes the limit the condition turns false and stays false.

    The same applies to decimal numbers. TypeScript numbers are binary floating-point values, so repeated additions of 0.1 do not land exactly on 1. A loop that waits for x != 1 while adding 0.1 each time would run past 1 and never stop. Use a range check there as well.

    Checklist for avoiding infinite loops

    1. Does the loop body change something the condition depends on? If the variable in the condition never changes, the loop cannot end.
    2. Does the change move in the right direction? Counting down toward a lower limit needs -= or --, and counting up toward an upper limit needs += or ++.
    3. Can the counter skip the stop value? If so, use >, >=, < or <= instead of an exact comparison.
    4. Trace the last few passes by hand. Check which value of the counter makes the condition false for the first time.

    Common mistakes

    • Fixing the symptom. Changing the start to an even number would stop this particular loop at 0, but it would print different numbers from the ones the task wants. Fix the condition and keep the start.
    • Using >= 0. For this loop it happens to give the same output, since the counter never equals 0, but > 0 says exactly what the task means: keep going while the number is positive.
    • Adding a break inside the loop. It can end the loop, but the cleaner fix is a correct condition, so a reader sees the stopping rule in one place.

    Key takeaways

    • An infinite loop is a loop whose condition never becomes false.
    • The update may be missing, may go the wrong way, or may jump over the exact value the condition waits for.
    • Prefer comparisons that test a range over tests for one exact value.
    • Tracing the variable through the last few passes shows quickly why a loop does not stop.
    Keep going with TypeScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free