The easiest way to understand decorators is to think of them as metadata that you can add to your classes,methods and even getter and setter properties
In fact,you can add far more than just information
You can actually extend these elements with additional behavior allowing you to add that behavior to your code without actually changing your code.
Typescript actually encourages developers to opt in to decorator support via configuration setting
In tsconfig file set the experimentalDecorator and emitDecoratorMetadata settings to “true“
{
"compilerOptions": {
"target": "exnext",
"noEmit": true,
"experimentalDecorators": true
"emitDecoratorMetadata": true
},
"include":["src/**/*"]
}
And then you need to install reflect-metadata library
npm i reflect-metadata --save
This library implements polyfill for another proposed Ecmascript features,which are considered experimental
Method Decorator
Implementing a method decorator as writing a function that looks like this
function authorize(role: string){
return function authorizeDecorator(target: any, property: string, descriptor: PropertyDescriptor){
const wrapped = descriptor.value;
descriptor.value = function(){
if(!currentUser.isAuthenticated()){
throw new Error("Unauthorized");
}
if(!currentUser.isInRole(role)){
throw Error(`User not in role ${role}`);
}
try {
return wrapped.apply(this, arguments);
}catch(ex){
throw ex;
}
}
}
}
let currentUser = {
roles: ["Viewer", "Editor"],
isAuthenticated(): boolean {
return true
},
isInRole(role:string): boolean {
return this.roles.contains(role);
}
}
interface Person {
id: number;
}
private persons: Person[] = [];
@authorize("Viewer")
getPersonById(id: number): Person | null {
const person = this.persons.find((x) => x.id === id);
return person;
}
Class Decorator
function freeze(constructor: Function){
Object.freeze(constructor);
Object.freeze(constructor.prototype);
}
function singleton<T extends { new (...args:any[]): {}}>(constructor: T){
return class Singleton extends constructor{
static _instance = null;
constructor(...args){
super(...args);
if(Singleton._instance){
throw Error('Duplicate instance');
}
Singleton._instance = this;
}
}
}
@freeze
@singleton
class Repository {}
Property Decorator
Property decorators are decorators that are applied to properties of a class like the context property of our repository.
You apply a decorator to property the same way you apply one to a class or a method
function auditable(target: object, key: string | symbol){
//get the initial value, before the decorator is applied
let val = target[key];
//then overwrite the property with a custom getter and setter
Object.defineProperty(target, key, {
get:() => val,
set: (newVal) => {
console.log(`${key.toString()} changed : `, newVal);
val = newVal;
},
enumerable: true,
configurable: true
})
}
interface Person {}
class Repository {
@auditable
private persons: Person[] = [];
}
It is rare for me to find something on the cyberspace thats as entertaining and fascinating as what you have got here.
Your page is sweet, your graphics are outstanding, and whats more, you use source that are relevant to
what you are talking about. You are definitely one in a million, good
job!
or their samples written