Код Senior Утилитарные типы обновлено

Мини-zod: тип из схемы через mapped-тип

Условие

Напиши валидатор по схеме, тип результата которого выводится из самой схемы:

  • схема это объект поле → 'string' | 'number' | 'boolean' | 'string?' | 'number?' | 'boolean?' (вопрос означает необязательное поле);
  • Infer<S>: обязательные поля с соответствующими типами, необязательные с ?;
  • validate<S extends Schema>(schema: S, value: unknown): { ok: true; data: Infer<S> } | { ok: false; errors: string[] }; ошибки в порядке полей схемы: <поле>: expected <тип>. Лишние поля в data не попадают. Не объект: errors: ['expected object'].

demo(value) валидирует пользователя по схеме и использует data с выведенным типом.

Примеры

demo({"name":"Аня","age":30}) // {"name":"Аня","age":30,"admin":false}
demo({"name":"Боря","age":40,"admin":true,"extra":1}) // {"name":"Боря","age":40,"admin":true}
demo({"name":1,"age":"2"}) // ["name: expected string", "age: expected number"]

Как подойти

Тип: пересечение двух mapped-типов (обязательные и необязательные ключи). Рантайм: обход схемы, typeof-проверка.

Подсказки: 3
  1. Раздели ключи на обязательные и необязательные условным типом по значению схемы.
  2. Шаблонный литеральный тип с infer: S[K] extends `${infer B extends Base}?`.
  3. Внутри реализации собирай Record<string, unknown> и в конце приведи к Infer<S> один раз.

Решите в тренажёре

Редактор с автотестами прямо в браузере. Можно решить спокойно, вслух или под таймером, как на собесе.