文章转载自:https://github.com/zhongsp
建议您直接跳转到上面的网址查看最新版本。
介绍
命令行:
tsc --target ES5 --experimentalDecorators
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
Decorators (后文译作装饰器)
function sealed(target) {
装饰器工厂
function color(value: string) {
装饰器组合
- 由上至下依次对装饰器表达式求值。
- 求值的结果会被当作函数,由下至上依次调用。
function f() {
console.log("f(): evaluated");
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("f(): called");
}
}
function g() {
console.log("g(): evaluated");
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("g(): called");
}
}
class C {
@f()
@g()
method() {}
}
f(): evaluated
g(): evaluated
g(): called
f(): called
装饰器求值
-
参数装饰器,然后方法,访问符,或属性装饰器应用到每个实例成员。
-
参数装饰器,然后方法,访问符,或属性装饰器应用到每个静态成员。
-
参数装饰器应用到构造函数。
-
类装饰器应用到类。
类装饰器
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
方法装饰器
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}
function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
访问符装饰器
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
class Point {
private _x: number;
private _y: number;
constructor(x: number, y: number) {
this._x = x;
this._y = y;
}
@configurable(false)
get x() { return this._x; }
@configurable(false)
get y() { return this._y; }
}
function configurable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}
属性装饰器
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
class Greeter {
@format("Hello, %s")
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
let formatString = getFormat(this, "greeting");
return formatString.replace("%s", this.greeting);
}
}
import "reflect-metadata";
const formatMetadataKey = Symbol("format");
function format(formatString: string) {
return Reflect.metadata(formatMetadataKey, formatString);
}
function getFormat(target: any, propertyKey: string) {
return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}
参数装饰器
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 参数在函数参数列表中的索引。
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@validate
greet(@required name: string) {
return "Hello " + name + ", " + this.greeting;
}
}
import "reflect-metadata";
const requiredMetadataKey = Symbol("required");
function required(target: Object, propertyKey: string|symbol, parameterIndex: number) {
Reflect.defineMetadata(requiredMetadataKey, true, target, parameterIndex);
}
function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
let method = descriptor.value;
descriptor.value = function () {
for (let parameterIndex = 0; parameterIndex < method.length; parameterIndex++) {
if (Reflect.getOwnMetadata(requiredMetadataKey, method, parameterIndex)) {
if (parameterIndex >= arguments.length || arguments[parameterIndex] === undefined) {
throw new Error("Missing required argument.");
}
}
}
return method.apply(this, arguments);
}
}
元数据
npm i reflect-metadata --save
tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
import "reflect-metadata";
class Point {
x: number;
y: number;
}
class Line {
private _p0: Point;
private _p1: Point;
@validate
set p0(value: Point) { this._p0 = value; }
get p0() { return this._p0; }
@validate
set p1(value: Point) { this._p1 = value; }
get p1() { return this._p1; }
}
function validate<T>(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<T>) {
let set = descriptor.set;
descriptor.set = function (value: T) {
let type = Reflect.getMetadata("design:type", target, propertyKey);
if (!(value instanceof type)) {
throw new TypeError("Invalid type.");
}
}
}
class Line {
private _p0: Point;
private _p1: Point;
@validate
@Reflect.metadata("design:type", Point)
set p0(value: Point) { this._p0 = value; }
get p0() { return this._p0; }
@validate
@Reflect.metadata("design:type", Point)
set p1(value: Point) { this._p1 = value; }
get p1() { return this._p1; }
}
|
请发表评论