Recursive functions in TypeScript

Josh Sherman
4 min read
Software Development JavaScript TypeScript

In working with the Slate framework for building rich text editors recently, I found myself faced with a scenario where I needed to loop through the editor’s value.

The value that comes out the editor is an array of objects that is nestable, I assume infinitely, by way of the children property.

Because I wasn’t entirely sure if the data was going to be infinitely nestable or not, I figured the best approach would be to write a recursive function to loop through and travel through the hierarchy.

I’m not going to get into the thick of the details as to why I was doing this as I’m saving that for another Slate specific post. I did realize that it had actually been a while since I had written a recursive function, and thought it would make for a good blog topic.

Turns out the only times I’ve written about recursiveness, it was in the context of traversing a directory structure and was limited to shell scripting and not in any of the web languages that I sling code in.

For those that may not be away, a recursive function is a function that calls upon itself. If you’re not careful, a poorly written self-referential function like this can go on indefinitely and create an infinite loop.

An easy example of a recursive function would be something that takes a nested array of objects like I mentioned above, and perhaps tallies up some values to get a grand total.

Such an value would would look something like this:

interface NestedObject {
  name: string;
  value: number;
  children?: NestedObject[];
}

const nestedObjects: NestedObject[] = [
  {
    name: 'First Parent',
    value: 100,
    children: [
      {
        name: 'First Child',
        value: 110,
      },
      {
        name: 'Second Child',
        value: 120,
        children: [
          {
            name: 'First Grandchild',
            value: 121,
          },
          {
            name: 'Second Grandchild',
            value: 122,
          },
        ],
      },
    ],
  },
  {
    name: 'Second Parent',
    value: 200,
    children: [
      {
        name: 'First Child',
        value: 210,
      },
      {
        name: 'Second Child',
        value: 220,
      },
      {
        name: 'Third Child',
        value: 230,
        children: [
          {
            name: 'First Grandchild',
            value: 231,
          },
        ],
      },
    ],
  },
];

For the sake of example, I only went three levels deep, but you could nest things as far as you’d like or need to.

Next up, we need to write a function that will take our nested array of objects as a parameter, loop through it, and if there are any children, repeat the process.

For this, I opted to use reduce as it provides an accumulator variable that we can keep adding values to:

const totalValues = (nestedObjects: NestedObject[]) => {
  return nestedObjects.reduce(
    (totalValue, nestedObject: NestedObject): number => {
      // Add the current object's value
      totalValue += nestedObject.value;

      // If we have children, let's add their values too
      if (nestedObject.children) {
        totalValue += totalValues(nestedObject.children);
      }

      // Return the new total
      return totalValue;
    },
    0,
  );
};

And to finish things off, we can call our method and dump out some information to the console. I included a poor man’s unit test to ensure we received the value we had expected to:

const totalValue = totalValues(nestedObjects);

console.log('Total value:', totalValue);
console.log('Value is correct:', totalValue === 1664);

Not much to it, and extremely powerful when dealing with data that could come in with varying levels of nesting!

Obviously, you could use this same code in vanilla JavaScript if you omit the typings :)

Join the Conversation

Good stuff? Want more?

Weekly emails about technology, development, and sometimes sauerkraut.

100% Fresh, Grade A Content, Never Spam.