Je charge un fichier de configuration JSON au moment de l'exécution et utilise une interface pour définir la structure attendue:
interface EngineConfig {
pathplanner?: PathPlannerConfig;
debug?: DebugConfig;
...
}
interface PathPlannerConfig {
nbMaxIter?: number;
nbIterPerChunk?: number;
heuristic?: string;
}
interface DebugConfig {
logLevel?: number;
}
...
Cela facilite l'accès aux différentes propriétés puisque je peux utiliser l'auto-complétion, etc.
Question: y at-il un moyen d’utiliser cette déclaration pour vérifier l’exactitude du fichier que je charge? c'est à dire que je n'ai pas de propriétés inattendues?
Non.
Actuellement, les types ne sont utilisés que pendant le développement et la compilation . Les informations de type ne sont en aucun cas traduites en Code JavaScript.
De https://stackoverflow.com/a/16016688/318557 , comme l'a souligné @JasonEvans
Il y a un moyen, mais vous devez le mettre en œuvre vous-même. Cela s'appelle un "Type défini par l'utilisateur" et cela ressemble à ceci:
interface Test {
prop: number;
}
function isTest(arg: any): arg is Test {
return arg && arg.prop && typeof(arg.prop) == 'number';
}
Bien sûr, l’implémentation réelle de la fonction isTest
dépend entièrement de vous, mais l’essentiel est qu’il s’agisse d’une fonction réelle, ce qui signifie qu’elle peut être testée.
Au moment de l'exécution, vous utiliseriez isTest()
pour valider si un objet respecte une interface. Au moment de la compilation, TypeScript relève le fil conducteur et traite l’utilisation ultérieure comme prévu, c’est-à-dire:
let a:any = { prop: 5 };
a.x; //ok because here a is of type any
if (isTest(a)) {
a.x; //error because here a is of type Test
}
Des explications plus détaillées ici: https://basarat.gitbooks.io/TypeScript/content/docs/types/typeGuard.html
Oui. Vous pouvez effectuer cette vérification au moment de l'exécution en utilisant une version améliorée du compilateur TypeScript que j'ai publié il y a quelques temps. Vous pouvez faire quelque chose comme ce qui suit:
export interface Person {
name: string;
surname: string;
age: number;
}
let personOk = { name: "John", surname: "Doe", age: 36 };
let personNotOk = { name: 22, age: "x" };
// YES. Now you CAN use an interface as a type reference object.
console.log("isValid(personOk): " + isValid(personOk, Person) + "\n");
console.log("isValid(personNotOk): " + isValid(personNotOk, Person) + "\n");
et voici la sortie:
isValid(personOk): true
Field name should be string but it is number
isValid(personNotOk): false
Veuillez noter que la fonction isValid
fonctionne récursivement, de sorte que vous pouvez également l'utiliser pour valider des objets imbriqués. Vous pouvez trouver l'exemple de travail complet ici
Je soupçonne que TypeScript adhère (judicieusement) à la loi de Curly et que TypeScript est un transpiler, pas un validateur d'objet. Cela dit, je pense également que les interfaces TypeScript permettraient une validation d'objet médiocre, car les interfaces ont un vocabulaire (merveilleusement) limité et ne peuvent pas être validées par rapport aux formes que d'autres programmeurs peuvent utiliser pour distinguer les objets, tels que la longueur d'un tableau, le nombre de propriétés, propriétés du motif, etc.
Lorsque je consomme des objets à partir de code non TypeScript, j'utilise un package JSONSchema validation, tel que AJV , pour la validation au moment de l'exécution, ainsi qu'un générateur de fichier .d.ts (tel que DTSgener ou DTS-generator ) pour compiler les définitions de type TypeScript à partir de mon JSONshcema.
L’avertissement principal est que, parce que JSONschemata est capable de décrire des formes qui ne peuvent pas être distinguées par TypeScript (telles que patternProperties ), ce n’est pas une traduction individuelle du schéma JSON en .t.ds, et vous pouvez avoir d’éditer manuellement les fichiers .d.ts générés lors de l’utilisation de tels schémas JSON.
Cela dit, comme d'autres programmeurs peuvent utiliser des propriétés telles que la longueur d'un tableau pour déduire le type d'objet, j'ai l'habitude de distinguer les types qui pourraient être confondus par le compilateur TypeScript en utilisant enum pour empêcher le transpiler d'accepter l'utilisation d'un type au lieu du type. autre, comme ça:
[MyTypes.yaml]
definitions:
type-A:
type: object
properties:
type:
enum:
- A
foo:
type: array
item: string
maxLength: 2
type-B:
type: object
properties:
type:
enum:
- B
foo:
type: array
item: string
minLength: 3
items: number
Ce qui génère un fichier .d.ts
comme ceci:
[MyTypes.d.ts]
interface typeA{
type: "A";
foo: string[];
}
interface typeB{
type: "B";
foo: string[];
}
Voici une autre alternative, spécifiquement pour cela:
ts-interface-builder est un outil que vous exécutez au moment de la construction de votre fichier TypeScript (par exemple, foo.ts
) pour générer des descripteurs d'exécution (par exemple, foo-ti.ts
).
ts-interface-checker les utilise pour valider des objets au moment de l'exécution. Par exemple.
import {createCheckers} from 'ts-interface-checker';
import fooDesc from 'foo-ti.ts';
const checkers = createCheckers(fooDesc);
checkers.EngineConfig.check(someObject); // Succeeds or throws an informative error
checkers.PathPlannerConfig.check(someObject);
Vous pouvez utiliser la méthode strictCheck()
pour vous assurer qu'il n'y a pas de propriétés inconnues.
Voici un bon moyen. Vous pouvez convertir une interface TypeScript en schéma JSON à l'aide de TypeScript-json-schema , par exemple.
TypeScript-json-schema --required --noExtraProps \
-o YOUR_SCHEMA.json YOUR_CODE.ts YOUR_INTERFACE_NAME
Puis validez les données au moment de l’exécution à l’aide d’un validateur de schéma JSON tel que ajv , par exemple.
const fs = require('fs');
const Ajv = require('ajv');
// Load schema
const schema = JSON.parse(fs.readFileSync('YOUR_SCHEMA.json', {encoding:"utf8"}));
const ajv = new Ajv();
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
var validator = ajv.compile(schema);
if (!validator({"hello": "world"})) {
console.log(validator.errors);
}
oui, il y a une lib qui le fait https://github.com/gcanti/io-ts
l'idée est simple, il suffit de faire des contrôles simples pour les propriétés composées en contrôles plus complexes pour les objets
Je ne sais pas à quoi ressemble votre fichier de configuration, mais le plus évident serait le fichier json, bien que j'irais avec le schéma json pour valider si le fichier correspond au schéma ou non.
Voici la documentation de json schema v4: http://json-schema.org/documentation.html
Et un exemple de test: https://github.com/fge/json-schema-validator
Bien sûr, vous devez écrire votre schéma en fonction d'interfaces, mais vous ne pouvez pas les utiliser directement.
Vous pouvez utiliser class-validation
classe Cat { @IsNotEmpty () name: string; } // Le typage statique est un travail !!! const cat: Cat = { nom: "Barsik" };
importer {validateSync} de "class-validator"; type data = { [key: string]: any; }; // Créer une nouvelle instance de classe, la remplir et la valider via "class-validator" export const validate = <D étend les données, C étend {new (): D}> (data: D, classTemplate: C): boolean => { const instanceClass = new classTemplate (); Object.keys (data) .forEach ((key) => { InstanceClass [clé] = data [clé]; }); return! validateSync (instanceClass) .length; }
si (valider (chat, chat)) { // D'ACCORD } autre { // ERREUR }