ToolPal
Code TypeScript sur un écran sombre avec une coloration syntaxique bleue et orange

Arrêtez d'écrire des interfaces TypeScript à la main : utilisez un générateur JSON

📷 Roman Synkevych / Pexels

Arrêtez d'écrire des interfaces TypeScript à la main : utilisez un générateur JSON

Écrire manuellement des interfaces TypeScript à partir de payloads JSON est fastidieux et source d'erreurs. Voici comment l'automatiser et à quoi faire attention.

DPar Daniel Park7 avril 20266 min de lecture

Si vous avez déjà passé vingt minutes à écrire à la main des interfaces TypeScript à partir d'un payload JSON reçu d'une API, vous savez déjà que c'est l'une de ces tâches qui semblent importantes mais qui sont presque entièrement mécaniques. Vous ne pensez pas. Vous copiez simplement des noms de champs et inférez des types. C'est le genre de travail qu'une machine devrait faire.

Et pourtant, beaucoup de développeurs le font encore à la main. Ce guide explique pourquoi cela vaut la peine d'arrêter, ce qu'un générateur JSON vers TypeScript produit réellement, et — plus important — ce qu'il ne peut pas faire pour que vous sachiez où prendre le relais.

Pourquoi les interfaces TypeScript comptent vraiment

Avant d'entrer dans l'outil, il vaut la peine d'être précis sur ce qu'on obtient des interfaces typées au-delà de "détecter les bugs".

L'autocomplétion IDE est la plus sous-estimée. Quand votre réponse d'API est typée, votre éditeur sait exactement quels champs existent et quelle forme ont les objets imbriqués. Vous arrêtez de deviner si c'est user.profilePicture ou user.profile_picture ou user.avatar.

Le refactoring devient beaucoup plus sûr. Si une équipe backend renomme un champ de userId en user_id, chaque endroit dans votre base de code qui référence l'ancien nom échoue à la compilation — pas silencieusement à l'exécution après qu'un utilisateur rencontre une erreur.

Une documentation qui ne se périme pas. Une interface bien nommée est souvent plus utile qu'une documentation écrite.

Le processus manuel vs. l'utilisation d'un générateur

Voici à quoi ressemble l'écriture de types à la main pour une réponse d'API de complexité moyenne :

{
  "user": {
    "id": 1042,
    "email": "alice@example.com",
    "name": "Alice Nguyen",
    "roles": ["admin", "editor"],
    "profile": {
      "bio": "Frontend developer based in Berlin.",
      "avatarUrl": "https://cdn.example.com/avatars/1042.png",
      "joinedAt": "2023-06-15T08:30:00Z"
    },
    "settings": {
      "theme": "dark",
      "notifications": {
        "email": true,
        "push": false
      }
    }
  },
  "meta": {
    "requestId": "abc-123",
    "timestamp": 1712486400
  }
}

Collez le même JSON dans l'outil JSON vers TypeScript et vous obtenez ceci en moins d'une seconde :

export interface Root {
  user: User;
  meta: Meta;
}

export interface User {
  id: number;
  email: string;
  name: string;
  roles: string[];
  profile: Profile;
  settings: Settings;
}

export interface Profile {
  bio: string;
  avatarUrl: string;
  joinedAt: string;
}

export interface Settings {
  theme: string;
  notifications: Notifications;
}

export interface Notifications {
  email: boolean;
  push: boolean;
}

export interface Meta {
  requestId: string;
  timestamp: number;
}

Tout ce que vous avez à faire c'est renommer Root en quelque chose de significatif comme UserResponse.

Cas d'utilisation réels

Typage des réponses d'API

C'est le cas d'utilisation principal. Vous intégrez une API tierce — processeur de paiement, CRM, service météo — et avez besoin de types pour ce qui revient.

Fichiers de configuration

Si votre application lit un fichier de configuration JSON à l'exécution, vous voulez une interface TypeScript correspondante :

// config.interface.ts (généré à partir de config.json)
export interface AppConfig {
  database: Database;
  redis: Redis;
  featureFlags: FeatureFlags;
}

