PassFront
  1. PassFront
  2. База знаний
  3. Продвинутые типы

Как проверять данные с сервера, если TypeScript проверяет типы только при компиляции?

Продвинутые типы

Типы TypeScript стираются при компиляции и ничего не проверяют во время работы. Данные из fetch, localStorage или формы приходят снаружи, и сервер может вернуть не то, что описано в интерфейсе.

В чём проблема

interface User { id: number; name: string }

const user = (await res.json()) as User; // это только утверждение, а не проверка
user.name.toUpperCase(); // упадёт, если name пришло null

as User лишь убеждает компилятор: проверки не происходит.

Runtime-валидация

Данные проверяют схемой при входе в приложение. Популярные библиотеки: Zod, Valibot, io-ts, Yup.

import { z } from 'zod';

const UserSchema = z.object({ id: z.number(), name: z.string() });
type User = z.infer<typeof UserSchema>; // тип выводится из схемы

const user = UserSchema.parse(await res.json()); // бросит ошибку при несоответствии

Одна схема даёт и проверку, и тип — расхождений не будет. safeParse возвращает результат без исключения.

Type guard вручную

Для простых случаев:

function isUser(value: unknown): value is User {
  return typeof value === 'object' && value !== null && 'id' in value && 'name' in value;
}

Где проверять

На границе системы: ответы API, localStorage, postMessage, переменные окружения. Внутри приложения проверенным данным можно доверять.

Дополнительные подходы

Генерация типов и клиента из OpenAPI/GraphQL-схемы уменьшает расхождение контракта, но не заменяет проверку для ненадёжных данных.

Коротко для собеседования

TypeScript проверяет только исходный код, не данные во время работы. Ответы API валидируют на входе схемой (Zod и аналоги) и выводят тип из неё; as — это не проверка.

Другие вопросы раздела