Проблема
В последней статье я обсуждал использование runtypes
для подключения статических типов и проверки во время выполнения. Теория, лежащая в основе runtypes
, состоит в том, что у runtypes
есть собственный язык определений, который может преобразовываться в функцию проверки во время выполнения и тип статического машинописного текста. Делая это, мы можем удалить дублирование в двух мирах.
Это здорово, однако один из самых больших минусов этого подхода: runtypes
определен хороший язык определений, но он малоизвестен. Из-за этого невозможно создать сильную экосистему для разных сценариев.
Например, недавно я работал над проектом REST API, и мы используем открытый API для создания интерактивного документа. Однако нам приходится писать машинописные типы для этих запросов и ответов, что раздражает и очень легко сделать ошибку. Я предполагаю, что у нас мог бы быть какой-то инструмент, который мог бы генерировать эти типы машинописных текстов на основе открытого документа API, точно так же, как это делает graphql-codegen
для схемы GraphQL.
Потому что открытый стандарт API зависит от схемы JSON, хорошо известного стандарта. Если мы сможем подключить статические типы и проверку во время выполнения на основе схемы JSON, я думаю, многие проблемы будут решены.
Другое решение
И это возможно!
Давайте посмотрим на пример файла схемы JSON с именем person.json
:
{ “title”: “Person”, “type”: “object”, “properties”: { “firstName”: { “type”: “string” }, “lastName”: { “type”: “string” }, “age”: { “description”: “Age in years”, “type”: “integer”, “minimum”: 0 }, “hairColor”: { “enum”: [“black”, “brown”, “blue”], “type”: “string” } }, “additionalProperties”: false, “required”: [“firstName”, “lastName”] }
Все, возможно, знают, что уже существует множество валидаторов схемы JSON, например: ajv, которые могут проверять передаваемые данные по заданной схеме JSON. Давайте приведем приведенный выше пример для проверки объекта:
import Ajv, { JSONSchemaType, DefinedError } from "ajv"; const validateObj = (obj: unknown) => { const ajv = new Ajv(); const validate = ajv.compile({ title: "Example Schema", type: "object", properties: { firstName: { type: "string" }, lastName: { type: "string" }, age: { description: "Age in years", type: "integer", minimum: 0 }, hairColor: { enum: ["black", "brown", "blue"], type: "string" } }, additionalProperties: false, required: ["firstName", "lastName"] }); if (validate(obj)) { // data is MyData here console.log("It is a valid obj: ", JSON.stringify(obj)); } else { console.log("It is not a valid obj: ", JSON.stringify(obj)); for (const err of validate.errors as DefinedError[]) { console.log(err); } } }; validateObj({}); validateObj({ firstName: "luke", lastName: "skywalker", age: 16, hairColor: "black" });
И вывод ниже:
It is not a valid obj: {} {keyword: "required", dataPath: "", schemaPath: "#/required", params: Object, message: "should have required property 'firstName'"} It is a valid obj: {"firstName":"luke","lastName":"skywalker","age":16,"hairColor":"black"}
И есть еще один инструмент под названием json-schema-to-typescript, который может генерировать машинописный текст на основе схемы JSON.
Например, учитывая приведенную выше схему JSON, выполните следующую команду:
yarn add json-schema-to-typescript json2ts person.json > person.d.ts
Он сгенерирует следующий машинописный файл:
export interface Person { firstName: string; lastName: string; /** * Age in years */ age?: number; hairColor?: "black" | "brown" | "blue"; }
Подвести итог
В этой статье мы используем другой подход для соединения проверки в реальном времени и статического машинописного типа с использованием более стандартной схемы JSON. Проверьте следующую диграмму для более подробной информации:
Первоначально опубликовано на https://github.com.