Aller au contenu principal

Convertir JSON en TypeScript

JSON vers TypeScript génère des interfaces à partir d’un document d’exemple, dans votre navigateur. Collez tous les enregistrements que vous avez plutôt qu’un seul : un champ qui apparaît dans certains enregistrements et pas dans d’autres n’est détectable qu’en comparant les échantillons, et il devient un membre optionnel plutôt qu’un champ requis absent à l’exécution.

100 % local
Structure
Exemple de JSON
0 B1 ligneLig. 1, Col. 1
Erreur de syntaxe · Erreur à la ligne 1, colonne 1

Le document s’arrête trop tôt — il semble tronqué.


^
Code générélecture seule
0 B1 ligne
Si vous en avez, collez plusieurs enregistrements. Cela permet de repérer les champs facultatifs absents de certaines lignes.

Comment fonctionne Convertir JSON en TypeScript ?

Le générateur construit un modèle de types intermédiaire à partir de votre échantillon puis le rend, ce qui ressemble à un détail d’implémentation et est la raison pour laquelle la sortie est correcte. Les décisions réellement difficiles — ce champ est-il optionnel, ces deux objets sont-ils du même type, quel est le type d’élément d’un tableau mixte — reçoivent une réponse unique, en un seul endroit, plutôt que d’être redérivées à chaque valeur rencontrée.

Les champs optionnels viennent des désaccords entre enregistrements

Avec [{"a":1}, {"a":1,"b":2}], l’implémentation évidente lit le premier élément et produit { a: number }, en perdant b en silence. La bonne réponse fusionne les ensembles de champs de chaque élément : a est dans les deux donc il est requis, b n’est que dans l’un donc il est b?: number. C’est la plus grande différence entre générateurs, et c’est pourquoi coller un seul enregistrement produit un type qui décrit un enregistrement plutôt que votre API.

Les formes identiques deviennent un type, pas cinquante

Chaque objet reçoit une empreinte de sa structure — noms de clés, optionalité, et empreinte de chaque type de valeur, indépendamment de l’ordre. Un document avec cinquante clients, chacun portant une adresse de même forme, produit une seule interface Address plutôt que Address jusqu’à Address50. Les noms viennent de la clé qui contenait l’objet, mis au singulier quand elle contenait un tableau, si bien que "users": [{…}] génère User.

null est une nullabilité, pas un type

Quand un champ est un nombre dans un enregistrement et null dans un autre, la sortie est number | null plutôt qu’un type union avec un nom généré. Quand un champ est null dans tous les enregistrements, la réponse honnête est unknown avec un commentaire qui le dit — émettre null serait exact vis-à-vis de votre échantillon et inutile vis-à-vis de vos données.

Les nombres sont des nombres, avec une note

TypeScript n’a qu’un seul type numérique, donc les entiers et les flottants deviennent tous deux number. Un entier trop grand pour un type 32 bits est quand même signalé dans un commentaire, car le même modèle alimente les générateurs Go, Java et C# où cette distinction décide entre int et int64 — et parce qu’un identifiant 64 bits qui arrive jusqu’à JavaScript mérite qu’on le sache.

Exemple

[
  { "id": 1, "name": "Ada", "deleted_at": null },
  { "id": 2, "name": "Grace", "deleted_at": null, "team": "ops" }
]

Généré

export interface User {
  id: number;
  name: string;
  deleted_at: unknown; // only null in the sample
  team?: string;
}

Quelles options et quels cas limites Convertir JSON en TypeScript prend en charge ?

Référence technique et options
ParamètreTypeValeur par défautComportement et cas limites
Type racineidentifiantRootNom du type de niveau supérieur. Une racine de tableau est signalée sous la forme Nom[], et les formes d’objets à l’intérieur sont nommées d’après les clés qui les contiennent.
interface / typedéclarationinterfaceLes interfaces supportent la fusion de déclarations et produisent de meilleurs messages d’erreur sur les formes d’objets ; les alias de type sont nécessaires si vous voulez ensuite des unions ou des types mappés. Les deux sont valides ici.
readonlybooléenoffMarque chaque membre comme readonly. Vaut le coup d’activer pour une réponse d’API parsée, qui ne devrait pas être mutée en place par votre code.
clés camelCasebooléenoffRenomme les clés snake_case et enregistre l’original dans un commentaire en fin de ligne. N’est correct que si quelque chose dans votre pipeline les renomme réellement — le type généré ne correspondrait sinon plus au JSON.
Optionnalitédéduitesur tous les enregistrementsUne clé absente d’au moins un enregistrement de même forme devient optionnelle. Collez plusieurs enregistrements ; un seul enregistrement ne peut exprimer cela.
Nullabledéduiteunion avec nullUne valeur qui est null dans certains enregistrements et une chaîne dans d’autres devient string | null. Absent et null sont des choses différentes et sont signalées différemment.
Tableaux mixtesunionentre parenthèsesUn tableau de scalaires mélangés devient (string | number)[]. Les parenthèses comptent : string | number[] signifie tout autre chose.
Taille d’entréebytes2 MBL’inférence lit chaque valeur. Quelques centaines d’enregistrements représentatifs décrivent une forme aussi bien qu’un million, donc le plafond ne coûte rien en pratique.

Questions fréquentes

Pourquoi un champ est-il optionnel alors que mon API l’envoie toujours ?

Parce qu’au moins un enregistrement de l’échantillon que vous avez collé ne l’avait pas. Le générateur ne peut décrire que les données qu’on lui a données. Si le champ est réellement toujours présent, collez un échantillon où il apparaît toujours — ou retirez le ? à la main, ce qui est le bon choix quand vous connaissez le contrat mieux que l’échantillon.

Dois-je coller un seul enregistrement ou toute la réponse ?

Toute la réponse, et idéalement plusieurs. L’optionalité, la nullabilité et les types mixtes sont des propriétés de l’ensemble des enregistrements, pas d’un seul. Un générateur nourri d’un seul enregistrement ne peut pas distinguer un champ toujours présent d’un champ qui se trouvait être présent cette fois-là, et il produira avec assurance un type faux de la manière la plus difficile à remarquer.

Pourquoi ai-je obtenu unknown au lieu d’un vrai type ?

Tous les échantillons à cette position étaient null, donc il n’y a rien dont inférer. Les alternatives sont pires : null comme type est exact vis-à-vis de l’échantillon et inutile vis-à-vis des données, et any désactive la vérification de types pour tout ce qui est en aval de lui. unknown vous oblige à rétrécir le type avant de l’utiliser, ce qui est l’issue correcte quand le type est réellement inconnu.

Peut-il générer des validateurs à l’exécution, et pas seulement des types ?

Non. Les types TypeScript sont effacés à la compilation, donc une interface générée à partir d’un échantillon ne vous dit rien de la réponse réellement reçue à l’exécution. Si vous avez besoin de la garantie plutôt que de l’annotation, générez plutôt un JSON Schema et validez par rapport à lui, ou écrivez à la main un schéma Zod. Prendre une interface générée pour une validation est une erreur courante et coûteuse.

Gère-t-il les documents profondément imbriqués ou récursifs ?

L’imbrication, oui, jusqu’à une profondeur de 100 — au-delà, le code généré serait de toute façon inutilisable, donc il y a un plafond net plutôt qu’un débordement de pile. La vraie récursion (un commentaire qui contient des commentaires) est déduite aussi loin que va l’échantillon ; si l’échantillon a trois niveaux, vous en obtenez trois, car rien dans les données ne dit que la structure se répète à l’infini.

Mon JSON est-il envoyé ?

Non. L’inférence et le rendu s’exécutent tous deux dans l’onglet déjà ouvert — ouvrez DevTools et observez le panneau Réseau pendant que vous collez. Cela compte plus ici que sur la plupart des outils, car les documents que les gens convertissent sont des réponses d’API de production, souvent avec de vrais enregistrements clients dedans.