Skip to content
Back to Blog
developerjson-formattertypescriptweb-development

Convertir du JSON en types TypeScript

Coller du JSON dans un générateur de types est facile ; obtenir des champs optionnels et des types union corrects ne l'est pas. Voici comment faire correctement, plus un convertisseur gratuit dans le navigateur.

SZ
Founder, Molixa
11 min read
Partager
Convertir du JSON en types TypeScript
Table of contents7 sections

Pour convertir du JSON en TypeScript, associez chaque valeur JSON à son type : les chaînes deviennent string, les nombres number, les objets des définitions interface imbriquées, et les tableaux T[]. Les difficultés sont l'inférence des champs optionnels ou obligatoires, la fusion de tableaux mixtes en types union, et la décision d'ajouter une validation d'exécution avec Zod.

La génération automatique gère les 90% ennuyeux. Les 10% restants, là où un convertisseur naïf se trompe, sont source de bugs. Un seul échantillon API ne peut pas vous dire quels champs sont nullables, parfois absents, ou si un tableau vide est string[] ou never[]. Ce guide explique les mécanismes et les pièges, puis montre comment générer l'interface, un schéma Zod et une structure Go à partir d'un seul collage.

The Basic Mapping: JSON Values to TypeScript Types#

Start with a concrete API response. Say you are integrating a user endpoint:

{
  "id": 4821,
  "username": "ada",
  "email": "[email protected]",
  "isActive": true,
  "roles": ["admin", "editor"],
  "profile": {
    "displayName": "Ada Lovelace",
    "avatarUrl": null
  },
  "lastLoginAt": "2026-05-30T11:04:00Z"
}

A direct, correct translation looks like this:

interface User {
  id: number;
  username: string;
  email: string;
  isActive: boolean;
  roles: string[];
  profile: Profile;
  lastLoginAt: string;
}

interface Profile {
  displayName: string;
  avatarUrl: string | null;
}

A few decisions are already baked in here that a careless generator would miss. Notice avatarUrl is string | null, not string, because the sample value is null. Notice lastLoginAt is string, not Date, because JSON has no date type, it is just an ISO string until you parse it. And profile was extracted into its own named Profile interface instead of being inlined, which keeps the types reusable.

The core mapping table is short:

JSONTypeScriptWatch out for
"text"stringISO dates are still string
42, 3.14numberNo int vs float distinction
true / falseboolean
nullnullUsually part of a union, e.g. string | null
{ ... }interface / nested objectExtract reused shapes into named interfaces
[ ... ]T[]Mixed-type arrays become a union; empty arrays are ambiguous

Interface vs Type Alias : lequel générer#

interface et type peuvent tous deux décrire une forme d'objet, et pour des réponses API simples, ils sont presque interchangeables. Les conseils pratiques :

  • Utilisez interface pour les formes d'objet que vous pourriez étendre ou qui représentent un contrat API. Les interfaces prennent en charge la fusion de déclarations et produisent des messages d'erreur plus clairs.
  • Utilisez type lorsque vous avez besoin d'unions, d'intersections, de types mappés ou de tuples qu'une interface ne peut pas exprimer.

Pour les modèles dérivés de JSON, optez par défaut pour interface. Vous n'utilisez type que lorsque les données elles-mêmes sont une union, comme un champ qui est "en attente" | "terminé". La plupart des générateurs vous permettent de choisir le style de sortie, et interface est le choix par défaut le plus sûr pour une forme d'API externe.

Les trois pièges que les générateurs à échantillon unique ratent#

C'est là que la plupart des convertisseurs en ligne échouent. Ils traduisent exactement ce que vous collez et rien de plus, donc les types ne sont aussi corrects que votre unique échantillon.

Piège 1 : Champs optionnels vs obligatoires#

Une seule réponse ne peut pas vous dire si un champ est optionnel. Si avatarUrl est présent dans votre échantillon mais que l'API l'omet pour les utilisateurs qui n'en ont jamais défini, un générateur le marque comme obligatoire et votre code plante à l'exécution lorsqu'il est absent.

Vous avez deux options honnêtes. Soit fournir plusieurs échantillons au générateur pour qu'il puisse voir quelles clés disparaissent, soit marquer les champs comme optionnels manuellement en vous basant sur la documentation de l'API :

interface User {
  id: number;
  username: string;
  email: string;
  isActive: boolean;
  roles: string[];
  profile: Profile;
  lastLoginAt?: string; // optionnel : absent pour les utilisateurs qui ne se sont jamais connectés
}

Le ? rend la propriété string | undefined. C'est différent de string | null. null signifie que la clé est présente avec une valeur nulle ; undefined signifie que la clé peut être totalement absente. Confondre les deux est une source classique d'erreurs cannot read property of undefined.

Piège 2 : Types unions à partir de tableaux hétérogènes#

Les tableaux réels ne sont pas toujours homogènes. Prenons un flux d'événements :

{
  "events": [
    { "type": "click", "x": 120, "y": 44 },
    { "type": "scroll", "delta": -300 }
  ]
}

Un générateur faible soit prend la forme du premier élément et ignore le reste, soit fusionne tous les champs en un seul objet gonflé avec tout optionnel. La sortie correcte est une union discriminée :

type AppEvent =
  | { type: "click"; x: number; y: number }
  | { type: "scroll"; delta: number };

interface EventPayload {
  events: AppEvent[];
}

Le champ partagé type est le discriminant. TypeScript peut maintenant réduire l'union dans un switch (event.type), ce qu'une interface unique fusionnée ne permettrait jamais.

Piège 3 : Tableaux vides et champs uniquement nuls#

Quel type pour "tags": [] ? Il n'y a aucun élément à déduire, donc la réponse honnête est "inconnu." Les outils naïfs émettent any[] ou never[], tous deux faux en pratique. Le même problème touche un champ dont la seule valeur d'échantillon est null : vous ne pouvez pas connaître le type non nul à partir de null seul. Lorsque vous rencontrez ces cas, fournissez un échantillon avec des données, ou annotez le type vous-même (tags: string[]) d'après ce que vous savez que l'API renvoie.

Quand vous avez aussi besoin de Zod (validation à l'exécution)#

Les types TypeScript disparaissent à la compilation. Ils ne vous protègent en rien contre une API qui renvoie en réalité quelque chose de différent de ce que vous avez typé. Si le serveur envoie une chaîne là où vous attendiez un nombre, TypeScript a déjà fait confiance à la mauvaise forme et votre application échoue en aval avec une erreur confuse.

Zod comble cette lacune. Vous définissez un schéma une fois, validez la réponse à la frontière et inférez le type statique à partir du même schéma, sans jamais l'écrire deux fois :

import { z } from "zod";

const ProfileSchema = z.object({
  displayName: z.string(),
  avatarUrl: z.string().url().nullable(),
});

const UserSchema = z.object({
  id: z.number().int(),
  username: z.string(),
  email: z.string().email(),
  isActive: z.boolean(),
  roles: z.array(z.string()),
  profile: ProfileSchema,
  lastLoginAt: z.string().datetime().optional(),
});

// Le type statique est dérivé du schéma, non écrit à la main :
type User = z.infer<typeof UserSchema>;

// À la frontière réseau :
const user = UserSchema.parse(await response.json());

Maintenant, UserSchema.parse() lève une erreur précise et lisible dès que les données violent le contrat, et z.infer maintient le type TypeScript parfaitement synchronisé. Utilisez Zod (ou un équivalent comme Valibot) chaque fois que des données traversent une frontière de confiance : réponses HTTP, saisie de formulaire, webhooks, files d'attente de messages, tout ce que vous n'avez pas produit vous-même. Pour les données internes, entièrement typées et que vous contrôlez de bout en bout, les simples interfaces suffisent.

Règle empirique : si le JSON vient de l'extérieur de votre codebase, validez-le à l'exécution. Les seuls types sont une promesse, pas une garantie.

Besoin d'une structure Go à la place ?#

Les équipes backend ont souvent besoin de la même forme en Go. La correspondance reflète TypeScript, avec des balises de structure portant les noms de clés JSON :

type Profile struct {
	DisplayName string  `json:"displayName"`
	AvatarURL   *string `json:"avatarUrl"`
}

type User struct {
	ID          int      `json:"id"`
	Username    string   `json:"username"`
	Email       string   `json:"email"`
	IsActive    bool     `json:"isActive"`
	Roles       []string `json:"roles"`
	Profile     Profile  `json:"profile"`
	LastLoginAt string   `json:"lastLoginAt"`
}

Notez le pointeur *string pour avatarUrl : en Go, un pointeur est la façon de représenter un champ nullable, car la valeur zéro de string est "", pas nil. La même question de nullabilité du côté TypeScript refait surface ici sous une forme différente.

Générez-le sans le coller sur un site aléatoire#

Faire cela manuellement pour une charge utile volumineuse est fastidieux et sujet aux erreurs, mais coller du JSON de production, qui peut contenir des jetons, des e-mails ou des données clients, sur un service distant inconnu est pire. Un convertisseur respectueux de la vie privée effectue la transformation entièrement dans votre navigateur, de sorte que les données ne touchent jamais un serveur.

Étape 1 : Collez et validez le JSON#

Déposez votre réponse API dans un formateur et convertisseur JSON gratuit. Il valide d'abord le JSON et l'affiche joliment, afin que vous repériez une virgule finale ou une clé non citée avant même de penser aux types. Un JSON mal formé est la raison la plus courante pour laquelle une conversion produit silencieusement des déchets.

Étape 2 : Choisissez votre cible de sortie#

Choisissez le format dont vous avez besoin : une interface TypeScript, un schéma Zod ou une structure Go. Comme le convertisseur JSON vers TypeScript s'exécute côté client, vous pouvez en toute sécurité y jeter des réponses réelles non expurgées sans vous soucier de la destination des données. Toute la transformation se produit dans l'onglet.

Étape 3 : Affinez manuellement les champs optionnels et les unions#

La génération vous donne un squelette correct à partir de l'échantillon. Appliquez maintenant les trois pièges : marquez les clés vraiment optionnelles avec ?, élargissez les champs uniquement null ou les tableaux vides à leurs types réels, et convertissez les tableaux d'objets mixtes en unions discriminées. Ces 10% finaux sont un jugement que l'outil ne peut pas prendre à partir d'une seule charge utile, et c'est ce qui sépare les types qui compilent de ceux qui correspondent réellement à l'API.

Lorsque votre flux de travail implique plus que des types, la même boîte à outils vous aide : validez les jetons avec les outils décodeur JWT adjacents, testez les modèles d'extraction dans le testeur d'expressions régulières ou gérez les charges utiles encodées avec l'encodeur et décodeur Base64. Pour un aperçu plus approfondi des flux de travail JSON quotidiens, consultez notre guide sur pourquoi un formateur JSON est un outil de développeur quotidien.

Foire aux questions#

Comment convertir du JSON en interface TypeScript ? Mappez chaque valeur JSON à son équivalent TypeScript : les chaînes en string, les nombres en number, les objets en interfaces imbriquées et les tableaux en T[]. Extrayez les formes d'objets réutilisées dans des interfaces nommées. Le chemin le plus rapide et fiable consiste à coller le JSON dans un convertisseur, puis à corriger manuellement les champs optionnels, les unions null et les tableaux mixtes que l'échantillon ne peut pas révéler.

Dois-je utiliser une interface ou un alias de type pour les données JSON ? Par défaut, utilisez interface pour les formes d'objets provenant d'une API, car les interfaces s'étendent proprement et donnent des messages d'erreur plus clairs. Utilisez un alias type lorsque les données sont elles-mêmes une union, une intersection ou un tuple qu'une interface ne peut pas exprimer, comme un champ de statut qui est "en attente" | "terminé".

Comment gérer les champs optionnels lors de la génération de types à partir de JSON ? Un seul échantillon ne peut pas révéler les champs optionnels, donc un générateur marque tout comme obligatoire. Soit fournissez plusieurs réponses pour qu'il voie quelles clés disparaissent, soit ajoutez vous-même le modificateur ? en vous basant sur la documentation de l'API. Rappelez-vous que field?: string (peut être absent) diffère de field: string | null (présent mais nul).

Ai-je besoin de Zod si j'ai déjà des types TypeScript ? Oui, dès que les données traversent une frontière de confiance. Les types TypeScript sont effacés à la compilation et ne peuvent pas valider ce qu'une API renvoie réellement à l'exécution. Zod valide la charge utile réelle et vous permet d'inférer le type statique à partir du même schéma avec z.infer, de sorte que le type et la vérification à l'exécution ne dérivent jamais.

Est-il sûr de convertir du JSON en TypeScript en ligne ? Seulement si le convertisseur s'exécute dans votre navigateur. De nombreux outils en ligne envoient votre JSON collé à un serveur, ce qui est risqué lorsque la charge utile contient des jetons, des e-mails ou des données clients. Un convertisseur côté client comme le formateur JSON Molixa effectue toute la transformation localement, de sorte que les données ne quittent jamais votre onglet.

Comment convertir des objets JSON imbriqués en TypeScript ? Extrayez chaque objet imbriqué dans sa propre interface nommée et référencez-la depuis le parent, plutôt que de tout intégrer profondément. Pour l'exemple utilisateur, profile devient une interface Profile séparée que User référence. Les interfaces nommées sont réutilisables, produisent des messages d'erreur plus courts et rendent les types générés beaucoup plus faciles à lire.

developerjson-formattertypescriptweb-development

More from Molixa

Try Molixa Tools

50+ free AI tools for content creation, SEO, coding, and more. No signup, no watermark.

Explore all tools
Convertisseur JSON vers TypeScript (gratuit) | Molixa | Molixa