Skip to content
Назад к блогу
Руководства

JSON в TypeScript: генерация интерфейсов и типов (гайд 2026)

Правильно конвертируйте JSON в интерфейсы TypeScript: правила вывода типов, interface против type, опциональные и union-поля, а также частые ошибки. Попробуйте бесплатно.

11 мин чтения

JSON в TypeScript: генерация интерфейсов и типов (гайд 2026)

Самый быстрый путь от JSON к TypeScript — вставить payload в конвертер JSON в TypeScript и скопировать сгенерированный интерфейс: ничего не нужно устанавливать или загружать, всё происходит в браузере. Это закрывает сценарий «типы нужны прямо сейчас».

Но сгенерировать типы и сгенерировать хорошие типы — это разные вещи. Конвертеру приходится угадывать: это поле опциональное или просто отсутствует в одном из примеров? Этот массив всегда состоит из строк или иногда содержит и числа? Стоит ли превращать строку с датой в Date? В этом гайде разбирается, как на самом деле работает вывод типов, когда выбирать interface, а когда type, и какие реальные подводные камни возникают при превращении живых ответов API в типы, которым можно доверять.

Как конвертировать JSON в TypeScript

Конвертация JSON в TypeScript занимает три шага:

  1. Вставьте свой JSON. Поместите объект, массив или сырой ответ API в поле ввода. Конвертация запускается мгновенно, полностью на стороне клиента.
  2. Настройте вывод. Выберите interface или type, задайте корневое имя вроде User или ApiResponse, включите ключевое слово export и выберите ?: или | null для опциональных полей.
  3. Скопируйте или скачайте. Получите готовый TypeScript одним кликом и вставьте его прямо в свой код.

На этом транзакционный путь закончен. Конвертер JSON в TypeScript читает входные данные, выводит дерево типов и печатает определения справа — ничего не покидает страницу. Остальная часть гайда посвящена тому, чтобы понять полученный результат и исправить случаи, которые угадать невозможно.

Как типы JSON соответствуют TypeScript

У каждого значения JSON есть аналог в TypeScript. Соответствие в основном взаимно-однозначное:

Значение JSONТип TypeScript
"text"string
42, 3.14number
true / falseboolean
nullnull
[1, 2, 3]number[]
{ ... }interface или type

Основная работа разворачивается вокруг объектов. Возьмём типичный REST-payload пользователя:

{
  "id": 101,
  "name": "Ada Lovelace",
  "email": "ada@example.com",
  "active": true,
  "roles": ["admin", "user"]
}

Из этого JSON конвертер создаёт такой интерфейс TypeScript:

export interface User {
  id: number;
  name: string;
  email: string;
  active: boolean;
  roles: string[];
}

Каждый скаляр соответствует своему примитивному типу, а массив roles превращается в string[]. Добавьте это в свой клиент API — и вы бесплатно получаете автодополнение и проверки на этапе компиляции.

Как конвертер выводит типы

Дальше начинается алгоритм вывода типов. Четыре правила покрывают почти всё, что вы ему скормите.

Структурный вывод: один именованный интерфейс на объект

Каждая отдельная форма объекта становится собственным именованным интерфейсом. Вложенные объекты не схлопываются в inline-типы — они выносятся в отдельные определения со ссылками на них:

{
  "order": {
    "id": "A-1",
    "total": 42.5,
    "customer": { "name": "Sam", "vip": false }
  }
}
export interface Root {
  order: Order;
}

export interface Order {
  id: string;
  total: number;
  customer: Customer;
}

export interface Customer {
  name: string;
  vip: boolean;
}

Идентичные формы дедуплицируются, поэтому два поля с одинаковой структурой используют один интерфейс вместо того, чтобы создавать копии.

Слияние массивов: вывод опциональных полей

Когда вы передаёте массив объектов, конвертер сливает их ключ за ключом. Если ключ встречается в одних элементах, но отсутствует в других, он помечается как опциональный:

{
  "users": [
    { "id": 1, "nick": "x" },
    { "id": 2 }
  ]
}
export interface Root {
  users: User[];
}

export interface User {
  id: number;
  nick?: string;
}

id есть в каждом элементе, поэтому остаётся обязательным. nick отсутствует у второго пользователя, поэтому становится nick?: string. Именно поэтому одного примера редко бывает достаточно — см. раздел про подводные камни ниже.

Union-типы для смешанных массивов

Массивы не обязаны быть однородными. Когда элементы имеют разные типы, конвертер собирает их в union:

{
  "tags": ["a", "b"],
  "meta": [1, "two"]
}
export interface Root {
  tags: string[];
  meta: (string | number)[];
}

tags состоит только из строк, поэтому string[]. meta смешивает число и строку, давая (string | number)[]. Пустой массив вывести вообще нельзя, и он откатывается к unknown[] — честно, ведь из нуля элементов узнать нечего.

Опциональное против null: ?: против | null

Они выглядят похоже, но означают разное. Поле, помеченное ?:, может вообще отсутствовать в объекте. Поле с типом | null всегда присутствует, но может хранить значение null:

{ "score": null }
export interface Root {
  score: number | null;
}

Здесь score присутствует с явным null, поэтому получает тип number | null — значение существует, просто оно равно null. Сравните это с nick?: string из примера с массивом, где ключ может отсутствовать вовсе. Выбирайте ?:, когда API может опустить ключ, и | null, когда он присылает ключ со значением null. Большинство конвертеров позволяют управлять отображением этого через переключатель.

interface против type: что выбрать?

Оба способа умеют описывать форму объекта. Вот как принять решение:

ПотребностьИспользуйте
Простая форма объекта из JSONinterface
Union (A | B) или intersection (A & C)type
Declaration merging / расширение между файламиinterface
Mapped- или conditional-типыtype
Немного более чистые сообщения об ошибках в редактореinterface

Для данных, полученных из объекта JSON, interface — это привычный выбор, который даёт чуть более приятные ошибки компилятора. Как только понадобится union — скажем, Result, который представляет собой либо успех, либо ошибку, — придётся переключиться на type, потому что интерфейсы не умеют выражать union:

type ApiResult =
  | { status: "ok"; data: User }
  | { status: "error"; message: string };

Хорошее значение по умолчанию: генерировать interface для простых объектов JSON и переходить на type, когда форме нужен union или intersection. Справочник TypeScript разбирает крайние случаи, если нужно полное сравнение. Когда вместо интерфейса нужен json to typescript type (псевдоним типа), большинство конвертеров предлагают один переключатель, который меняет весь вывод.

quicktype против json-to-ts против онлайн-инструментов против ручной работы

Единственного лучшего способа генерировать типы TypeScript нет — всё зависит от того, где живёт JSON и как часто он меняется.

ПодходЛучше всего дляКомпромисс
quicktypeВывод на нескольких языках, генерация кода для рантайм-валидацииТяжелее; вывода больше, чем часто нужно
json-to-ts (библиотека)Кодогенерация на этапе сборки, встроенная в скрипт или pipelineТребует настройки и Node-инструментария
Онлайн-инструмент в браузереРазовые конвертации, чувствительные payload, нулевая установкаКаждый раз приходится вставлять вручную
Написание типов вручнуюКрошечные объекты, изучение системы типовУтомительно и подвержено ошибкам при масштабе

Выбирайте quicktype, когда нужны типы на нескольких языках или нужно, чтобы он выдавал валидаторы вместе с типами. Выбирайте библиотеку json-to-ts, когда конвертация относится к этапу сборки. Для быстрой конвертации — особенно payload, содержащего token, идентификаторы клиентов или что-то, что лучше не вставлять в удалённый сервис, — браузерный инструмент выигрывает по приватности и скорости. Наш конвертер JSON в TypeScript работает полностью на стороне клиента: JSON никогда не покидает страницу, и нечего устанавливать или обновлять.

Типы — это не валидация: переход к рантайм-проверкам

На этом спотыкается множество команд, поэтому стоит сказать прямо: типы TypeScript стираются на этапе компиляции и ничего не делают в рантайме. Сгенерированный interface User не будет проверять, что реальный ответ API ему соответствует. Если сервер пришлёт id строкой вместо числа, TypeScript с радостью поверит вашей аннотации типа, пока реальные данные лгут.

Чтобы generate typescript types и обеспечить их соблюдение на живых данных, объедините типы с рантайм-валидатором:

  • zod — определите схему один раз, выведите из неё статический тип и разбирайте ответы в рантайме.
  • io-ts — валидация на основе кодеков, популярна в функциональных кодовых базах.
  • JSON Schema + Ajv — независимые от языка схемы, проверяемые в рантайме; полезны, когда контракт разделяется между сервисами.

Распространённый паттерн — сгенерировать интерфейс для поддержки в редакторе, а затем написать соответствующую схему zod как фактическую проверку на границе:

import { z } from "zod";

const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
  active: z.boolean(),
  roles: z.array(z.string()),
});

