Для этого кода, где у меня есть определяемый пользователем интерфейс и определение схемы.
type SchemaDefinition<T> = {
[K in keyof T]: {
type: { new(): unknown } //
required?: boolean
}
}
class Schema<T> {
constructor(public schema: SchemaDefinition<T>) {}
validate(obj: T): boolean {
for (const prop of Object.keys(this.schema) as (keyof T)[]) {
if (!(obj[prop] instanceof this.schema[prop].type)) return false
if (this.schema[prop].required && obj[prop] == null) return false
}
return true
}
}
interface IUser {
name: string;
email: string;
}
Тут две схемы. 1. для контейнера, специфичного для языка программирования, который представляет собой интерфейс IUser 2. тот, который я хочу отправить на серверную часть, который состоит из объекта схемы, что-то вроде
new Schema<IUser>('users',
{
name: {type: Number, required: true},
email: {type: String, required: true},
});
теперь я пытаюсь сериализовать этот объект схемы в строку, используя JSON.stringify()
, но type
пропускается, как я могу его сериализовать или как я могу перевести это IUser
в схему JSON наилучшим образом в TS.
Редактировать:
Я смог получить имя типа, выполнив что-то вроде этого
const schemaRepresentation = {};
schemaRepresentation['title'] = this._name;
schemaRepresentation['additionalProperties'] = false;
schemaRepresentation['additionalProperties'] = false;
const properties = {};
for (const schemaKey in this.schema) {
properties[schemaKey.toString()] = this.schema[schemaKey].datatype.name;
}
schemaRepresentation['properties'] = properties
если в интерфейсе есть поле массива - как мне получить тип массива?
Вам просто нужно использовать значения, которые можно сериализовать в JSON, потому что String
и Number
являются функциями и, следовательно, не сериализуемы.
Например, может быть, вы хотите проверить typeof obj[prop]
для определенной строки.
type AllowedTypeNames = 'string' | 'number' | 'boolean'
type SchemaDefinition<T> = {
[K in keyof T]: {
type: AllowedTypeNames
required?: boolean
}
}
И validate
теперь будет выглядеть так:
validate(obj: T): boolean {
for (const prop of Object.keys(this.schema) as (keyof T)[]) {
if (typeof obj[prop] !== this.schema[prop].type) return false
// ^ check if the typeof the obj[prop] matches the schema.
if (this.schema[prop].required && obj[prop] == null) return false
// ^ check if the typeof the obj[prop] is required and present.
}
return true
}
Что сериализуется нормально:
const userSchema = new Schema<IUser>({
name: { type: 'string', required: true },
email: { type: 'string', required: true },
});
console.log(JSON.stringify(userSchema.schema))
// {"name":{"type":"string","required":true},"email":{"type":"string","required":true}}
Пожалуйста, дайте мне знать, если вы считаете, что это другой вопрос и заслуживает нового вопроса SO.
Это новый вопрос :) Также вы уверены, что не просто повторно реализуете json-schema.org?
Я посмотрел на реализацию схемы json в ts. похоже, что библиотечная форма этого должна принимать файл .ts
в качестве входных данных - немного странно просить пользователя предоставить это с моей точки зрения пользователя библиотеки.
Спасибо, Алекс. Я смог получить тип, сделав что-то, о чем идет речь (отредактировано). ваш подход хорош, но он не сработает для меня, так как ограничивает тип. Теперь вопрос в том, как мне получить фактический тип массива. +1