export interface Database {
  host: string;
  port: number;
  name: string;
  ssl: boolean;
}

Données de mock pour les tests

Lors de l'écriture de tests, vous avez souvent besoin d'objets mock typés. Générez l'interface à partir de données réelles, puis créez votre mock typé dessus.

Gestion des cas délicats

Valeurs null

JSON autorise null comme valeur, et les générateurs typisent ces champs comme null. Mais en pratique, un champ null signifie généralement que le champ est optionnel :

interface User {
  middleName: string | null;
}

Dates

JSON n'a pas de type Date natif. "2023-06-15T08:30:00Z" est une string du point de vue de JSON. Certaines équipes créent un alias de type :

type ISODateString = string;

Unions discriminées

Parfois une API retourne différentes formes selon un champ type ou status. Vous devrez écrire vous-même ces types :

type ApiResult = SuccessResult | ErrorResult;

interface SuccessResult {
  type: "success";
  data: OrderData;
}

interface ErrorResult {
  type: "error";
  code: string;
  message: string;
}

Meilleures pratiques pour les types générés

Nommer l'interface racine de façon significative

Le générateur la nommera Root ou quelque chose de générique. Renommez-la toujours avant de commiter. UserProfileResponse, CheckoutSessionPayload, ProductListItem.

Conserver les types dans des fichiers dédiés

src/
  types/
    api/
      user.types.ts
      order.types.ts
    config.types.ts

Zod pour la validation à l'exécution

Les types TypeScript sont effacés à l'exécution — ils ne vous protègent pas si une API retourne réellement des données inattendues. Si vous avez besoin de garanties à l'exécution, envisagez Zod :

import { z } from "zod";

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

type User = z.infer<typeof UserSchema>;

Ce que le générateur ne peut pas faire pour vous

Il ne connaît pas votre logique métier. Un champ typé comme number pourrait n'être en pratique qu'un entier positif.

Il travaille à partir d'un instantané. Les types générés reflètent un échantillon de données. Les APIs réelles évoluent.

Il ne peut pas distinguer requis et optionnel. Chaque champ dans l'exemple est traité comme requis.

Il traite toutes les chaînes comme des chaînes. Un champ status qui ne contient que "pending", "active" ou "cancelled" sera typé comme string plutôt que comme le type union littéral plus précis.

Ce ne sont pas des raisons d'éviter l'outil — ce sont des raisons de traiter la sortie comme un brouillon, pas un produit fini. Le générateur gère 80% du travail fastidieux. Vous gérez les 20% qui nécessitent de comprendre la sémantique réelle des données.

Tout mettre ensemble

Le workflow qui a du sens pour la plupart des projets :

  1. Obtenir un vrai (ou représentatif) exemple de JSON depuis l'API, la configuration ou une autre source
  2. Coller dans le générateur JSON vers TypeScript
  3. Renommer Root en quelque chose de significatif
  4. Copier la sortie dans le fichier *.types.ts approprié
  5. Passer en revue chaque champ : marquer les champs optionnels avec ?, ajouter | null où nécessaire, convertir les chaînes littérales en types union là où c'est approprié
  6. Si votre JSON source est minifié et difficile à lire, utilisez le formateur JSON d'abord, puis générez les types
  7. Si vous maintenez aussi une configuration YAML, le convertisseur JSON vers YAML peut aider à les synchroniser

L'objectif est d'avoir des types TypeScript précis, nommés et organisés sans passer de temps en transcription purement mécanique. Le générateur fait la partie mécanique. Vous apportez le contexte sur ce que les données signifient réellement.

Les types écrits à la main ne sont pas intrinsèquement meilleurs — ils sont juste plus lents et plus susceptibles d'avoir des fautes de frappe. Utilisez l'outil, passez la sortie en revue, et consacrez votre temps aux parties qui nécessitent vraiment un humain.

Questions Fréquentes

D

À propos de l'auteur

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

En savoir plus

Partager

XLinkedIn

Articles associés