A Property Decorator is applied on a property declaration.
The property decorator function is called with the following two arguments:
- Either the constructor function of the class for a static member, or the prototype of the class for an instance member.
- The name of the property.
As opposed to class and method decorators, a Property Descriptor is not provided as an argument to a property decorator.
Also the return value from the decorator function is ignored.
A property decorator can only be used to observe that a property of a specific name has been declared for a class.
Example
Property Decorator without parameters
Ex1PropertyDecorator.tsfunction notNull(target: any, propertyKey: string) {
Validator.registerNotNull(target, propertyKey);
}
class Validator {
private static notNullValidatorMap: Map<any, string[]> = new Map();
//todo add more validator maps
static registerNotNull(target: any, property: any): void {
let keys: string[] = this.notNullValidatorMap.get(target);
if (!keys) {
keys = [];
this.notNullValidatorMap.set(target, keys);
}
keys.push(property);
}
static validate(target: any): boolean {
let notNullProps: string[] = this.notNullValidatorMap.get(Object.getPrototypeOf(target));
if (!notNullProps) {
return true;
}
let hasErrors: boolean = false;
for (const property of notNullProps) {
let value = target[property];
if (!value) {
console.error(property + " value cannot be null");
hasErrors = true;
}
}
return hasErrors;
}
}
class Person {
@notNull
name: string;
constructor(name: string) {
this.name = name;
}
}
console.log("-- creating instance --");
let person: Person = new Person(null);
console.log(person);
let b = Validator.validate(person);
console.log("validation passed: " + !b);
console.log("-- creating another instance --");
let person2: Person = new Person("Tina");
console.log(person2);
b = Validator.validate(person2);
console.log("validation passed: " + !b);
-- creating instance --
Person { name: null }
name value cannot be null
validation passed: false
-- creating another instance --
Person { name: 'Tina' }
validation passed: true
Property Decorator with parameters
Ex2PropertyDecorator.tsenum ValidationType {
NotNull
}
function validate(...types: ValidationType[]) {
return function (target: any, propertyKey: string) {
Validator2.registerValidators(target, propertyKey, types);
}
}
class Validator2 {
private static notNullValidatorMap: Map<any, string[]> = new Map();
//todo add more validator maps
static registerValidators(target: any, property: any, types: ValidationType[]): void {
for (const type of types) {
if(type==ValidationType.NotNull){
let keys: string[] = this.notNullValidatorMap.get(target);
if (!keys) {
keys = [];
this.notNullValidatorMap.set(target, keys);
}
keys.push(property);
}
}//todo add more validators if else
}
static validate(target: any): boolean {
let notNullProps: string[] = this.notNullValidatorMap.get(Object.getPrototypeOf(target));
if (!notNullProps) {
return true;
}
let hasErrors: boolean = false;
for (const property of notNullProps) {
let value = target[property];
if (!value) {
console.error(property + " value cannot be null");
hasErrors = true;
}
}
return hasErrors;
}
}
class Person2 {
@validate(ValidationType.NotNull)
name: string;
constructor(name: string) {
this.name = name;
}
}
console.log("-- creating instance --");
let person3: Person2 = new Person2(null);
console.log(person3);
let b2 = Validator2.validate(person3);
console.log("validation passed: " + !b2);
console.log("-- creating another instance --");
let person4: Person2 = new Person2("Tina");
console.log(person4);
b2 = Validator2.validate(person4);
console.log("validation passed: " + !b2);
-- creating instance --
Person2 { name: null }
name value cannot be null
validation passed: false
-- creating another instance --
Person2 { name: 'Tina' }
validation passed: true
Example ProjectDependencies and Technologies Used: |