ToolActToolAct

JSON para TypeScript

Converta automaticamente dados JSON para interfaces TypeScript ou definições de tipo

Entrada JSON
Linhas: 1 | Caracteres: 0
Saída TypeScript
// Definições de tipo TypeScript serão geradas automaticamente
Tipos: 0 | Linhas: 1

O que é JSON para TypeScript?

JSON to TypeScript analisa uma estrutura JSON e gera interfaces ou aliases de tipo TypeScript a partir dela. Ele é útil quando respostas de API, arquivos de configuração, payloads de exemplo ou dados simulados precisam entrar rapidamente em um projeto frontend ou Node.js tipado. A ferramenta infere objetos, arrays, propriedades aninhadas, campos opcionais e tipos básicos, transformando dados brutos em uma base prática para autocompletar código e fazer verificações em tempo de compilação. Ainda assim, a saída precisa de revisão: um exemplo pode omitir campos, arrays vazios não revelam a forma dos itens e APIs reais podem retornar null ou variantes.

Como Usar

Como usar

  1. Cole dados JSON na caixa de entrada à esquerda ou clique no botão de exemplo para carregar um exemplo
  2. Configure as opções: defina o nome do tipo raiz, escolha o estilo interface/type, se deve adicionar export, etc.
  3. As definições de tipo TypeScript correspondentes são geradas automaticamente à direita
  4. Clique no botão 'Copiar' para copiar as definições de tipo geradas para a área de transferência
  5. Cole as definições de tipo em seu projeto TypeScript para utilizá-las

Dicas sobre Geração de Tipos

  • Use amostras JSON representativas. Um único exemplo não revela todos os campos opcionais, valores nulos ou tipos união em uma API real.
  • Revise os nomes gerados antes de commitá-los, especialmente em objetos aninhados onde os nomes automáticos de interface podem ser genéricos demais.

Casos de uso

Criar tipos TypeScript a partir de exemplos de APICole uma resposta JSON, escolha o estilo interface ou type alias e gere um tipo raiz com declarações aninhadas. A ferramenta mesma formas de objetos encontradas dentro de arrays, para que registros repetidos possam se tornar um modelo prático no cliente em vez de um conjunto de exemplos desconexos.
Adaptar rapidamente às convenções de nomenclatura locaisOpções para declarações exportadas, propriedades opcionais e prefixos I/T permitem adaptar o código gerado ao estilo existente do projeto antes de copiá-lo. Renomear o tipo raiz é útil ao transformar uma amostra bruta de endpoint em um modelo de domínio como UserProfileResponse ou InvoiceLine.
Inicializar mocks e fixtures com segurançaQuando um fixture cresce mais rápido do que sua definição de tipo, converter a amostra JSON mais recente revela campos ausentes, valores nulos, arrays vazios e tipos primitivos misturados. É uma maneira rápida de manter testes e dados de demonstração alinhados com a forma que a UI realmente consome.
Gerar tipos separados para variantes de uniãoQuando um campo pode ser string, number ou objeto aninhado dependendo do caso, divida as amostras JSON e execute cada uma pelo gerador para obter tipos variantes limpos em vez de uma união ruidosa. Monte manualmente as variantes com uma discriminated union depois para um narrowing correto em instruções switch. Observe que a ferramenta marca todo campo observado, mas nunca um não observado, então um array vazio [] produz unknown[] em vez de uma forma de elemento fantasma, e uma união inferida de primitivos misturados frequentemente oculta o discriminador que você realmente precisa para o switch.
Comparar tipos gerados com definições OpenAPIExecute uma resposta real pelo conversor e depois faça diff do resultado contra os tipos oficiais do OpenAPI ou gerados pelo backend. Captura campos ausentes, nulabilidade incorreta e incompatibilidades de itens de array que uma única amostra não expõe, especialmente quando o contrato da API se desviou do comportamento em produção. A flag ? do gerador rastreia presença em múltiplos objetos na mesma entrada; uma única amostra nunca a define, então um campo genuinamente obrigatório ainda parecerá opcional até que você forneça um segundo payload que também o omita. Chaves em snake_case como user_id são preservadas literalmente em vez de convertidas para camelCase, para que o resultado se alinhe com SDKs do servidor que emitem JSON em snake_case sem renomeação.

Princípio técnico

