Deep Readonly
Завдання
Реалізувати тип DeepReadonly<T>
який робить властивості об’єкту незмінними
(рекурсивно!). Наприклад:
type X = {
x: {
a: 1;
b: "hi";
};
y: "hey";
};
type Expected = {
readonly x: {
readonly a: 1;
readonly b: "hi";
};
readonly y: "hey";
};
const todo: DeepReadonly<X>; // should be same as `Expected`
Розв’язок
Це завдання схоже з тим, що ми розв’язували в
Readonly<T>
. Відрізняється тільки тим, що тут потрібно
це робити рекурсивно.
Почнемо з класичної реалізації і зробимо Readonly<T>
:
type DeepReadonly<T> = { readonly [P in keyof T]: T[P] };
Але, як ви вже здогадалися, цей тип не зробить всі властивості незмінними, а
тільки ті, що знаходяться на першому рівні вкладеності. Причина в тому, що якщо
T[P]
це не примітив, а об’єкт, то його властивості залишаться неопрацьованими.
Тому, замінимо T[P]
на рекурсивний виклик DeepReadonly<T>
. І оскільки ми вже
почали використовувати рекурсію, не забуваємо про базовий випадок. Алгоритм
простий. Якщо, T[P]
- об’єкт, рухаємося в глибину й викликаємо DeepReadonly
,
в інакшому випадку — повертаємо T[P]
без змін.
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends Record<string, unknown>
? DeepReadonly<T[P]>
: T[P];
};
Коментарі