Pular para o conteúdo
Tutorial

Pare de escrever interfaces TypeScript manualmente: gere-as automaticamente a partir de JSON

| 5 min read

Use a API Botoi JSON para TypeScript para gerar interfaces TypeScript precisas e esquemas Zod a partir de qualquer carga JSON em uma única solicitação POST.

TypeScript interface definition in an editor
Photo by Safar Safarov on Unsplash

Cada vez que você integra uma nova API, você acaba olhando para uma resposta JSON e digitando uma interface manualmente. Campo por campo. Adivinhar quais valores são opcionais. Esquecendo isso created_at é uma string, não uma data. Copiar e colar documentos que podem ou não corresponder à resposta real.

Isso é tedioso, lento e uma fonte confiável de bugs. O JSON já contém todos os tipos que você precisa. Uma única chamada de API pode extraí-los.

Uma solicitação POST, uma interface TypeScript

Envie qualquer objeto JSON para o Botoi json-to-typescript endpoint com um nome para a interface raiz. A API retorna a interface TypeScript completa como uma string.

curl -X POST https://api.botoi.com/v1/schema/json-to-typescript \\
  -H "Content-Type: application/json" \\
  -d '{
    "json": {
      "id": 1,
      "name": "Acme Corp",
      "active": true,
      "tags": ["saas", "b2b"]
    },
    "name": "Company"
  }'

Resposta:

{
  "success": true,
  "data": {
    "typescript": "interface Company {\\n  id: number;\\n  name: string;\\n  active: boolean;\\n  tags: string[];\\n}",
    "name": "Company"
  }
}

A interface gerada, formatada:

interface Company {
  id: number;
  name: string;
  active: boolean;
  tags: string[];
}

A API infere number, string, boolean, e string[] dos valores. Nenhuma anotação manual. Sem adivinhação.

Crie um script de tipos da API para o seu projeto

Digitar interfaces manualmente é uma solução única. A melhor abordagem: um script que busca respostas de API ao vivo e gera arquivos de tipo que você pode enviar para seu repositório.

Aqui está um script bash que gera tipos TypeScript a partir de qualquer URL:

#!/bin/bash
set -euo pipefail

API="https://api.botoi.com/v1/schema/json-to-typescript"
OUT_DIR="./src/types/generated"
mkdir -p "\$OUT_DIR"

generate_type() {
  local url="\$1"
  local name="\$2"
  local file="\$3"

  echo "Fetching \$url ..."
  local json
  json=\$(curl -s "\$url")

  echo "Generating \$name interface..."
  local result
  result=\$(curl -s -X POST "\$API" \\
    -H "Content-Type: application/json" \\
    -d "{\"json\": \$json, \"name\": \"\$name\"}")

  echo "\$result" | jq -r '.data.typescript' > "\$OUT_DIR/\$file"
  echo "Wrote \$OUT_DIR/\$file"
}

generate_type "https://api.github.com/users/octocat" "GitHubUser" "github-user.ts"
generate_type "https://jsonplaceholder.typicode.com/posts/1" "BlogPost" "blog-post.ts"

echo "Done. All types written to \$OUT_DIR/"

Execute este script durante o desenvolvimento ou como um gancho de pré-confirmação. Quando a API upstream muda, execute novamente o script e seus tipos permanecerão precisos.

Se você preferir Node.js em vez de bash:

import { writeFileSync, mkdirSync } from "fs";

const API = "https://api.botoi.com/v1/schema/json-to-typescript";

async function generateType(json: unknown, name: string): Promise<string> {
  const res = await fetch(API, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ json, name }),
  });
  const data = await res.json();
  return data.data.typescript;
}

async function main() {
  const userRes = await fetch("https://api.github.com/users/octocat");
  const userJson = await userRes.json();

  const typescript = await generateType(userJson, "GitHubUser");

  mkdirSync("./src/types/generated", { recursive: true });
  writeFileSync("./src/types/generated/github-user.ts", typescript);
  console.log("Wrote ./src/types/generated/github-user.ts");
}

main();

Exemplo real: gerar tipos para a resposta do usuário da API GitHub

O GitHub /users/:username endpoint retorna mais de 30 campos. Escrevendo essa interface manualmente leva minutos e convida a erros de digitação. Aqui está a abordagem em duas etapas:

# Fetch the GitHub user JSON
GITHUB_JSON=\$(curl -s https://api.github.com/users/octocat)

# Send it to the Botoi API
curl -s -X POST https://api.botoi.com/v1/schema/json-to-typescript \\
  -H "Content-Type: application/json" \\
  -d "{\"json\": \$GITHUB_JSON, \"name\": \"GitHubUser\"}" \\
  | jq -r '.data.typescript'

Saída:

interface GitHubUser {
  login: string;
  id: number;
  node_id: string;
  avatar_url: string;
  gravatar_id: string;
  url: string;
  html_url: string;
  followers_url: string;
  following_url: string;
  gists_url: string;
  starred_url: string;
  subscriptions_url: string;
  organizations_url: string;
  repos_url: string;
  events_url: string;
  received_events_url: string;
  type: string;
  site_admin: boolean;
  name: string;
  company: string;
  blog: string;
  location: string;
  bio: string;
  twitter_username: string;
  public_repos: number;
  public_gists: number;
  followers: number;
  following: number;
  created_at: string;
  updated_at: string;
}

São 32 campos, digitados corretamente, em menos de um segundo. Canalize a saída em um arquivo e você terá uma definição de tipo pronta para produção.

Em vez disso, gere esquemas Zod

As interfaces TypeScript oferecem segurança em tempo de compilação, mas desaparecem em tempo de execução. Se você precisar de validação em tempo de execução, o json-to-zod endpoint gera um esquema Zod a partir da mesma entrada JSON.

curl -s -X POST https://api.botoi.com/v1/schema/json-to-zod \\
  -H "Content-Type: application/json" \\
  -d '{
    "json": {
      "id": 1,
      "name": "Acme Corp",
      "active": true,
      "tags": ["saas", "b2b"]
    },
    "name": "Company"
  }' | jq -r '.data.zod'

Saída:

import { z } from "zod";

const Company = z.object({
  id: z.number(),
  name: z.string(),
  active: z.boolean(),
  tags: z.array(z.string()),
});

Coloque o esquema gerado em sua base de código e você obterá validação de tempo de execução e inferência de tipo:

import { z } from "zod";

const Company = z.object({
  id: z.number(),
  name: z.string(),
  active: z.boolean(),
  tags: z.array(z.string()),
});

type Company = z.infer<typeof Company>;

const parsed = Company.parse(apiResponse);
// parsed is fully typed and validated at runtime

Com o Zod, dados inválidos são lançados no limite em vez de causar bugs silenciosos na lógica do seu aplicativo.

Quando usar cada endpoint

Cenário Ponto final Por que
Respostas internas da API em que você confia json-to-typescript Leve; sem custo de tempo de execução
Respostas externas da API json-to-zod Valida dados no limite
Entradas de formulário ou dados enviados pelo usuário json-to-zod Analise, não valide
Prototipagem rápida json-to-typescript Caminho mais rápido para código digitado
Geração de tipo de pipeline de CI Qualquer Ambos produzem resultados determinísticos

Pontos-chave

  • Uma solicitação substitui a digitação manual. Envie JSON, obtenha de volta uma interface TypeScript ou esquema Zod.
  • Automatize-o. Adicione um script ao seu projeto que regenera tipos sempre que as APIs upstream mudam.
  • Nenhuma conta é necessária. O nível gratuito permite 5 solicitações por minuto sem inscrição.
  • Funciona com qualquer fonte JSON. APIs REST, arquivos de configuração, exportações de banco de dados, cargas úteis de webhook.

O documentação completa da API capa pontos de extremidade de esquema adicionais, incluindo json-to-jsonschema para saída do esquema JSON.

FAQ

Quais estruturas JSON a API suporta?
A API lida com objetos aninhados, matrizes, matrizes de tipo misto, nulos e estruturas profundamente aninhadas. Ele infere o tipo TypeScript correto para cada valor, incluindo campos opcionais quando nulo está presente.
Preciso de uma chave de API?
Não. O acesso anônimo é permitido a 5 solicitações por minuto com limitação de taxa baseada em IP. Para volumes maiores, inscreva-se para obter uma chave de API em botoi.com/api.
Posso gerar esquemas Zod em vez de interfaces TypeScript?
Sim. Envie o mesmo corpo JSON para POST https://api.botoi.com/v1/schema/json-to-zod e você obterá uma string de esquema Zod que pode inserir em seu projeto.
Como a API lida com arrays com tipos mistos?
Se uma matriz contiver valores de tipos diferentes, a API produzirá um tipo de união. Por exemplo, um array com strings e números torna-se (string | number)[].
Posso usar isso em um pipeline de CI?
Sim. A API é um endpoint HTTP POST padrão. Chame-o de qualquer script de shell, ação do GitHub ou etapa de construção para manter suas definições de tipo sincronizadas com as respostas da API upstream.

Comece a construir com botoi

150+ endpoints de API para consultas, processamento de texto, geração de imagens e utilitários para desenvolvedores. Plano gratuito, sem cartão de crédito.