JSON para TypeScript
Interfaces mescladas a partir de todos os elementos do array, para que o opcional seja realmente opcional.
Nada do que você cola sai do seu navegador. A lista de permissões connect-src transforma isso em uma garantia do navegador, e não em uma promessa. Confira você mesmo
Transforme um payload JSON em interfaces TypeScript. Objetos aninhados viram tipos com nome próprio, arrays são mesclados a partir de todos os elementos, e formatos estruturalmente idênticos são emitidos uma vez e reaproveitados.
Inferir a partir de uma amostra é chute. O ponto desta página é que os chutes ficam visíveis.
Campos opcionais, que é onde a maioria dos geradores falha
Um gerador que lê o elemento zero de um array e para produz uma interface em que todo campo é obrigatório. O primeiro registro que omite um campo opcional então falha na checagem de tipos, e você acaba editando os tipos gerados à mão, o que derruba o propósito da coisa.
Este mescla todos os elementos. Uma chave presente em todos é obrigatória; uma chave presente em alguns é marcada como opcional com um ponto de interrogação. Isso é informação de verdade, extraída da sua amostra, que um gerador de um elemento só joga fora.
As outras decisões
- null vira uma união
- Um campo visto como string e como null é string | null, não any e não string.
- Um array vazio é unknown[]
- Não any[]. Um array vazio não carrega informação de tipo, e any[] desligaria em silêncio a checagem para tudo que encostasse nele.
- Formatos repetidos são deduplicados
- Uma lista de quinhentos registros produz uma interface, não quinhentas.
- Nomes de elemento de array vão para o singular
- Um array categories produz uma interface Category.
- Identificadores inválidos ganham aspas
- Uma chave has-dash, 2fast ou class vira um nome de propriedade entre aspas.
- Inteiros inseguros são sinalizados
- Um campo tipado como number quando a amostra tinha um inteiro acima de 2^53-1 é mentira, porque o JavaScript não consegue representá-lo. A nota diz isso; a correção certa é lá atrás, mandando como string.
O que um tipo gerado não te dá
Uma interface TypeScript é apagada em tempo de execução. Ela diz ao compilador o que você espera e não faz absolutamente nada quando a API manda outra coisa. Para isso você precisa de um validador em tempo de execução, e o fluxo honesto para uma API externa é um schema que valida e infere o tipo a partir da mesma definição.
Zod, Valibot e ArkType fazem isso. Gere uma interface aqui para entender um payload, e depois escreva o schema de execução para a fronteira que você não controla.
How to do this in code
A mesma ideia em código, e o que usar em uma fronteira em que você não confia.
sh quicktype
O quicktype suporta várias linguagens de destino. Passar várias amostras é a opção que realmente importa.
npx quicktype --lang ts --just-types --src-lang json payload.json
# Several samples, which is what makes optionality accurate
npx quicktype --lang ts --just-types samples/*.json ts Zod
Este é o padrão para a fronteira de uma API. A interface conta para o compilador; o schema diz a verdade.
import { z } from 'zod';
const User = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
verifiedAt: z.string().nullable(),
roles: z.array(z.string()),
});
// One definition, both a runtime check and a static type
type User = z.infer<typeof User>;
const result = User.safeParse(await res.json());
if (!result.success) console.error(result.error.issues); ts Só tipos, a partir de um literal
// If the data is a constant you control, TypeScript can infer
// the type without a generator at all.
const config = {
retries: 3,
endpoints: ['a', 'b'],
} as const;
type Config = typeof config; Perguntas frequentes
- Por que um campo saiu opcional se a minha API sempre manda?
- Porque pelo menos um registro da amostra não tinha esse campo. Isso é ou um campo opcional de verdade ou uma amostra incompleta. Cole um array com mais registros e a resposta melhora.
- Devo usar interface ou type?
- Para formatos de objeto quase não muda nada. Interfaces suportam declaration merging e produzem mensagens de erro um pouco melhores; aliases de tipo conseguem expressar uniões e tipos mapeados. Os dois estão disponíveis acima.
- Esses tipos validam alguma coisa em tempo de execução?
- Não. Tipos do TypeScript são apagados na compilação. Eles descrevem o que você acredita; não conferem. Para dados que atravessam uma fronteira de rede, use um validador em tempo de execução.