Si vous souhaitez que votre JSON ait un type Typecript validé, vous devrez effectuer vous-même ce travail de validation. Cela n’a rien de nouveau. En Javascript simple, vous devrez faire de même.
Validation
J'aime exprimer ma logique de validation comme un ensemble de «transformations». Je définis a Descriptor
comme une carte de transformations:
type Descriptor<T> = {
[P in keyof T]: (v: any) => T[P];
};
Ensuite, je peux créer une fonction qui appliquera ces transformations à une entrée arbitraire:
function pick<T>(v: any, d: Descriptor<T>): T {
const ret: any = {};
for (let key in d) {
try {
const val = d[key](v[key]);
if (typeof val !== "undefined") {
ret[key] = val;
}
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
throw new Error(`could not pick ${key}: ${msg}`);
}
}
return ret;
}
Maintenant, non seulement je valide mon entrée JSON, mais je construis un type Typecript au fur et à mesure. Les types génériques ci-dessus garantissent que le résultat infère les types à partir de vos "transformations".
Au cas où la transformation lèverait une erreur (c'est ainsi que vous implémenteriez la validation), j'aime l'envelopper avec une autre erreur indiquant quelle clé a causé l'erreur.
Usage
Dans votre exemple, j'utiliserais ceci comme suit:
const value = pick(JSON.parse('{"name": "Bob", "error": false}'), {
name: String,
error: Boolean,
});
Maintenant value
sera tapé, puisque String
et Boolean
sont tous deux des "transformateurs" dans le sens où ils prennent une entrée et retournent une sortie typée.
De plus, le value
sera réellement de ce type. En d'autres termes, si name
c'était réellement 123
, il sera transformé en "123"
afin que vous ayez une chaîne valide. C'est parce que nous avons utilisé String
au moment de l'exécution, une fonction intégrée qui accepte une entrée arbitraire et renvoie unstring
.
Vous pouvez voir cela fonctionner ici . Essayez les choses suivantes pour vous convaincre:
- Survolez la
const value
définition pour voir que la fenêtre contextuelle affiche le type correct.
- Essayez de changer
"Bob"
à 123
et re-exécuter l'exemple. Dans votre console, vous verrez que le nom a été correctement converti en chaîne "123"
.