Skip to content
Voltar ao blog
Tutoriais

JSON para TypeScript: gerar interfaces e tipos (guia 2026)

Converta JSON em interfaces TypeScript do jeito certo: regras de inferência de tipos, interface vs type, campos opcionais e uniões, e armadilhas a evitar. Grátis.

11 min de leitura

JSON para TypeScript: gerar interfaces e tipos (guia 2026)

O jeito mais rápido de ir de JSON para TypeScript é colar seu payload em um conversor de JSON para TypeScript e copiar a interface que ele gera — sem instalar nada, sem upload, tudo pronto no seu navegador. Isso resolve o caso “preciso dos tipos agora”.

Mas gerar tipos e gerar tipos bons são duas coisas diferentes. Um conversor precisa adivinhar: este campo é opcional ou só estava faltando em uma amostra? Aquele array é sempre de strings, ou às vezes também tem números? A string de data deveria virar um Date? Este guia mostra como a inferência funciona de fato, quando recorrer a interface em vez de type, e as armadilhas reais de transformar respostas de API ao vivo em tipos nos quais você pode confiar.

Como converter JSON para TypeScript

Converter JSON para TypeScript tem três passos:

  1. Cole seu JSON. Solte um objeto, um array ou uma resposta crua de API na caixa de entrada. A conversão roda na hora, inteiramente no lado do cliente.
  2. Ajuste a saída. Escolha interface ou type, defina um nome de raiz como User ou ApiResponse, ligue/desligue a palavra-chave export e escolha ?: ou | null para campos opcionais.
  3. Copie ou baixe. Pegue o TypeScript gerado com um clique e cole direto na sua base de código.

É só isso no caminho transacional. O conversor de JSON para TypeScript lê a entrada, infere uma árvore de tipos e imprime as definições à direita, sem nada sair da página. O resto deste guia é sobre entender o que foi produzido para que você consiga corrigir os casos que ele não consegue adivinhar.

Como os tipos JSON mapeiam para TypeScript

Todo valor JSON tem um equivalente em TypeScript. O mapeamento é quase sempre um-para-um:

Valor JSONTipo TypeScript
"text"string
42, 3.14number
true / falseboolean
nullnull
[1, 2, 3]number[]
{ ... }interface ou type

Os objetos são onde o trabalho acontece. Pegue um payload típico de usuário em REST:

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

Um conversor produz esta interface TypeScript a partir do JSON:

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

Cada escalar mapeia para seu tipo primitivo, e o array roles vira string[]. Coloque isso no seu cliente de API e você ganha autocomplete e verificações em tempo de compilação de graça.

Como o conversor infere os tipos

A parte interessante é o algoritmo de inferência. Quatro regras cobrem quase tudo que você vai jogar nele.

Inferência estrutural: uma interface nomeada por objeto

Cada formato de objeto distinto vira sua própria interface nomeada. Objetos aninhados não colapsam em tipos inline; eles são içados para definições separadas e referenciadas:

{
  "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;
}

Formatos idênticos são deduplicados, então dois campos com a mesma estrutura compartilham uma única interface em vez de gerar cópias.

Mesclagem de arrays: inferindo campos opcionais

Quando você passa um array de objetos, o conversor os mescla chave por chave. Se uma chave aparece em alguns elementos mas não em outros, ela é marcada como opcional:

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

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

id está em todos os elementos, então continua obrigatório. nick está ausente no segundo usuário, então vira nick?: string. É por isso que uma única amostra raramente é suficiente (veja a seção de armadilhas abaixo).

Tipos de união para arrays mistos

Arrays não precisam ser homogêneos. Quando os elementos têm tipos diferentes, o conversor os reúne em uma união:

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

tags é uniformemente de strings, então string[]. meta mistura um número e uma string, produzindo (string | number)[]. Um array vazio não pode ser inferido de jeito nenhum e recai em unknown[], o que é honesto: não há nada a aprender de zero elementos.

Opcional vs null: ?: versus | null

Estes parecem semelhantes, mas significam coisas diferentes. Um campo marcado com ?: pode estar totalmente ausente do objeto. Um campo tipado com | null está sempre presente, mas pode conter o valor null:

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

