interface ValidatorConfig {
[property: string]: {
[validatableProp: string]: string[]
}
}
const registeredValidators: ValidatorConfig = {};
function Required(target:any, propName: string) {
registeredValidators[target.constructor.name] = {
...registeredValidators[target.constructor.name],
[propName]: ['required']
};
}
function PositiveNumber(target:any, propName: string) {
registeredValidators[target.constructor.name] = {
...registeredValidators[target.constructor.name],
[propName]: ['positive']
};
}
function validate(obj: any) {
const objValidatorsConfig = registeredValidators[obj.constructor.name];
if (!objValidatorsConfig) {
return true;
}
let isValid = true;
for (const prop in objValidatorsConfig) {
for (const validator of objValidatorsConfig[prop]) {
switch (validator) {
case 'required':
isValid = isValid && !!obj[prop];
break;
case 'positive':
isValid = isValid && obj[prop] > 0;
break;
}
}
}
return isValid;
}
class Course {
@Required
title: string;
@PositiveNumber
price: number;
constructor(t: string, p: number) {
this.title = t;
this.price = p;
}
}
const courseForm = document.querySelector('form')!;
courseForm.addEventListener('submit', e => {
e.preventDefault();
const titleEl = document.getElementById('title') as HTMLInputElement;
const priceEl = document.getElementById('price') as HTMLInputElement;
const title = titleEl.value;
const price = +priceEl.value;
const createdCourse = new Course(title, price);
if (!validate(createdCourse)) {
alert('Invalid input, please try again!');
return;
}
console.log(createdCourse);
});