JSON para TypeScript é fundamentalmente um processo de 'inferência de estrutura'. A ferramenta percorre cada nó da árvore JSON recursivamente, mapeando o tipo em tempo de execução de cada valor para um tipo TypeScript: string -> string, number -> number, boolean -> boolean, null -> null, object -> sub-interface, array -> array do tipo do elemento. A saída é um conjunto de declarações `interface` TypeScript (ou aliases `type` se o modo de saída 'type' for selecionado) mais quaisquer interfaces aninhadas extraídas de campos com valor de objeto. A parte difícil da inferência é a decisão entre união e tipo único para arrays. Quando todos os elementos de um array têm o mesmo tipo, a saída é `T[]` (array homogêneo). Quando elementos têm tipos diferentes, a saída é a união desses tipos: `[1, 'a', true]` se torna `(number | string | boolean)[]`. Quando a entrada é um objeto que mistura valores literais e estruturados (ex.: `{ id: 1, name: 'Alice', tags: ['admin', 'editor'] }`), cada campo recebe seu próprio tipo; para objetos com valores primitivos misturados a página emite uma única interface, não uma união, pois é isso que o código TypeScript espera (e corresponde à natureza do objeto JSON como um tipo record). Múltiplos objetos de amostra (o caso de uso típico: colar um array JSON) são mesclados por interseção de suas formas. Campos presentes em todas as amostras se tornam obrigatórios; campos ausentes em qualquer amostra se tornam opcionais (`fieldName?: T`). Este é o comportamento correto para respostas de API: uma resposta 200 OK tem uma forma, uma resposta 404 tem outra, e a união de ambas é o tipo TS correto. Para uma única amostra, todo campo é obrigatório. A normalização de nomes é onde a maioria das ferramentas 'JSON para TS' falha. Chaves JSON geralmente são snake_case (`user_id`, `created_at`) ou camelCase (`userId`, `createdAt`); a convenção TypeScript é PascalCase para nomes de interface (`UserProfile`, `AuditEntry`) e camelCase para nomes de propriedade. A página converte chaves JSON para camelCase (ou as preserva se já forem camelCase ou palavra única) e PascalCase para nomes de interface. Objetos internos são extraídos em interfaces nomeadas: `{ user: { name, age } }` se torna `interface User { name: string; age: number; }` e o pai se torna `interface Root { user: User; }`. Estruturas recursivas (um nó de árvore com um campo `children: TreeNode[]`) recebem uma auto-referência usando uma declaração `type` forward em vez de `interface` para que o ciclo seja bem definido. A alternância 'root' é a diferença entre um array raiz e um objeto raiz. Um array JSON se torna `type Root = Item[]` ou `interface Root { items: Item[]; ... }` dependendo da opção de encapsulamento de array. Um objeto JSON se torna uma interface plana no nível superior. Strings de data (RFC 3339 / ISO 8601) podem ser marcadas como `Date` em vez de `string`; UUIDs, emails e URLs podem ser marcados como branded types (`type UUID = string & { readonly __brand: 'UUID' };`) quando a opção modo estrito está ativada. A geração de JSDoc é heurística: um campo chamado `email` (e cujo valor corresponde a um regex básico de email) recebe um comentário como `/** user email */` acima da declaração. O mesmo vale para `id`, `name`, `url`, `created_at`/`createdAt`, `updated_at`/`updatedAt`, `description`, `title`. Os comentários são de melhor esforço e não pretendem ser escritos por humanos; são um ponto de partida que os humanos editarão. A página também emite modificadores `export` para que a saída possa ser inserida diretamente em qualquer arquivo TS, e um cabeçalho `// generated by json-to-typescript, do not edit by hand` para desencorajar edições manuais que seriam sobrescritas na próxima vez que o schema for regenerado.

  • Mapeamento de tipos atômicos: string/number/boolean/null do JSON mapeiam um-para-um para string/number/boolean/null do TypeScript. Inteiros grandes (>2^53) precisam de BigInt; a página os marca como `bigint` quando o valor excede Number.MAX_SAFE_INTEGER.
  • Inferência de tipo de array: percorre todos os elementos e toma a união de seus tipos; tipos idênticos colapsam para `T[]`, tipos distintos formam `(A | B | C)[]`. Arrays vazios se tornam `unknown[]` pois o tipo do elemento é desconhecido.
  • Extração de objetos aninhados: objetos internos são automaticamente elevados a interfaces nomeadas. Estruturas recursivas usam `type Name = ...` (não `interface`) para que a referência forward seja bem definida no verificador de tipos do TypeScript.
  • Detecção de campos opcionais: quando múltiplos objetos de amostra são mesclados, campos presentes em todas as amostras se tornam obrigatórios; campos ausentes em qualquer amostra se tornam opcionais (`fieldName?: T`). Entrada com uma única amostra marca todo campo como obrigatório.
  • Convenção de nomenclatura: chaves JSON são convertidas para camelCase para nomes de propriedade (user_id -> userId, created_at -> createdAt) e PascalCase para nomes de interface (UserProfile, AuditEntry). Chaves de palavra única são preservadas; números em chaves são preservados; dígitos iniciais recebem prefixo underscore para permanecerem identificadores TS válidos.
  • Alternância root: array raiz -> `export type Root = Item[]` (ou encapsulado em `{ items: Item[]; }` se wrap-array estiver ativo); objeto raiz -> uma única `export interface Root { ... }`. Estruturas recursivas recebem primeiro um stub de declaração forward.
  • Comentários JSDoc: geração heurística de comentários para nomes de campos conhecidos (email, id, name, url, createdAt, updatedAt, description, title). A saída inclui modificadores `export` e um cabeçalho `// generated, do not edit by hand` para desencorajar edições manuais.
  • Modo estrito: opt-in por branded types (UUID, Email, URL, Date), modificadores readonly, exactOptionalPropertyTypes e noUncheckedIndexedAccess. A página emite `type UUID = string & { readonly __brand: 'UUID' };` quando o modo estrito está ativo, para que o código downstream possa distinguir uma string bruta de um valor tipado.

