Recursive Types

Types that call themselves.

TypeScript5 min readConcept 34 of 54

Infinite Nesting

Just like a function can call itself in JavaScript, a type can reference itself in TypeScript.

Recursive types are essential for modeling data structures that can be infinitely nested, like JSON objects, file directories, or linked lists.

The DeepPartial Problem

The built-in Partial<T> utility only makes the *top-level* properties of an object optional. If you have nested objects, their properties remain required.

By creating a DeepPartial<T> recursive type, you can traverse every nested level of an object and apply the ? modifier all the way down.

Syntax

typescript // Base case: If T is an object, map over it and call DeepPartial on its children. // Otherwise, just return T. type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]>; } : T; type User = { id: number; settings: { theme: string; notifications: boolean }; }; type A = DeepPartial<User>; // Both 'settings' AND 'theme'/'notifications' are now optional!

Try it

Watch the DeepPartial type recursively traverse a nested configuration object, applying the optional ? modifier to every level.

Recursive Traversal in progress...
type DeepPartial<T> =
Textendsobject? {
[K in keyof T]?:DeepPartial<T[K]>;
} :T;
Call Stack
Depth: 0
{
id?: number;
settings?: {
theme?: string;
};
}

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1Why does a recursive type like `DeepPartial<T>` need a conditional check (`T extends object`)?

Remember this

  • Recursive types reference themselves in their own definition.
  • They must have a base case (usually a conditional check) to terminate.
  • They are required for modeling infinite structures like JSON, Trees, or DeepPartial.
  • TypeScript has strict limits on recursion depth to protect the compiler.

Done with this concept?

Mark it complete to track your progress. No login needed.