Тип може посилатися сам на себе - так описують деревоподібні структури.
Значення JSON:
type Json =
| string
| number
| boolean
| null
| Json[]
| { [key: string]: Json };
const data: Json = { users: [{ id: 1, tags: ['php'], manager: null }] };
const bad: Json = { createdAt: new Date() }; // помилка: Date не є Json
Корисно для функцій, що приймають «будь-який серіалізовний об'єкт» (кеш, localStorage, postMessage) - тоді Date, Map, функції не пройдуть.
Глибокі утиліти:
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
type Settings = { theme: { colors: { primary: string; accent: string } } };
const patch: DeepPartial<Settings> = { theme: { colors: { accent: '#f00' } } };
Деревоподібні дані:
type Category = { id: number; name: string; children: Category[] };
type MenuItem = { label: string; href?: string; items?: MenuItem[] };
Обмеження й пастки:
- функції, дати,
Map-T[K] extends objectістинне і для них.DeepReadonly<Date>спробує обійти методиDate. Їх виключають окремими гілками:T[K] extends Function | Date | Map<any, any> ? T[K] : ...; - масиви в mapped types обробляються як масиви (гомоморфні типи), але кортежі й readonly-масиви інколи потребують окремої обробки;
- глибина інстанціювання: компілятор обмежує глибину рекурсії. Для дуже глибоких чи «вибухових» типів з'являється «Type instantiation is excessively deep and possibly infinite». Хвостова рекурсія в умовних типах (TS 4.5+) дозволяє до ~1000 рівнів, а звичайна обривається значно раніше - на кількох десятках;
- продуктивність: рекурсивні типи над великими структурами (типи відповідей API на сотні полів) помітно сповільнюють редактор. Повільна підказка в IDE - ознака, що тип надто «розумний»;
- рекурсивні псевдоніми (
type Json = ... Json[]) підтримуються з TS 3.7; раніше доводилося обходити через інтерфейси.
Порада: рекурсивні типи - для справді рекурсивних даних. Якщо рекурсія потрібна лише для «розумної» перевірки, варто зважити, чи вартий виграш у типах повільнішого редактора й незрозумілих повідомлень про помилки.