Типизация данных из API
Вопрос
Как безопасно типизировать ответ сервера? Чем плохо const user = await res.json() as User?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Типы стираются, `as` ничего не проверяет в рантайме
Если сервер вернёт другую форму, ошибка проявится далеко от места запроса
Правильно принимать данные как `unknown` и сужать
Для сложных форм использовать схему (zod, valibot): один источник для проверки и для типа через `z.infer`
Ещё вариант: генерация типов и клиентов из OpenAPI, но рантайм-проверку на границе это не заменяет
Что могут спросить следом
- Где проводить валидацию: в каждом компоненте или в одном слое?
- Что делать при невалидном ответе?
- Чем type guard хуже схемы?
Разбор
as User это обещание компилятору, а не проверка. Типы стираются, и если бэкенд переименует поле или вернёт null, приложение упадёт где-то в рендере, далеко от запроса. Поэтому всё, что приходит извне, я считаю unknown и сужаю на границе: в слое API-клиента. Для маленьких форм хватит type guard, но он ручной и легко врёт. Для реальных DTO беру схему, например zod: User.parse(json) проверяет данные в рантайме, а z.infer<typeof User> даёт тип, и они не разъезжаются. Если есть OpenAPI, генерирую из него типы, но это синхронизирует контракт на этапе сборки, а не проверяет конкретный ответ. При невалидном ответе бросаю понятную ошибку с логированием, чтобы UI показал состояние ошибки, а не сломался на undefined.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.