Ich lade zur Laufzeit eine JSON-Konfigurationsdatei und verwende eine Schnittstelle, um die erwartete Struktur zu definieren:
interface EngineConfig {
pathplanner?: PathPlannerConfig;
debug?: DebugConfig;
...
}
interface PathPlannerConfig {
nbMaxIter?: number;
nbIterPerChunk?: number;
heuristic?: string;
}
interface DebugConfig {
logLevel?: number;
}
...
Dies macht es bequem, auf die verschiedenen Eigenschaften zuzugreifen, da ich Autovervollständigungen usw. verwenden kann.
Frage: Gibt es eine Möglichkeit, mit dieser Deklaration die Richtigkeit der von mir geladenen Datei zu überprüfen? dh dass ich keine unerwarteten Eigenschaften habe?
javascript
typescript
MasterScrat
quelle
quelle
Antworten:
Es gibt einen Weg, aber Sie müssen ihn selbst implementieren. Es heißt "User Defined Type Guard" und sieht folgendermaßen aus:
interface Test { prop: number; } function isTest(arg: any): arg is Test { return arg && arg.prop && typeof(arg.prop) == 'number'; }
Natürlich liegt die tatsächliche Implementierung der
isTest
Funktion ganz bei Ihnen, aber das Gute daran ist, dass es sich um eine tatsächliche Funktion handelt, was bedeutet, dass sie testbar ist.Jetzt würden Sie zur Laufzeit
isTest()
überprüfen, ob ein Objekt eine Schnittstelle respektiert. Zur Kompilierungszeit nimmt das Typoskript die Wache auf und behandelt die spätere Verwendung wie erwartet, dh: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 }
Ausführlichere Erklärungen finden Sie hier: https://basarat.gitbook.io/typescript/type-system/typeguard
quelle
Von https://stackoverflow.com/a/16016688/318557 , wie von @JasonEvans hervorgehoben
Seit Juni 2015 gibt es im TypeScript-Repo ein offenes Problem dazu: https://github.com/microsoft/TypeScript/issues/3628
quelle
experimentalDecorators
undemitDecoratorMetadata
ermöglicht das Aufzeichnen von Typinformationen. Siehe meine Antwort für eine Bibliothek, die ich geschrieben habe und die diese Informationen zur Laufzeit verwendet.Hier ist eine andere Alternative, speziell dafür:
ts-interface-builder ist ein Tool, das Sie zur Erstellungszeit in Ihrer TypeScript-Datei ausführen
foo.ts
(zfoo-ti.ts
. B. ), um Laufzeitbeschreibungen zu erstellen (z . B. ).ts-interface-checker verwendet diese, um Objekte zur Laufzeit zu validieren. Z.B
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);
Mit der
strictCheck()
Methode können Sie sicherstellen, dass keine unbekannten Eigenschaften vorhanden sind.quelle
Hier ist ein guter Weg. Sie können eine TypeScript-Schnittstelle mithilfe des Typenskript- JSON-Schemas in ein JSON-Schema konvertieren , z
Überprüfen Sie dann die Daten zur Laufzeit mit einem JSON-Schema-Validator wie ajv , z
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); }
quelle
Ich vermute, dass TypeScript (mit Bedacht) das Curly-Gesetz einhält und Typescript ein Transpiler und kein Objektvalidator ist. Ich denke jedoch auch, dass Typoskript-Schnittstellen zu einer miesen Objektvalidierung führen würden, da Schnittstellen ein (wunderbar) begrenztes Vokabular haben und nicht anhand von Formen validieren können, die andere Programmierer zur Unterscheidung von Objekten verwenden können, wie z. B. Array-Länge, Anzahl der Eigenschaften, Mustereigenschaften usw.
Wenn ich Objekte aus Nicht-Typoskript-Code verwende, verwende ich ein JSONSchema- Validierungspaket wie AJV zur Laufzeitvalidierung und einen .d.ts-Dateigenerator (wie DTSgenerator oder DTS-Generator ), um TypeScript-Typdefinitionen aus my zu kompilieren JSONshcema.
Die größte Einschränkung besteht darin, dass JSON-Schemata Formen beschreiben können, die nicht durch Typoskript unterschieden werden können (z. B. patternProperties) ). Es handelt sich also nicht um eine Eins-zu-Eins-Übersetzung vom JSON-Schema in .t.ds, und Sie müssen möglicherweise etwas Handarbeit leisten Bearbeiten von generierten .d.ts-Dateien bei Verwendung solcher JSON-Schemata.
Da andere Programmierer möglicherweise Eigenschaften wie die Array-Länge verwenden, um auf den Objekttyp zu schließen, habe ich die Gewohnheit, Typen zu unterscheiden, die vom TypeScript-Compiler durch Aufzählungen verwirrt werden könnten, um zu verhindern, dass der Transpiler die Verwendung eines Typs anstelle des Typs akzeptiert andere, wie so:
[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
Welches erzeugt eine
.d.ts
Datei wie folgt:[MyTypes.d.ts] interface typeA{ type: "A"; foo: string[]; } interface typeB{ type: "B"; foo: string[]; }
quelle
Ja. Sie können diese Überprüfung zur Laufzeit durchführen, indem Sie eine erweiterte Version des TypeScript-Compilers verwenden, die ich vor einiger Zeit veröffentlicht habe. Sie können Folgendes tun:
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");
und das ist die Ausgabe:
isValid(personOk): true Field name should be string but it is number isValid(personNotOk): false
Bitte beachten Sie, dass die
isValid
Funktion rekursiv funktioniert , sodass Sie sie auch zum Überprüfen verschachtelter Objekte verwenden können. Das vollständige Arbeitsbeispiel finden Sie hierquelle
isValid
Funktion nutzen? Soweit ich sehen kann, wird es nicht aus Ihrem Paket exportiert. Es wird in den Beispielen aus der Validator-Datei exportiert, aber das ist nicht im Paket enthalten. Wie kann ich es am besten in meinen Code aufnehmen?isValid
Funktion ist nur eine Demonstration der Reflexionsfähigkeiten; Wenn Sie eine vollständige Typprüfung erstellen möchten, sollten Sie dies selbst tun oder andere ähnliche Projekte verwenden (diese können jedoch derzeit keine Reflexion nutzen). Der Hauptpunkt hierbei ist nicht die Typprüfung, sondern die Fähigkeit des Compilers, zur Laufzeit auf eine Schnittstelle zu verweisen. Bitte beachten Sie, dass sich das Reflect-Ts-Projekt derzeit im Standby-Modus befindet, da ich darauf warte, dass die Transformator-Erweiterbarkeits-API vom Compilerkern entkoppelt wird.Ja, es gibt eine Bibliothek, die dies tut https://github.com/gcanti/io-ts
Die Idee ist einfach: Lassen Sie einfache Überprüfungen für Eigenschaften zu komplexeren Überprüfungen für Objekte zusammensetzen
quelle
Sie können verwenden Klassenvalidierung verwenden
quelle
Mir ist klar, dass diese Frage alt ist, aber ich habe gerade meinen eigenen Validator für JSON-Objekte und Typoskript geschrieben, und zwar genau zu diesem Zweck unter Verwendung von Dekoratoren.
Hier verfügbar: ts-json-object .
Typescript hat sich seit dieser Frage etwas weiterentwickelt und verfügt nun über experimentelle Funktionen, mit denen Typinformationen für die spätere Verwendung aufgezeichnet werden können.
Das folgende Beispiel validiert
@required
und@optional
Eigenschaften, validiert aber auch ihren Typ, obwohl der Typ in der Validierungsnotation nicht erwähnt wird.Beispiel:
import {JSONObject,required,optional,lt,gte} from 'ts-json-object' class Person extends JSONObject { @required // required name: string @optional // optional! @lt(150) // less than 150 @gte(0) // Greater or equal to 0 age?: number } let person = new Person({ name: 'Joe' }) // Ok let person = new Person({ }) // Will throw a TypeError, because name is required let person = new Person({ name: 123 }) // Will throw a TypeError, because name must be a string
Hat viele andere Funktionen wie benutzerdefinierte Validierungen usw.
quelle
Ich weiß nicht, wie Ihre Konfigurationsdatei aussieht, aber am offensichtlichsten wäre die JSON-Datei, obwohl ich das JSON-Schema verwenden würde, um zu überprüfen, ob die Datei zum Schema passt oder nicht.
Hier ist die Dokumentation zu json schema v4: http://json-schema.org/documentation.html
Und eines der Beispiele, wie Sie es testen können: https://github.com/fge/json-schema-validator
Natürlich müssen Sie Ihr Schema basierend auf Schnittstellen schreiben, aber Sie können sie nicht direkt verwenden.
quelle