type User = z.infer<typeof UserSchema>;

// Throws if the real response doesn't match the schema.
const user = UserSchema.parse(await res.json());

Если вы идёте путём схем, наш гайд по валидации JSON Schema подробно разбирает написание и применение схем от начала до конца.

Частые ошибки при типизации JSON

Сгенерированные типы — это отправная точка, а не готовый продукт. Следите за этим.

snake_case против camelCase. Конвертеры сохраняют ключи дословно. Payload в стиле GitHub с public_repos даст public_repos: number, а не publicRepos. Если в вашей кодовой базе предпочитают camelCase, придётся либо мириться со snake_case-типами, либо добавить слой маппинга, который переименовывает поля на входе.

Строки с датами остаются string. Поле вроде "2026-06-01T00:00:00Z" типизируется как string, а не Date. Это сделано намеренно: в JSON нет типа для дат, а ошибиться в догадке хуже, чем быть честным. Преобразование строки в Date относится к вашему слою разбора, где оно под вашим контролем.

Утечка any и unknown. Пустые массивы становятся unknown[], а глубоко смешанные структуры могут деградировать до расплывчатых типов. Это не баги; так конвертер признаёт, что не может вывести тип из недостаточных данных. Уточните их вручную, когда узнаете реальную форму.

Взрыв глубокой вложенности. Сильно вложенный payload генерирует длинную цепочку небольших интерфейсов. Обычно это нормально и читается лучше, чем один гигантский inline-тип, но стоит уплощать формы, которые не заслуживают собственного имени.

Ловушка единственного примера. Это главная из всех. Опциональные поля можно вывести только из нескольких элементов массива — один объект не может подсказать конвертеру, какие ключи иногда отсутствуют. Сначала соберите представительный массив ответов. Форматировщик JSON удобен, чтобы вставить и просмотреть несколько примеров бок о бок перед конвертацией, а если вы подаёте нестандартный ввод вроде JSONC, прочитайте наш гайд по JSON5 / JSONC — конвертеру нужен строго валидный JSON.

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

Как конвертировать JSON в интерфейс TypeScript?

Вставьте свой JSON в конвертер JSON в TypeScript. Он читает ввод в браузере и мгновенно генерирует интерфейс TypeScript. Нажмите «Скопировать», чтобы забрать результат, — никакой загрузки, никакого аккаунта, никакого плагина для установки.

interface или type для данных JSON?

Используйте interface для простых форм объектов из JSON — это привычно и даёт чуть более понятные ошибки в редакторе. Переключайтесь на type, когда нужен union или intersection, поскольку интерфейсы не умеют их выражать.

Как обрабатываются вложенные объекты и массивы?

Вложенные объекты становятся отдельными именованными интерфейсами (поле address даёт интерфейс Address). Массивы объектов сливаются ключ за ключом в один интерфейс элемента; массивы примитивов становятся типизированными массивами вроде string[].

Как типизируются опциональные и null-поля?

Ключ, отсутствующий в части элементов массива, помечается как опциональный (nick?: string). Ключ, который всегда присутствует, но хранит null, типизируется через | null (score: number | null). Эти два варианта описывают разные ситуации: отсутствует против присутствует-но-null.

Валидируют ли типы TypeScript данные JSON в рантайме?

Нет. Типы TypeScript стираются на этапе компиляции и не проверяют данные в рантайме. Чтобы проверить реальный ответ API, объедините сгенерированные типы с рантайм-валидатором вроде zod, io-ts или JSON Schema с Ajv.

quicktype против json-to-ts против онлайн-конвертера — что лучше?

quicktype подходит для вывода на нескольких языках и рантайм-валидаторов; библиотека json-to-ts подходит для кодогенерации на этапе сборки; онлайн-конвертер подходит для быстрых, приватных, разовых конвертаций с нулевой установкой. Для чувствительных payload браузерный инструмент на стороне клиента держит данные подальше от любого сервера.

Почему строки с датами типизируются как string, а не Date?

В JSON нет типа для дат, поэтому дата — это просто строка на проводе. Типизация её как string честна и стабильна; преобразование в Date — это решение вашего слоя разбора, где вы контролируете формат и обработку ошибок.

Приватны ли мои данные JSON при использовании онлайн-конвертера?

С инструментом на стороне клиента — да. Конвертация выполняется полностью в вашем браузере на JavaScript, поэтому JSON — включая token, идентификаторы и данные клиентов — никогда не покидает страницу и никогда не отправляется на сервер.

Похожие статьи

Все статьи