Разработка

Типы TypeScript из JSON — как делать правильно

Генерация типов из примера ответа занимает секунды. А вот типы, которым можно доверять, требуют чуть больше решений: что необязательно, что может быть null, как назвать сущности и как убедиться, что API держит обещания во время выполнения.

Средний · Чтение: 8 мин · Обновлено 30 октября 2026 г.

Типы TypeScript из JSON — как делать правильно

Начните с реальных примеров

Вставьте ответ в конвертер JSON в TypeScript, и вы получите интерфейсы для каждого вложенного объекта. Но один пример описывает только одну структуру, поэтому вставляйте массив из нескольких реальных объектов: конвертер объединит их и пометит как необязательные поля, которых нет в некоторых из них.

[
  { "id": 1, "name": "Ada", "email": "ada@example.com", "team": { "id": 7, "name": "Core" } },
  { "id": 2, "name": "Grace", "email": null }
]
interface User {
  id: number;
  name: string;
  email: string | null;
  team?: Team;
}
interface Team {
  id: number;
  name: string;
}

Необязательное не значит nullable

team?: Team означает, что ключ может отсутствовать. email: string | null означает, что ключ всегда есть, но может содержать null. API используют их по-разному, и в коде проверяются они тоже по-разному ('team' in user и user.email === null), поэтому сохраняйте различие, а не превращайте всё в ?: … | null.

Уточните то, что пример не может показать

  • Литеральные объединения — поле status, которое в примере равно "active", станет string; замените его на 'active' | 'paused' | 'deleted' из документации API.
  • Даты приходят как строки ISO. Типизируйте их как string и разбирайте на границе приложения — не притворяйтесь, что это объекты Date.
  • ID — большие числовые ID (больше 253) теряют точность в JavaScript, поэтому многие API по этой причине отдают их строками.
  • Пустые массивы становятся unknown[] или any[]; тип элементов укажите сами.

Во время выполнения типов нет

TypeScript проверяет ваш код, а не данные. Если API изменится, компилятор этого не заметит. Проверяйте ответы на границе:

  1. Создайте схему по тем же примерам с помощью JSON в JSON Schema.
  2. Отредактируйте её — обязательные поля, перечисления, форматы вроде date-time — и проверьте реальные данные в JSON Schema Validator.
  3. Проверяйте данные в приложении с помощью библиотеки, например Ajv, и генерируйте типы из схемы (JSON Schema в TypeScript), чтобы был один источник истины.
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(userSchema);
const data = await res.json();
if (!validate(data)) throw new Error('Unexpected API response: ' + ajv.errorsText(validate.errors));

Библиотеки вроде Zod или Valibot делают то же самое, но схема пишется на самом TypeScript, а тип выводится из неё.

Именование и структура

Давайте корневому типу осмысленное имя (User, а не Root), экспортируйте типы из одного модуля и используйте interface для объектов, которые, возможно, понадобится расширять. Сначала отформатируйте большие ответы в JSON Formatter, чтобы увидеть, какие ветки важны.

Часто задаваемые вопросы

Как преобразовать JSON в интерфейс TypeScript?
Вставьте JSON в конвертер, например JSON в TypeScript от devpack. Используйте несколько реальных примеров в массиве, чтобы необязательные поля определились автоматически.
Что использовать: interface или type?
Для описания объектов подходят оба варианта. Интерфейсы можно расширять и объединять, а псевдонимы type нужны для объединений и mapped-типов. Многие команды используют interface для объектов, а type — для всего остального.
Проверяют ли типы TypeScript данные API?
Нет, типы удаляются при компиляции. Проверяйте данные во время выполнения с помощью JSON Schema (Ajv) или библиотеки схем вроде Zod.

Читайте также