Microsoft/TypeScript

Homomorphic mapped types with arrays doesn't work well with recursive arrays

Open

#61,868 opened on Jun 14, 2025

View on GitHub
 (10 comments) (0 reactions) (0 assignees)TypeScript (48,455 stars) (6,726 forks)batch import
Domain: Mapped TypesHelp WantedPossible Improvement

Description

Acknowledgement

  • I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.

Comment

Consider this homomorphic mapped type:

type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> };

Now, consider its instantiation with a recursive type:

type StringNode = string | { node: StringNode };

type T1 = DeepReadonly<StringNode>;
//   ^? type T1 = string | DeepReadonly<{ node: StringNode; }>

const t1: T1 = { node: { node: 'A' } };

Everything works fine. Playground: https://tsplay.dev/wRDrQm.

However, if the type is instantiated with an array, I start getting "Type instantiation is excessively deep and possibly infinite" error.

type StringNode = string | StringNode[];

type T1 = DeepReadonly<StringNode>;
// errors

Updating the implementation to this makes the error go away, but this doesn't work with tuples.

type DeepReadonly<T> =
  T extends ReadonlyArray<infer V>
    ? ReadonlyArray<DeepReadonly<V>>
    : { readonly [P in keyof T]: DeepReadonly<T[P]> };

type StringNode = string | StringNode[];

type T1 = DeepReadonly<StringNode>;

const t1: T1 = [['foo']];
type StringNodeTuple = string | [StringNodeTuple];

type T2 = DeepReadonly<StringNode>;

const t2: T2 = [['foo', 'bar']]; // doesn't error

If the mapped type works with objects it should have worked with arrays as well. Is there something that I am missing?

Contributor guide