Aqui score está presente com um null explícito, então é tipado como number | null: o valor existe, só está nulo. Compare isso com nick?: string do exemplo do array, onde a chave pode estar ausente por completo. Recorra a ?: quando a API pode omitir a chave, e a | null quando ela envia a chave com um valor nulo. A maioria dos conversores deixa você controlar como isso é renderizado por meio de um botão de alternância.

interface vs type: qual você deve usar?

Ambos conseguem descrever o formato de um objeto. Veja como decidir:

NecessidadeUse
Formato de objeto simples vindo de JSONinterface
União (A | B) ou interseção (A & C)type
Mesclagem de declarações / extensão entre arquivosinterface
Tipos mapeados ou condicionaistype
Mensagens de erro do editor um pouco mais limpasinterface

Para dados que saíram de um objeto JSON, interface é a escolha convencional e produz erros de compilador um pouco mais agradáveis. Quando você precisa de uma união (digamos, um Result que é ou um sucesso ou um erro), tem que mudar para um type, porque interfaces não conseguem expressar uniões:

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

Um bom padrão: gerar uma interface para objetos JSON simples e converter para um type quando o formato precisa de uma união ou interseção. O Manual do TypeScript cobre os casos extremos se você quiser a comparação completa. Quando você precisa de um alias de json to typescript type em vez de uma interface, a maioria dos conversores expõe um único botão de alternância para inverter toda a saída.

quicktype vs json-to-ts vs ferramentas online vs manual

Não existe um único melhor jeito de gerar tipos TypeScript. Depende de onde o JSON mora e com que frequência ele muda.

AbordagemMelhor paraContrapartida
quicktypeSaída multilíngue, gerar código de validação em runtimeMais pesado; mais saída do que você costuma precisar
json-to-ts (biblioteca)Geração de código em tempo de build integrada a um script ou pipelineExige configuração e um toolchain Node
Ferramenta online baseada no navegadorConversões pontuais, payloads sensíveis, zero instalaçãoColar manualmente toda vez
Escrever tipos à mãoObjetos minúsculos, aprender o sistema de tiposTedioso e sujeito a erros em escala

Escolha o quicktype quando precisar de tipos em várias linguagens ou quiser que ele emita validadores junto com os tipos. Escolha a biblioteca json-to-ts quando a conversão pertence a uma etapa de build. Para uma conversão rápida, especialmente de um payload contendo tokens, IDs de clientes ou qualquer coisa que você prefira não colar em um serviço remoto, uma ferramenta de navegador vence em privacidade e velocidade. Nosso conversor de JSON para TypeScript roda inteiramente no lado do cliente: o JSON nunca sai da página, e não há nada para instalar ou atualizar.

Tipos não são validação: fazendo a ponte com verificações em runtime

Isso confunde muitas equipes, então vale dizer com todas as letras: os tipos do TypeScript são apagados em tempo de compilação e não fazem nada em runtime. Uma interface User gerada não vai verificar se uma resposta de API real corresponde a ela. Se o servidor envia id como uma string em vez de um número, o TypeScript acredita feliz na sua anotação de tipo enquanto os dados reais mentem.

Para generate typescript types e forçar seu cumprimento em dados ao vivo, combine os tipos com um validador de runtime:

  • zod — defina um schema uma vez, infira o tipo estático a partir dele e faça o parse das respostas em runtime.
  • io-ts — validação baseada em codecs, popular em bases de código funcionais.
  • JSON Schema + Ajv — schemas agnósticos de linguagem validados em runtime, úteis quando o contrato é compartilhado entre serviços.

Um padrão comum é gerar a interface para suporte do editor e depois escrever um schema zod correspondente como a verificação de fronteira de fato:

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>;

// Lança um erro se a resposta real não corresponder ao schema.
const user = UserSchema.parse(await res.json());

Se você for pelo caminho do schema, nosso guia de validação com JSON Schema percorre a escrita e o cumprimento de schemas de ponta a ponta.

Armadilhas comuns ao tipar JSON

