Я хочу изолировать проверку модели внутри самого класса модели, без необходимости жесткого кодирования требуемых состояний (наши дизайнеры не знают, что требуется, просто им нужно подключить свойства). Я безуспешно пытаюсь использовать путь декоратора свойств. Конструктор перезаписывает то, что устанавливает декоратор. Это вообще возможно, я должен пойти об этом по-другому?
модель.ts
@Required
name: string;
hobbies: string;
constructor(dto?: any) {
this.name = dto.name; // This clears my "required" property
this.hobbies = dto.hobbies;
}
декоратор.ts
function Required(target: any, key: string) {
Object.defineProperty(target, "required", { value: true });
}
Чего я надеюсь добиться...
*.html
<input name = "name" [(ngModel)] = "model.name" [required] = "model.name.hasOwnProperty('required')">
Я также пробовал играть с самим прототипом String, чтобы инициализировать это свойство, но конструктор по-прежнему очищает все, что устанавливается.
String.prototype["required"] = false;





Вы не можете хранить дополнительную информацию в таком свойстве. Присвоенное свойство будет заменено новым значением, ничто из того, что вы назначаете, кроме прототипа класса (а target является prototype не экземпляром класса), не будет доступно после присвоения нового значения.
Решением было бы добавить дополнительное свойство, назовем его meta, которое могло бы содержать эти метаданные (и другие метаданные свойства по мере необходимости). Вы даже можете ввести его правильно, используя сопоставленные типы. Это решение довольно близко к желаемому результату:
class Model {
readonly meta!: Metadata<Model>
@Required
name: string;
hobbies: string;
constructor(dto?: any) {
this.name = dto.name; // This clears my "required" property
this.hobbies = dto.hobbies;
}
}
type Metadata<T> = Partial<Record<keyof T, PropertyMetadata>>
type PropertyMetadata = {
required?: boolean
}
function Required<T extends { meta: Metadata<T> }, TKey extends keyof T>(target: T, key: TKey) {
let meta = target.meta || (target.meta = {});
let propMeta = meta[key] || (meta[key] = {})
propMeta!.required = true
}
console.info(new Model({}).meta.name!.required);
Обратите внимание, что meta может быть неопределенным, если у вас нет метаданных. И метаданные для свойства также могут быть неопределенными, поэтому в шаблоне angular вы должны получить к ним доступ, используя ?: model.meta?.name?.required. Вы также можете сделать что-то более интересное, назначив Proxy вместо {}meta, но здесь я пошел простым путем.
Я не понимаю, как вы собираетесь использовать/создавать это. Не могли бы вы создать минимальный воспроизводимый пример на stackblitz.com? Я понимаю, что код не будет работать, но он передаст намерение.