Ответ вслух Middle Задачи на типы обновлено

DeepReadonly вслух

Вопрос

Напишите и проговорите DeepReadonly<T>, который делает readonly все поля на любой глубине.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Встроенный Readonly действует только на верхний уровень, поэтому нужна рекурсия. Пишу mapped-тип: type DeepReadonly<T = { readonly [K in keyof T]: T[K] extends Function ?

Что должно прозвучать в ответе

  • Mapped-тип по `keyof T` с модификатором `readonly`

  • Рекурсивный вызов для значений-объектов: `T[K] extends object ? DeepReadonly<T[K]> : T[K]`

  • Функции не нужно разбирать, их стоит оставить как есть: проверка `T[K] extends Function`

  • Массивы: гомоморфный mapped-тип превратит их в readonly-массивы

  • Проверка на примере с вложенным объектом, массивом и методом

Что могут спросить следом

  • Что станет с Date и Map?
  • Как сделать обратную операцию DeepMutable?
  • Почему не хватает встроенного Readonly?

Разбор

Встроенный Readonly действует только на верхний уровень, поэтому нужна рекурсия. Пишу mapped-тип: type DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends Function ? T[K] : T[K] extends object ? DeepReadonly<T[K]> : T[K] }. Для каждого поля добавляю readonly. Если значение функция, оставляю как есть, иначе метод превратился бы в объект без сигнатуры вызова. Если значение объект, рекурсивно применяю тот же тип. Массивы и кортежи обрабатываются корректно: гомоморфный mapped-тип над массивом даёт readonly-массив. Проверяю на примере с вложенным объектом, массивом объектов и методом. Отдельно оговариваю Date, Map и Set: они станут «объектами из полей», и методы вроде set останутся вызываемыми, для них нужна отдельная ветка с ReadonlyMap.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.