Tipos gerados são um ponto de partida, não um produto acabado. Fique atento a estas.

snake_case vs camelCase. Conversores mantêm as chaves ao pé da letra. Um payload no estilo GitHub com public_repos produz public_repos: number, não publicRepos. Se sua base de código prefere camelCase, você vai conviver com os tipos em snake_case ou adicionar uma camada de mapeamento que renomeia os campos na entrada.

Strings de data continuam string. Um campo como "2026-06-01T00:00:00Z" é tipado como string, não Date. Isso é proposital: JSON não tem tipo de data, e adivinhar errado é pior do que ser honesto. A conversão de string para Date pertence à sua camada de parsing, onde você a controla.

Vazamento de any e unknown. Arrays vazios viram unknown[] e estruturas profundamente mistas podem degradar para tipos frouxos. Esses não são bugs; é o conversor admitindo que não consegue inferir a partir de dados insuficientes. Aperte-os à mão assim que souber o formato real.

Explosão de aninhamento profundo. Um payload fortemente aninhado gera uma longa cadeia de interfaces pequenas. Isso costuma estar tudo bem e é mais legível do que um tipo inline gigante, mas vale a pena achatar formatos que não merecem um nome próprio.

A armadilha da amostra única. Esta é a grande. Campos opcionais só podem ser inferidos a partir de múltiplos elementos de um array; um único objeto não consegue dizer ao conversor quais chaves às vezes estão ausentes. Colete primeiro um array representativo de respostas. Um formatador JSON é útil para colar e inspecionar várias amostras lado a lado antes de converter, e se você estiver alimentando entradas fora do padrão como JSONC, leia nosso guia de JSON5 / JSONC, porque o conversor precisa de JSON estritamente válido.

Perguntas frequentes

Como faço para converter JSON em uma interface TypeScript?

Cole seu JSON em um conversor de JSON para TypeScript. Ele lê a entrada no seu navegador e gera uma interface TypeScript na hora. Clique em Copiar para pegar o resultado: sem upload, sem conta, sem plugin para instalar.

Devo usar interface ou type para dados JSON?

Use interface para formatos de objeto simples vindos de JSON; é o convencional e dá erros de editor um pouco mais claros. Mude para type quando precisar de uma união ou interseção, já que interfaces não conseguem expressá-las.

Como objetos e arrays aninhados são tratados?

Objetos aninhados viram interfaces separadas e nomeadas (um campo address gera uma interface Address). Arrays de objetos são mesclados chave por chave em uma única interface de elemento; arrays de primitivos viram arrays tipados como string[].

Como campos opcionais e nulos são tipados?

Uma chave ausente em alguns elementos de um array é marcada como opcional (nick?: string). Uma chave que está sempre presente mas contém null é tipada com | null (score: number | null). As duas descrevem situações diferentes: ausente versus presente-mas-nulo.

Os tipos do TypeScript validam o JSON em runtime?

Não. Os tipos do TypeScript são apagados em tempo de compilação e não verificam os dados em runtime. Para validar uma resposta de API real, combine os tipos gerados com um validador de runtime como zod, io-ts ou JSON Schema com Ajv.

quicktype vs json-to-ts vs um conversor online — qual é o melhor?

O quicktype combina com saída multilíngue e validadores de runtime; a biblioteca json-to-ts combina com geração de código em tempo de build; um conversor online combina com conversões rápidas, privadas e pontuais com zero instalação. Para payloads sensíveis, uma ferramenta de navegador no lado do cliente mantém os dados fora de qualquer servidor.

Por que strings de data são tipadas como string em vez de Date?

JSON não tem tipo de data, então uma data é apenas uma string no fio. Tipá-la como string é honesto e estável; convertê-la para Date é uma decisão da sua camada de parsing, onde você controla o formato e o tratamento de erros.

Meus dados JSON ficam privados ao usar um conversor online?

Com uma ferramenta no lado do cliente, sim. A conversão roda inteiramente no seu navegador usando JavaScript, então o JSON (incluindo tokens, IDs e dados de clientes) nunca sai da página e nunca é enviado a um servidor.

Artigos relacionados

Ver todos os artigos