Open In App

What are Recursive Types & Interfaces in TypeScript ?

Last Updated : 07 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In TypeScript, recursive types and interfaces are used to define types or interfaces that can refer to themselves in their definition. This is a powerful concept that allows you to describe complex, nested structures with a simple, elegant definition.

Recursive Interfaces

Recursive interfaces in TypeScript are used to define an interface that references itself within its definition. This is commonly used for hierarchical data structures, such as trees or linked lists, where each node might contain a reference to another node of the same type.

Syntax:

interface RecursiveInterface {
value: any;
next?: RecursiveInterface;
}

Example: Define a ListNode interface for a linked list, where each node has a value and an optional reference to the next node (next) of the same type. We then create two nodes and link them together.

Javascript




interface ListNode {
  value: number;
  next?: ListNode;
}
 
const node1: ListNode = { value: 1 };
const node2: ListNode = { value: 2 };
node1.next = node2;
 
console.log(node1);


Output

[LOG]: { 
"value": 1,
"next": {
"value": 2
}
}

Recursive Type Aliases

Type aliases can also be recursive in TypeScript. This allows for more flexible and complex type definitions compared to interfaces, as type aliases can involve unions, intersections, and other complex types.

Syntax:

type RecursiveType = {
value: any;
children?: RecursiveType[];
};

Example: Defining a tree using a recursive type alias for a tree structure where each node can have an arbitrary number of children. We create a simple tree with a root node, two child nodes, and one grandchild node to demonstrate the recursive structure.

Javascript




type TreeNode = {
  value: string,
  children?: TreeNode[],
};
 
const tree: TreeNode = {
  value: "root",
  children: [
    {
      value: "child1",
      children: [
        {
          value: "grandchild1",
        },
      ],
    },
    {
      value: "child2",
    },
  ],
};
 
console.log(tree);


Output

[LOG]: {  
"value": "root",
"children": [
{ "value": "child1", "children": [
{ "value": "grandchild1" }
]
},
{ "value": "child2" }
] }

Using Recursive Types with Generics

Recursive types and interfaces become even more powerful when combined with generics, enabling the definition of complex, self-referential structures that can contain various types of data.

Syntax:

interface RecursiveGenericInterface<T> {
value: T;
next?: RecursiveGenericInterface<T>;
}

Example: To demonstrate creating a linked list of numbers by using generic interface which allows for the creation of linked list nodes that can hold any type of data.

Javascript




interface GenericListNode<T> {
  value: T;
  next?: GenericListNode<T>;
}
 
const node1: GenericListNode<number> =
    { value: 123 };
const node2: GenericListNode<number> =
    { value: 456, next: node1 };
 
console.log(node2);


Output

[LOG]: {   "value": 456,   "next": {     "value": 123   } } 

Recursive Types for Function Definitions

Recursive types are not limited to data structures; they can also be used in function definitions to describe functions that return a value of their own type, enabling complex, self-referential algorithms.

Syntax:

type RecursiveFunction = () => RecursiveFunction;

Example: The recursiveFunction to demonstrates a simplistic conditional check to decide between ending the recursion (returning null) or continuing it by returning a reference to itself.

Javascript




type RecursiveFunction = () => RecursiveFunction | null;
 
const recursiveFunction: RecursiveFunction =
    (): RecursiveFunction | null => {
   
      // A condition that determines whether
    // to return another recursive call or null
  const stopCondition = true; // This should be based on actual logic
  if (stopCondition) {
    return null; // Base case: ends the recursion
  } else {
   
      // Recursive case: returns itself for further execution
    return recursiveFunction;
  }
};
 
console.log(recursiveFunction());


Output

[LOG] : null


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads