Convertisseur JSON → TypeScript, gratuit
Collez du JSON et obtenez instantanément des interfaces TypeScript.
Comment utiliser
- Collez votre JSON dans le panneau de gauche (objet ou tableau).
- Cliquez sur Convertir · les interfaces TypeScript apparaissent à droite.
- Ajustez le nom racine et activez les options au besoin.
- Cliquez sur Copier la sortie pour copier le code généré.
Questions fréquentes
Gère-t-il les objets imbriqués ?
Oui. Chaque objet imbriqué reçoit sa propre interface nommée. Les éléments des tableaux sont aussi analysés pour déterminer le type d'élément.
Que se passe-t-il avec des tableaux de types mixtes ?
Si un tableau contient des éléments de types différents, le convertisseur utilise un type union (par ex. string | number).
Prend-il en charge les tableaux JSON à la racine ?
Oui. Si la valeur racine est un tableau, le convertisseur analyse ses éléments et produit l'interface appropriée ainsi qu'un alias de type pour le tableau.
Ce que fait réellement le convertisseur
Il analyse votre JSON, parcourt chaque valeur et produit un ensemble de déclarations d'interface TypeScript décrivant la structure. Chaque objet imbriqué reçoit sa propre interface nommée, dérivée de la clé de propriété parente en PascalCase (un champ user devient une interface User). Lorsque deux objets imbriqués entrent en collision de nom, le second reçoit un suffixe numérique (User, User2). À la racine, un tableau devient un alias type Root = RootItem[]; ainsi que l'interface RootItem ; un objet devient une seule interface Root (ou le nom que vous saisissez dans le champ « nom racine »).
Exemple d'entrée et de sortie :
// Input
{
"id": 42,
"name": "Ada",
"active": true,
"tags": ["admin", "billing"],
"profile": { "bio": "Programmer", "link": null }
}
// Output
export interface Root {
id: number;
name: string;
active: boolean;
tags: string[];
profile: Profile;
}
export interface Profile {
bio: string;
link: unknown;
}
Le mappage de types JSON → TypeScript
| Valeur JSON | TS généré |
|---|---|
"hello" | string |
42 ou 3.14 | number (TS n'a pas de type entier distinct) |
true / false | boolean |
null | unknown (le convertisseur ne peut pas savoir si le champ est nullable ou simplement absent dans cet exemple) |
[] | unknown[] |
[1, 2, 3] | number[] |
[1, "x"] | (number | string)[] |
{ "a": 1 } | interface nommée |
Pour les tableaux d'objets de niveau racine, le convertisseur fusionne les clés de tous les éléments en une seule interface représentative. C'est une approximation correcte lorsque les éléments partagent une même structure, mais elle perd de l'information lorsque les structures divergent réellement (par ex. un tableau d'événements hétérogènes). Dans ce cas, vous devrez écrire une union discriminée à la main après la génération.
Pourquoi interface pour les objets et type pour le tableau racine
Le TypeScript Handbook officiel donne une heuristique en une ligne : « Si vous souhaitez une heuristique, utilisez interface jusqu'à ce que vous ayez besoin de fonctionnalités de type. » Les deux sont typés structurellement, les deux peuvent décrire des formes d'objet, mais interface l'emporte pour les formes d'objet car il prend en charge la fusion de déclarations (rouvrir l'interface pour ajouter des champs), fonctionne proprement avec extends, et apparaît par son nom dans les erreurs du compilateur. Les alias type sont nécessaires lorsque vous avez besoin d'unions de primitives, d'intersections de plusieurs types, ou de nommer une chose qui n'est pas un objet, ce qui explique pourquoi le tableau de niveau racine reçoit un alias type Root = RootItem[]; plutôt qu'une interface.
Une note sur le nommage : le convertisseur utilise le PascalCase sans le préfixe I hérité (donc User plutôt que IUser). Les guides de style TS modernes (ceux de Google, de Microsoft, de la communauté React) abandonnent presque tous le préfixe. Les noms de propriété correspondent exactement aux clés JSON (camelCase si le JSON utilise camelCase, snake_case s'il utilise snake_case). Les clés qui ne sont pas des identifiants JS valides (contenant des traits d'union, des espaces, ou commençant par un chiffre) sont mises entre guillemets : "foo-bar": string;.
Ce que cet outil ne fait pas (soyons honnêtes sur les limites)
Un seul exemple JSON porte moins d'information qu'un véritable schéma, si bien que plusieurs choses qu'il serait utile de détecter ne sont pas possibles à partir de la seule entrée :
- Champs optionnels. Chaque propriété de votre exemple devient obligatoire. Si la véritable API omet parfois un champ, vous devez ajouter le
?à la main :email?: string;. Ou exécutez le convertisseur sur plusieurs exemples et faites l'union des résultats. - Détection des valeurs nullables. Un
nulldans l'exemple devientunknown; le convertisseur ne peut pas savoir si le champ est réellement nullable (string | null) ou s'il s'est simplement trouvé être null dans cet échantillon. Ajustez à la main selon le contrat de l'API. - Unions de littéraux de chaîne. Un champ de statut ayant la valeur
"active"devientstring, et non"active" | "inactive" | "pending". Le convertisseur ne peut pas voir les autres valeurs. - Détection du type Date. Une chaîne ISO 8601 comme
"2024-04-12T10:00:00Z"reste de typestring. LeDatede JavaScript n'est pas un type JSON. - Unions discriminées. Si un tableau racine contient des éléments de structures différentes (événements de types différents, enregistrements polymorphes), le convertisseur fusionne toutes les clés en une seule interface au lieu de produire une union étiquetée. Pour des données réellement hétérogènes, vous voudrez écrire l'union à la main.
- Précision des nombres. Le
numberde JavaScript représente sans risque les entiers jusqu'à 253−1. Les identifiants entiers plus grands perdent en précision lorsqu'ils sont analysés parJSON.parse; si votre API renvoie des entiers 64 bits, le modèle le plus sûr consiste à les envoyer sous forme de chaînes et à les typer enstring.
Quand utiliser cet outil
- Amorcer des types à partir d'une vraie réponse d'API. Appelez le point de terminaison, collez le JSON, obtenez un ensemble d'interfaces de départ. Ajustez à la main pour les champs optionnels et les littéraux de chaîne.
- Ajouter des types à un SDK tiers non typé. De nombreuses bibliothèques JS plus anciennes sont livrées sans types. Générer à partir d'une réponse d'exemple est plus rapide que de lire la documentation.
- Partager des types entre le front-end et le back-end. Générez à partir d'un exemple canonique unique et copiez dans les deux bases de code (ou partagez via un paquet de types publié).
- Migrer une base de code JS vers TypeScript. Générez des types à partir des données réelles qui circulent dans l'application et annotez progressivement les signatures de fonctions.
- Générer des types pour un fichier de configuration. Un typage strict rend les erreurs de configuration visibles à la compilation.
- Documenter la structure d'un fichier de données interne. L'interface générée fait aussi office de documentation lisible par machine.
Code d'abord, schéma d'abord ou direct (la place de cet outil)
Trois flux de travail courants pour obtenir des types TypeScript à partir de données d'exécution :
- Validateurs d'exécution code d'abord : Zod, Yup, Effect Schema, Joi. Vous écrivez un schéma de validation en JS, il vous donne à la fois l'analyse à l'exécution et un type TypeScript par inférence. Le schéma est la source de vérité. Idéal lorsque la validation compte autant que le type.
- Schéma d'abord : écrivez un JSON Schema ou une spécification OpenAPI, générez des types TypeScript via des outils comme
quicktype,json-schema-to-typescript, ouopenapi-typescript. Idéal lorsqu'un contrat d'API couvre plusieurs langages. - Inférence directe par échantillon (cet outil, ainsi que le mode JSON brut de quicktype) : collez des données réelles, obtenez des types. Voie la plus rapide ; garanties de validation les plus faibles, car rien ne vérifie les données d'exécution par rapport au type.
Le bon choix dépend de votre priorité : la vérification statique des types (cet outil est excellent) ou aussi la sûreté à l'exécution (tournez-vous plutôt vers Zod / Effect Schema).
Erreurs fréquentes
- Traiter les types générés comme une spécification finie. Ils constituent un point de départ achevé à 70 %. Ajoutez
?pour les champs optionnels,| nulllà où c'est réellement nullable, et des unions de littéraux de chaîne le cas échéant. - Générer à partir d'un seul exemple alors que l'API a des variantes. Un objet utilisateur qui possède parfois un champ
emailet parfois non sera généré comme « email est requis ». Exécutez plusieurs exemples et faites l'union des résultats, ou modifiez à la main. - Marquer tout en
readonlyautomatiquement. Utile pour les flux de données immuables, mais inadapté aux objets d'état que vous modifiez. Utilisez l'optionreadonlyavec discernement. - Se fier à la précision des grands identifiants entiers. Le
numberde JavaScript plafonne à 253−1. Pour les identifiants 64 bits, transmettez-les sous forme de chaînes et typez-les enstring. - Confondre
interfaceettype. Outils différents, compromis différents. L'heuristique du TypeScript Handbook est « utilisez interface à moins d'avoir besoin d'une fonctionnalité que seul type offre », précisément ce que fait cet outil. - Coller du JSON confidentiel dans un convertisseur côté serveur. Les vraies réponses d'API contiennent souvent des données clients, des identifiants de connexion, des ID internes. Une conversion uniquement dans le navigateur (cet outil) conserve les données sur votre machine.
Autres questions fréquentes
Pourquoi tous mes champs ont-ils été marqués comme obligatoires ?
Parce qu'un seul exemple JSON ne peut pas indiquer au convertisseur quels champs sont parfois absents dans la véritable API. Chaque clé qui apparaît dans l'exemple devient obligatoire. Si vous savez qu'un champ est optionnel, ajoutez un ? final à la main : email?: string;. Pour la détection d'optionalité sur plusieurs échantillons, l'interface en ligne de commande quicktype, plus sophistiquée, la gère nativement.
Pourquoi mon champ null est-il typé en unknown ?
Parce que le convertisseur ne peut pas déterminer, à partir d'un seul null, si le champ est toujours nullable (string | null) ou s'il s'est simplement trouvé être null dans cet échantillon (string). unknown est la valeur par défaut prudente ; TypeScript vous obligera à affiner le type avant d'utiliser la valeur, ce qui est plus sûr que any. Modifiez en string | null à la main une fois que vous connaissez l'intention de l'API.
Dois-je utiliser interface ou type ?
L'heuristique du TypeScript Handbook officiel : utilisez interface jusqu'à ce que vous ayez besoin d'une fonctionnalité que seul type offre, principalement les types union, les types intersection, ou le nommage d'une primitive. Ce convertisseur suit cette règle : interface pour chaque forme d'objet, type pour l'alias du tableau racine. Certains guides de style recommandent plutôt type par défaut (Matt Pocock a défendu publiquement cette position), mais la valeur par défaut conventionnelle est interface pour les objets.
Mon JSON sera-t-il téléversé quelque part ?
Non. La conversion est une IIFE JavaScript autonome qui analyse votre JSON via JSON.parse, parcourt la valeur et écrit la sortie TypeScript dans une zone de texte. Il n'y a aucune requête fetch, aucun appel d'analytique transportant le contenu JSON, aucun serveur. C'est important, car les vraies réponses d'API contiennent généralement des données clients, des ID internes ou des identifiants de connexion que vous ne voulez pas voir transiter par un tiers.
Et JSDoc, Zod ou la validation à l'exécution ?
Cet outil n'émet que des types TypeScript à la compilation : aucun validateur d'exécution (ni Zod / Yup / Effect Schema), aucun commentaire JSDoc. Si vous avez besoin d'une validation à l'exécution qui sert aussi de type statique, écrivez le schéma en Zod et utilisez le z.infer<typeof Schema> de Zod pour dériver le type. Si vous avez un JSON Schema et souhaitez à la fois la validation à l'exécution et les types TS, json-schema-to-typescript + AJV est la combinaison conventionnelle.
Pourquoi n'y a-t-il pas de préfixe I sur les noms d'interface ?
Parce que la plupart des guides de style TypeScript modernes l'abandonnent. Le Google TypeScript Style Guide le déconseille explicitement ; la communauté React a convergé vers le PascalCase sans préfixe. La convention héritée IUser provient de l'influence de C# / Java sur les débuts de TypeScript ; la pratique actuelle est simplement User.