Exemplos

Objeto simples para interface

{"id": 1, "name": "Alice", "active": true}
->
interface User {
  id: number;
  name: string;
  active: boolean;
}

Objeto aninhado gera sub-interfaces

{"user": {"name": "Alice", "address": {"city": "NYC"}}}
->
interface Root {
  user: User;
}
interface User {
  name: string;
  address: Address;
}
interface Address {
  city: string;
}

Array para tupla readonly

[{"id": 1}, {"id": 2}]
->
interface Item {
  id: number;
}
type Root = readonly Item[];

Perguntas frequentes

Quais construtores TypeScript ele gera?

Interfaces por padrão — uma para cada formato de objeto. Campos opcionais usam o marcador ?. Arrays viram T[]. Arrays com tipos mistos viram uma union. Strings com formatos reconhecidos (por exemplo, datas ISO) permanecem como string a menos que você opte por branded types. Algumas páginas oferecem aliases de 'type' em vez de 'interface'.

Como objetos aninhados são tratados?

Cada formato aninhado distinto recebe sua própria interface, nomeada conforme o caminho da propriedade (User, UserAddress, UserPreferences). Se duas propriedades compartilham o mesmo formato, o gerador pode ou não desduplicar dependendo das configurações — confira a saída e consolide manualmente se necessário.

As propriedades são obrigatórias ou opcionais?

Por padrão, propriedades presentes na amostra são marcadas como obrigatórias. Propriedades que aparecem em alguns elementos do array, mas não em outros, são marcadas como opcionais com `?`. Ative 'todas opcionais' se sua amostra é um exemplo entre muitos formatos possíveis.

Como ele lida com null e undefined?

null no JSON vira `null` no TypeScript (não undefined). Uma propriedade que é às vezes string e às vezes null vira `string | null`. JSON não tem undefined, então o gerador nunca emite `undefined` diretamente.

E sobre union types e discriminated unions?

Quando um array contém formatos de objeto mistos, o gerador emite uma union de interfaces. Ele não detecta automaticamente um campo discriminador; reescreva manualmente como discriminated union (por exemplo, tag 'kind') se quiser estreitamento exaustivo de tipos.

O JSON é enviado para algum servidor?

Não. A conversão roda no seu navegador via um parser JSON em JS e templates de string. O JSON colado não sai do seu dispositivo.

Vai bater com o que meu backend realmente retorna?

Apenas na medida em que a amostra for representativa. Sempre valide os dados em tempo de execução com um schema (Zod, io-ts, Yup) — os tipos do TypeScript são apagados em runtime e não vão pegar um backend que se desviou do exemplo.