Skip to content

Instantly share code, notes, and snippets.

@basyusuf
Created March 15, 2021 21:56
Show Gist options
  • Save basyusuf/76120ac4e5fa4ec377901e9ecfd3818b to your computer and use it in GitHub Desktop.
Save basyusuf/76120ac4e5fa4ec377901e9ecfd3818b to your computer and use it in GitHub Desktop.
Custom validator with decarator
enum ValidationTypes {
'required' = 'required',
'positive' = 'positive',
'number' = 'number'
}
interface ValidatorConfig {
[property: string]: {
[validatableProp: string]: string[];
}
}
let registiredConfig: ValidatorConfig = {};
function addValidator(target: any, property_name: string, type: ValidationTypes) {
const validator_items = registiredConfig[target.constructor.name]?.[property_name] ?? []
registiredConfig[target.constructor.name] = {
...registiredConfig[target.constructor.name],
[property_name]: [...validator_items, type]
}
}
const IsRequire = (target: any, property_name: string) => addValidator(target, property_name, ValidationTypes.required);
const IsNumber = (target: any, property_name: string) => addValidator(target, property_name, ValidationTypes.number);
const PositiveNumber = (target: any, property_name: string) => addValidator(target, property_name, ValidationTypes.positive);
const validate = (obj: any): { status: boolean, list: string[] } => {
let error_list: string[] = [];
const objValidatorConfig = registiredConfig[obj.constructor.name];
if (!objValidatorConfig) {
return { status: true, list: error_list };
}
let validation_status = true;
Object.keys(objValidatorConfig).map((class_key) => {
objValidatorConfig[class_key].map((validator_string) => {
console.log("Validator Type:", validator_string, " Key:", class_key, " Value:", obj[class_key])
switch (validator_string) {
case ValidationTypes.required:
let required_check = !!obj[class_key];
if (!required_check) {
error_list.push(`${class_key} couldn't meet the requirement to ${validator_string}. Value:${obj[class_key]}`)
}
validation_status = validation_status && required_check;
break;
case ValidationTypes.positive:
let positive_check = obj[class_key] > 0;
if (!positive_check) {
error_list.push(`${class_key} couldn't meet the requirement to ${validator_string}. Value:${obj[class_key]}`)
}
validation_status = validation_status && positive_check;
break;
case ValidationTypes.number:
let number_check = typeof obj[class_key] === "number";
if (!number_check) {
error_list.push(`${class_key} couldn't meet the requirement to ${validator_string}. Value:${obj[class_key]}`)
}
validation_status = validation_status && number_check;
break;
}
})
})
return { status: validation_status, list: error_list }
}
class Course {
@IsRequire
name: string;
@PositiveNumber
@IsNumber
price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
let example_course = new Course("", 15);
let validate_course = validate(example_course);
if (!validate_course.status) {
console.log("ERROR:", validate_course.list)
} else {
console.log("Validated");
//Continue
}
/* Example Output
Validator Type: required Key: name Value:
Validator Type: number Key: price Value: 15
Validator Type: positive Key: price Value: 15
ERROR: [ "name couldn't meet the requirement to required. Value:" ] */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment