Closures in TypeScript

TypeScript supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it.

import { log } from "console";

// This function intSeq returns another function, which
// we define anonymously in the body of intSeq. The
// returned function closes over the variable i to
// form a closure.
function intSeq(): () => number {
    let i = 0;
    return function() {
        i++;
        return i;
    };
}

function main() {
    // We call intSeq, assigning the result (a function)
    // to nextInt. This function value captures its
    // own i value, which will be updated each time
    // we call nextInt.
    const nextInt = intSeq();

    // See the effect of the closure by calling nextInt
    // a few times.
    log(nextInt());
    log(nextInt());
    log(nextInt());

    // To confirm that the state is unique to that
    // particular function, create and test a new one.
    const newInts = intSeq();
    log(newInts());
}

main();

To run this TypeScript code, you would typically use the TypeScript compiler (tsc) to compile it to JavaScript, and then run the resulting JavaScript with Node.js. Here’s how you might do that:

$ tsc closures.ts
$ node closures.js
1
2
3
1

In TypeScript, closures work in a very similar way to many other languages. The intSeq function returns an anonymous function that has access to the i variable in its outer scope. Each time this returned function is called, it increments and returns the value of i.

The main function demonstrates how this closure works. It creates two separate instances of the counter (nextInt and newInts), showing that each maintains its own independent state.

The last feature of functions we’ll look at for now is recursion.