装饰器
介绍
随着 TypeScript 和 ES6 中类的引入,现在存在某些需要附加功能来支持注释或修改类和类成员的场景。装饰器提供了一种为类声明和成员添加注释和元编程语法的方法。装饰器是 JavaScript 的 第 2 阶段提案,可作为 TypeScript 的实验性功能使用。
注意 装饰器是一项实验性功能,可能会在未来的版本中发生变化。
要启用对装饰器的实验性支持,您必须在命令行或 tsconfig.json
中启用 experimentalDecorators
编译器选项:
命令行:
tsc --target ES5 --experimentalDecorators
tsconfig.json:
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
装饰器
o3fxb2gG80QosCkjKX+9ZIDT8jQVw9iMirvD1/AjPMAHTdAnknaRGP9Ra2rfeYw/+b8OKHSExyLwCbjRo78irGSIrvrmkHavIUbKLDQX1O2KfRovKLFEwYgX0F+/2uJxuyHx3iCuCTL53Svt/VVhxKisRpg5SlCUGkyH69zh3SVXlffZKUl/h9xIFuT72ZD2me0l2gSq7wKGqSLcITFgchwY6bip9HktyFtA76PKf9au47FjLVt5G+hO5G2AQxBc+kRrDIq/EfgiVooUVgdm+awscz5A7jvyuD+MMjtVOHkto+hWLk+ZtjCrjGaiI1gZJwmgPABQ0EBfRTmCekMhjtV6ebnj1CQ4hR/XvWJKAV32fLcNzK+gYY8FexFbYbGNNjW+sQyP6XWH4kpth1jZaMGrjBYKcPUIxOlRoL5xWTZQhyHJS4yDV+GHW4Rr4Emsq9k3TROB91eunsCQ5BZ47Zz3nf8CFAxVbpczqWvEnDrtBWPqSLMhez/6RJQlsR0YdY6sSvC42K5hEmv6oS+VlR+p75XBPqeeQ7z+628FIBouyzcVlJcIc0QFzabPJ8qfSfRCuX1vOMadlXv0zjVfIgyo2HgHUEBib5mx7QgmBef4SuVTopxvqWiohI7F9ge1v2ydtFAj8qg+YK7LT5ROLtEJK2RcI0idSUthSVE8jrOzI2BS8FJ0ZMlOJqgOFxjarwtp3yftNgykiaDRCVaC0A==
4mrTNjElZgxiA3lRHd8tZihwQeBl66rZtwirlnSviT7MGYAQIejXz8ntbrrYw9iIirNJk2qZy6nxAAd4HCo53/cPTvVjZrijvrESYDtkmypzcoMKRxpeVtRMopyyCOY4BxdYdDHHw1A+eOJivG2ADQ==
function sealed(target) {
// do something with 'target' ...
}
装饰器工厂
IQ2giPobtI3qLMfSn9gapbeg2MGjgwBxeL57YNTTanfaFUbDxAgrPK4J4ng7kYJMJOUfYOeIWi/oJTY99T63s/B+958foLBj2+tZpMaxWJNDzg72YXVP/Gt747/VJrUjMaz+3blWlyyLsH1J8hYkesshT5w6efG2eJrxDw0OPLWBKyt2xOqKJnrMce4DQcQIfCmzWUoZg05wLRA0nTf0vVagqNynYI8XzY0Ff76htkQRB8DapTVLG6sBwkbTCGbcbEDQibfgpSREdWOXVWUw4Q==
Q6bK7LzXK2POD9khcBgOCjggyx0m/2bAyt9U20+ksslGdgliX+v1ACMSDCXjXRbJIrFW17hJFKok/IcSOK4LQA==
function color(value: string) {
// this is the decorator factory, it sets up
// the returned decorator function
return function (target) {
// this is the decorator
// do something with 'target' and 'value'...
};
}
装饰器组成
W/tCMyqQpfbbPHHtX1JaBAhLbq0FDRqk4oimi8zgQxQF1YpkeMQV/9WZlovkKlzxy/w2zaXexcHpUoX+P8NEKQ==
function f() {}
function g() {}
@f @g x
xaXuhDGJuK8gOFRKEFQ/4Q==
function f() {}
function g() {}
@f
@g
x
O2T3jN+HKEYLL/31OJsdKRM4+uAwtZD1IxvIPgw2j2s/vbclhU+kRxpLuVr0szH0Lg3utZtLtOnqT58EB+2BmYG+4O02HyKP9Tqhbq+nMyFSscx7jnhOEnfNqxJHkT6TxMZ/5ON01m3GqC2L/zN5pEoHqiVwSBcwII0QilAxeynFTqNNNiF8/6D2MHmKmXjksJd0oSpWHBppuRDX2rx+Qc7c36yjTALF+FcATm5xGjbasp6eoH3uR/cwYyRtMtxcO6IZPtIVcK+55v4jCFIY2cwZBxpsgrPNN0wJNmmfUZpf49i3JgrU2uUM/bPSXiDAGPEiF11jsXm0aX/q4gPV1g==
NHT1w+HFFOogMjDaPRigvhy6hAqtbcFWz47v5vA7VQY212FPHDAay9sJ/9G2R5dFB2UWOq3+l6rnh7YRekJ79XlSbL3e8SBB+CWUvcqlwL6z6vEzL1HqV9k/PwpAKah3
- 每个装饰器的表达式都是从上到下计算的。
- 然后将结果作为函数从下到上调用。
rNOSvm5DJH/Bu+HPi+i07jkXaVAp0iTsQ4DSDf/Mr7MS+meVmBCqPv3Ssvm+Uon02PNtBcFH+1NARfJqHvTXjm7/GoNIKCChboF0WBRZYG63wIzPuiJghF9Tt4D9JycsbVDHWrYUGMbP/rHMhiwusktJ19x6q/dxd6lrky2cNrrOrQBPuRQyN338jIrA2hcO
function first() {
console.log("first(): factory evaluated");
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("first(): called");
};
}
function second() {
console.log("second(): factory evaluated");
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("second(): called");
};
}
class ExampleClass {
@first()
@second()
method() {}
}
11fUEHPyXRpCmg7yyy3sAoWa+EjOYWdwElWX5TYXs8K6/q0l4jlpnHGNpOEuxxK0
first(): factory evaluated
second(): factory evaluated
second(): called
first(): called
装饰器评价
F/tkTrmz7hK6pMXhky9OMG9SN5xMpfVOORB/rM9OJXM6BP+jXEn6cwefBmBBRcSJXQHzZfZ7MWlCBAYyC/IVW6IA33EVK3Kqkrj03UbbHPjHxnpQxIe6n0HBHrJOsrIq
- 参数装饰器,后跟方法、访问器或属性装饰器应用于每个实例成员。
- 参数装饰器,后跟方法、访问器或属性装饰器应用于每个静态成员。
- 参数装饰器应用于构造函数。
- 类装饰器应用于类。
类装饰器
IUsDEpcEDTNUjUBMMTkU9HVepjQ+y3knJ7GFdGOvXRkNNDNHCxgRZSwCRp4NyQU1MD8yii+PAXrkXLhAMFqch9UI0wKxKZUv1SJlG82rjmBdjFadpd3szSsTYFz/jU5aA0GTPPVb/o2xxU0/CBznu6rIVvCMcuBCcibLEPt99PBNCtST8ejE0TJ0uTk9EmVzpv5LuKXBAANFHY2SwzaevIYL6kGVHjHbysojqy4eu0mCh6TZHCrHPnyDZbhjYBwLBtdSFOdWX/CycNtOrAqvMPvZ04LKh4oD1R6I9SeA9TuNDj+7eumA03+DSpfpdJpfzzarFobYsOhQqdQvU81DdA==
le8a+NeNn3yMlXI7Ju8ETJJDD+Jp9GjYqfQLAXKwNtxTo0OxC1rIqQUZXqQ/uj5Z8BeoEfyoe9ux7lBHqlsZwHzvytPE2bgNHZ45Y0NIZyhSm4E7egeoGGMJ0U9WiF/xtiQVN8iP6M95eFndy4m6TQ==
R3ekuByTQlOh+920bTBZ0csgSgL5bjlVc3LVrI6nnH2D23ZMFPhuVFHH6PsrQWYjz/zOK4UhmdDWBTARLstvNJVAZRtPp/K+WkthcNCgRqix3Fd7At4G5cmnNlr1THOv
rR9BxcxmvAHVptJGY9xXWNPwwwuO9AuGkVV41tFCMEx2WYXndOe6t4P20kM2QOJ3zuj3CUB54JgJ871ISwRpHxbAbEGRyD7t1PyNUHxycYOec1bFf1HmOmjw+gIsEV7NflptxBQ0S2fBCKWjjBEE3PPZ8gUjAwKpp/hjMjoaCLAOV1kFv/yGiVZ8IUy+Prmp9cP+hK1PXll0ZITucfSjhRZGm2ShORRXKhz1mwJFNdU=
8gE+JRACalRqviqXRrwVPJvDom9ccr3/NNZk32veu1I7eAQjR2VhqeIEFooHZ1wZctwBsYooXGXZIWMmIjrB6HVeKiyts5BT1DrbIrBis+Cr7z2Zoq0g+VTv6I7/7Jc/zfHQV8W1yrDKWc+yzjKs6g==
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class BugReport {
type = "report";
title: string;
constructor(t: string) {
this.title = t;
}
}
D8hMSmaW2zu8E5bzOEF36naXLxEQBYXV9bwcXtCumk3JQreexlzOABn8KlPo1IKNGIz5pcLbndLJn+6Vmy5k7/1vKEeC8zN4xf4HWZtORFY=
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
w/7GCvFnDU1ICJ4Fxp5P+a6xcmY8Oq8mPPfoMnIqgfX/ViJ7GGvvKTNYNxFsnOQxJvLRBWJVCA1p/KyB1u0Co7+1elbpegkCxs1BL5iAQbwCVf4KrFg1q7HmcLbZhCiqotnNh6cqUeKT88Hw9FEGjiboqAY1jlaKM4MXCAAtjWynJuIwTyzFBXWpLJ6/NF4HeDore4ukP5BmQBdWSkQH7CD6+VXqdYeJydecCWDQmN6yEmBxoAREeHIA1FcDnKIzV2pdD3IsqsjKWHqzsuYctstfEo+Z9N0fSpmq+2L9nqwBAclks72md7GiCvY5WevviZRozfzG/hCP54KxdV/fJ+Ma0MEdlEGhKr2NxPm5/N3poIV5h2nf6doBCw1WvX6exnqK4az9JFBHbR9FmS7FUYH3RUj0ai6tqQyd8EY5nv/UCoZbf6lFU+dx2S6rCWhFbGP5glNuDPKP/7P1/7cbVN6c8ojWB1rrIBKnU9Ly2dGGjU/O+O7lokpG6gnbKUUgamKDiTA0R5XSTcc0eLxajfL6VbotBOR7SXxkaEtL6/hCid7DT/SQzHMQycDZlOv+
nj21u+bT+U6m9RBNPJzmEI+8drrpukZWeRZRB9LarCETyeCtuZLHelv+88gzaUq2Z7c1bycPCsbUSlYSD9AgEDO2/nFFPEcDRD6GVvVkaAurzWMHP0u0X0RmaA3Ha2VL
function reportableClassDecorator<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
reportingURL = "http://www...";
};
}
@reportableClassDecorator
class BugReport {
type = "report";
title: string;
constructor(t: string) {
this.title = t;
}
}
const bug = new BugReport("Needs dark mode");
console.log(bug.title); // Prints "Needs dark mode"
console.log(bug.type); // Prints "report"
// Note that the decorator _does not_ change the TypeScript type
// and so the new property `reportingURL` is not known
// to the type system:
bug.reportingURL;
方法装饰器
Wbqk2YueWVruo1dwEca4GKWkS/QS/k17UmYicol13/VtEBIU1hTInpIp4Oxi740A9ZxlOqUoyArijmq6Jyb6x6GAXOWEXLKw5Mn7X8+XyP6/IxyYnJC7R0vHpKBfByMi9CVDbJXTtoGVS6zIoq64xTbgbSgDoDbpfE/XwCmbAKLklQofxFdRGMmpTaxycKfwlpSgR61e283lbx/g1SB6bUrUW430I3j4HkTN2zZpliH2dXm6iRtiiA0G0GQNdqdR+b7j/XKVflvkuwJZGt/5OWaP+0kUqyqszQPn1wQUBiii/wG6MF56WpIdqu0QVoDAeml+pDuA18dyvw+dF4YyqCL8Wz5eEoklcL3cL5oie04=
FF0UCM8KhNfZixVKpvt5MBrEVuenrfWBOTkwD7I7hcRsLAtKZCQwTMiS/a7kZqoavWAOgzxnFY5EE4ES6Nh03Eci7Z+K12wEQEclwiKTvSGX19vkjN+A86BTIOBTmhmn
- 静态成员的类的构造函数,或者实例成员的类的原型。
- 成员的姓名。
- 成员的属性描述符。
lFt3UKbZu3Mi8w6IRaowA65/YBFxZCpAx6EWw3lsYXF5G6YRUj/JYqiajv9kXxXg7/bv5JWB9pteJ1T5Cg5/c0a0dUlgoy++Fdu2Is232e7PfX+v3d/paBbEFoCwhvFT0VkCcb52SDJNYQNjo66Muw==
ZyIMeyPZ7I07Y3RJDs+V31h7PuMEb2meZgLDXupXOVfMc6AWAaoasqCvQFobtv8mmtmx3FYr75kO9cWg2X973R9+fegTKOS0i1yA5E3OIzr3kLe+d7QbeC0wT2aqzyCw
lFt3UKbZu3Mi8w6IRaowA65/YBFxZCpAx6EWw3lsYXF5G6YRUj/JYqiajv9kXxXgaeizNCHwuI6M99QEp90wan8LQO0RJX32NNtFyCTeEOc7FaVGxnTBeB61XLkAbqXA
8gE+JRACalRqviqXRrwVPIZcw1/rddBhZLTDW3HyH6TXBHbhlu9s4JFMhqfD4igGUxqmJAh4OPysnQdIcMEaIqVUzvWGj9Q9StnloxAlfHug/3rwjBbQ2Dsfr1Ic+fjTp7M3NZUmlu8D37mzO9rfiQ==
function enumerable(value: boolean) {
return function (target: any,propertyKey: string,descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}
D8hMSmaW2zu8E5bzOEF36naXLxEQBYXV9bwcXtCumk3JQreexlzOABn8KlPo1IKNrmzsUj7wrovvNytP98Y6XGd0a71sl8cjP5fQ8S8YpBsNFKHwuADiOw/OSG1iHre0
function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
Qi09s7/3jpHu32y37wbiuZGntkSyS1tsnQXcAPS+d4GfpS264hrPb14bhP6P4m9K/MTus1gmV9E4A/pqYONaF8fQeqrwG4U4Y2ZMwluLlMOMgHm+NVo+AaBxZXin6lyzjSdlu6kiDhu9f0k540ODnb/I31GIqKbwWSbck6ZJDL1WW7JF+U7eBvR0O3/tq4lKt2L6bi4vYRxkqljfYv1xslfAuTqarqzSKQ4mOkHqOL68qWKRDKmToVNCSk7nRtI3X+xcurBBQ559NTEvO+3vuM7vtFysXF6zTZBPmCG3dhEjilRxA8EKS0rktLNw9bd0Mehe2mywtzdiF1vMbQ45mg==
访问器装饰器
1EZx4adBLSm/bE4UX8MdR0zP8U5uatMoL7Nz7rEaeiEGxd/tUh2IGdXtNXK0x1V0qvoQf7STNCQ53q8WxArPsANkUDvplrK20q/mpici1uTA22jOuiyB6ljOTWrNBSG2peOFzmQ6o7KtWJJuEhSQtyo9wDU5KPXhN+pc67WmxY+z8Im6GXvSJINhNKOrBwvwLKXF3vUn2bLdr/rsz51ssxibr6EF6X2L/0U+jYt/QVGWZ3NdKscY45r07kjx6a2lb61mL6BKmmKU9zg8dArjEbtFJrG/aXQJ07juVBiuOGLy3rxL6cHSbbdMdA8ftawC7SYu0TdytZUXzFunijLzGBVIk0+KF9JIgxtwqN5KBEVGs9Q/LhgRpXHcFt2Ie40a
bup5xhlwcpbLYgeMSs5a1BAPS2XbTn70XWXDtXH9MnRY22pjLzQP+uNJiWXlNzSwegWWn9EJR59stldxxBWbT0MmjBHS0VL/s0b3Q0cSpdWI1Mpn4EfJYGcN9bxeW2Og3pLpm12E5RsRE6PBN6PDGp9AA5CXdpScZTPN57QYmQsgXE9o1ba6RX+eqYa/+emnu2M0NpQFsgg1PcqklFxGaFEld72EvJxETYsXMP6BQAD/LhHYeXW2SeIdpl0jMhCZsHTki53mARJUWiyOsCfy05dEs4ZvMSHcKbnFf8ogXWbgmOVTjjg+NnmIiKKDFl6Yl4XuP+Aa99Ow/JVBu5a91q+9is2l+ytsqwG6rM/NqcjM4Uihp30Do4M8YJkchiZ73KLyZcooTHpTrd7BZx7AFQmQ4WMDs4KsS3lymbRV3i8o2tBOU1bVidWe/6qEAmaNQ3E8mJ7cRXMsIPUgniJqXw==
1EZx4adBLSm/bE4UX8MdR+svoY9f+7yx8PEoUS+3QHCFHT0+vutogWEnzkjEjQlkyvWBFPRM790+yeQctzjTnfcXiHuCM2AlnDoRL4dE5HUJO4rvuiF8Djbz750LoFNKkjJnagc1sg3wJxbifpq6sw==
- 静态成员的类的构造函数,或者实例成员的类的原型。
- 成员的姓名。
- 成员的属性描述符。
lFt3UKbZu3Mi8w6IRaowA65/YBFxZCpAx6EWw3lsYXF5G6YRUj/JYqiajv9kXxXg7/bv5JWB9pteJ1T5Cg5/c0a0dUlgoy++Fdu2Is232e7PfX+v3d/paBbEFoCwhvFT0VkCcb52SDJNYQNjo66Muw==
ItaavYqURUDhplpz7ryEA5rDf+Kb9/ANjNRG9pvYlQjV/HCKFdxFB2+UJWslfceuiFBETHxBekjM3GpFOiAQyOpUanoaSxohsXpAPJqBet5Wq9MsAxC8yvTvdTZppY4N
lFt3UKbZu3Mi8w6IRaowA65/YBFxZCpAx6EWw3lsYXF5G6YRUj/JYqiajv9kXxXgaeizNCHwuI6M99QEp90wan8LQO0RJX32NNtFyCTeEOc7FaVGxnTBeB61XLkAbqXA
8gE+JRACalRqviqXRrwVPBgGUqGXEWX7eC6jyPC0htfNH/NNPtmRLs38pXdfCO9LtTNObZXhz5d7tUJbolVF+ca+t0Qc+zobVUI2BBIUqzorXYswfKKEV/XrcG8D7p6ymWpuC9j5RY9KFOicTFlhrQ==
function configurable(value: boolean) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
descriptor.configurable = 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;
}
}
D8hMSmaW2zu8E5bzOEF36naXLxEQBYXV9bwcXtCumk3JQreexlzOABn8KlPo1IKNLXw3ebZ84hOuH0ZzSwjx3aEWPZm/KBl/yZHMecaj0B+45jrQHfiK6XSSnaTtXo1Q
function configurable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}
属性装饰器
+LioaS6mm6SNtg0Hzaceb0mdvsJ7q+eoi5I57hsGfaQCY2ABjMa98tjBDF2ZbjBam2kg9LI4bLQYZBThTPSv3Mbk57ZAHv4eIzwklWYZkjxEL5Re679PdvfSg4Dt9LcJUqVw9II2P8CAzJrycWpNX5ih5lcoB7/WZCDOHcb+NQd9+fTJJ/uITWsVYiNFr2Q3Fr+W2TWigGwFN80Mfhup9ZGa5LCWnsh0FZY9/ewvBO4=
iclDvjyJoPYe2oWMqeDtGJuUGWzVFfPJZgG/K3TrpRBlRA1UO4bsSz1y0DknHKSdvLD5IDy11EyOcH7LD84LDB1cLOnHPQ9JmJLBQW/DKMTJ6Rvp5Jtz3MPYqgyBcbIi
- 静态成员的类的构造函数,或者实例成员的类的原型。
- 成员的姓名。
tm1Bsbs7jHN0rsSsPDmHZnl2BYw/vjuKbCC1HT9iu9kU/46wqP8VyKVnON7mViC6g40Nj0hbw1eDO++d+7JXzRWFUXUGqkGhp0tX+OhZsM9QGHUZCMPtJdbNxKr83mTkCqZyImr2U1Bqo5W2FU4DT1e5aJIxNSXx7dRcEy9lcddry0QCjEWPlgo8oOhTI0waGp3GZB/rBIhExbyKSFCG+6oQCC1B1hN287C2QUoPtM/+j25xFWsPGuNt0iOK8fsBIfdrhFA3SkDZBsTiJEM9TvJdxUhJtCFMiin4qw8+4+tdRNk9IvbphI1CY5e6dRwkE0/VGzlTJVCbIcHp9o1h0smJoU0lMHG1Uwle3F2AGv4BkwypA6LDY56stNpWsq7ZLHHOaNlJ5wd/eWZQOCDc7i3vfnOmR1Z5+MNl4fD3LGtR+49/zffIrO7Z/PEGCNTo6JdCctS+wT1IDxc8v1hwDuXoUofmFbL3AFvPVteLvaerN57mXpDRbybTIpRmHQGC
D8hMSmaW2zu8E5bzOEF36nrH5C9yjz4ClO0IZeEjaRY3tGw+7kOIEflk6s0UCHJQXJcgTpya51LSFYbDCn/ayQctNZh4wW73AZM/YYbJBbzo3sndyYGCleug+e9hqJM5
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);
}
}
us+MFmlit/XJwZmi89apGFhuYYeyUgprbbtM3yQrawl8swR+8A8x8rRi4FHP25N9Qk+B6gjn47/selaX+Nxn9i+3897tDuhINx2g3oEl6M21CrqPm+jIvIKPEOqj8f8eynnTiNs6F03U2F+gqCiyf3R9JXsMGBu1kHNoysaHnIU=
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);
}
Qi09s7/3jpHu32y37wbiuTMygboGQgvAP9wNZdi9pSrxapoQNknE/gBRNEBQHE/yA2uppFRTap9y7//LQIMc9ItPTAFGgQT+gF0ywmX5iNV4RjK/xwKR/PhVlCIn8O/GiEBtA7r302C2ikav8oMiyvsnN0wr/jAXshXzkFsGOUfyo+3h5DWH0d6UFC0fIehQbic7spG2Sx1VJ+SBnyq3CgCC0uaJSq0KLUxSq0eRL78WfU/R90iZw7EHBkOpZq8HneUut1FD3k0etvlLiujLEXW/DPr9Ae8kb2HPeZBVDuVcg01xmK8IwRDoi+5g2pl2FLO9vHvc+M+j+KPk3Y5C5SFzv+EJYtFfgzYV8fsW/bJX+I8a/pPP/4sjykvn0b+TtHQjunUhppaz/EBdwJWowPHjmv+c4SZAWVqTCxnkFh0GvQ0l4QscqnvO+gdYQk/KwGHpOIrgWlPkRO7aN8jKGQ8IcgxDs40eqNOAscKkOpdS/Ha56usUozT0haIUBUS0
X70dA1tN+6/2D0w/qZRUdbtK1MVp0eeJuGVe3QwypINdtEpZR8Ygik2jQf6bDCXD/4LgoqF2OWHwzO4XfK0nuegJr1lAIwq/LHCChLFaR53sh8JVx9sDTjAoFxUuHcVWDSqqOpX8pjVLwmncHq0ZgPr/z9h/DD51fSN2uhmd8ioTa3h7BvP9Pn5d4iMQwOAWKOwJ3gG1IV2yxNDeqJOYjiDSrnPzpswXCttCAak8TKrMAEGAz0TXg5OJeKEF8riZ
参数装饰器
PtpO9T90mQeSsTpbsxclLNMOOpZCXf2kHUYc7Y2Yg9dXPRlDb9okGknCs6Nv6DhzmntEwURz94GlNo40jepGGbs7Euo7cpN2ClS3tgGZgRAd8kbIfi7waNyjAsWJEi/CwsFpYCSvoe+DROS4ypqL5dHeKltcG0etIbmkI8zmGkTyTKIZRFAMibL0LpUqzt4AiWCpgnT3kmvDs+vIuP7XHnZ5DmxNa+7YlGGFePql+ZHchhKyoVh6c4k8Z68yvjXSLDCJqWKFTivfK+Bhw0bnnoDuLJrIlhriR0cmJ/D9ELPA1agU+gbwN9EdxvjFyHF5B3BgBnRvJIe4NH5JTJo9Kg==
X+b6P3ujrZj16kV5W22oxjI9FuaTNzy/NDKLLGxnZ6EDcdm2GUblOaPlLjbqGVqWEGd7vekhxYKDjBPfqcGnDsgmtJvsWlJcMqdDxVooAr+Qzo76q5fxoj99PwYE9jFb
- 静态成员的类的构造函数,或者实例成员的类的原型。
- 成员的姓名。
- 函数参数列表中参数的序号索引。
ebstWo7JZe3/h9lvSqWsJU6ZdEGeBtENJ0EEF4STC9xKBLGNhPpDba7Db8U+dWwcZ4uBYUDzpU0f0yABQF9+oKZ3xlvHrGBiVSshcLm6nww=
X+b6P3ujrZj16kV5W22oxgLtQmXmWNv51NCQdNlU8j9Hm20Kq/neZC5rFayNLj6o
8gE+JRACalRqviqXRrwVPJvDom9ccr3/NNZk32veu1Ksw+BsE/Gxd+4mwnikwhpyKNoU2mh4tI+Fp2E4XswbBIKh6l/loBFMRddYo1Mb+RMYpnVKYxF3fu9zgM2ydh+MHQtsE4uarP6nwHf7XciXYGqoPbz3L7LGQcgfiyyiIPI=
function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<any>) {}
function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {}
class BugReport {
type = "report";
title: string;
constructor(t: string) {
this.title = t;
}
@validate
print(@required verbose: boolean) {
if (verbose) {
return `type: ${this.type}\ntitle: ${this.title}`;
} else {
return this.title;
}
}
}
us+MFmlit/XJwZmi89apGFhuYYeyUgprbbtM3yQrawl8swR+8A8x8rRi4FHP25N9Qew6edAD5NSHKstAN8cE93WXFa5aIwX1d1m2pWGxtMcFZbo9tIe1oHbQkPkBa6l17jKjsaiXIiflAZydbtHFPyP9u192BxzCGASL0jSU8wA=
import "reflect-metadata";
const requiredMetadataKey = Symbol("required");
function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {
let existingRequiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || [];
existingRequiredParameters.push(parameterIndex);
Reflect.defineMetadata( requiredMetadataKey, existingRequiredParameters, target, propertyKey);
}
function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
let method = descriptor.value!;
descriptor.value = function () {
let requiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyName);
if (requiredParameters) {
for (let parameterIndex of requiredParameters) {
if (parameterIndex >= arguments.length || arguments[parameterIndex] === undefined) {
throw new Error("Missing required argument.");
}
}
}
return method.apply(this, arguments);
};
}
Z/XSj9G141ZIUEjYE2Kl+Yhq/E4zPZmDYR+a+3el62N9XrC0HIIeRa9loHyXqDvFT1+FZJ4L08JLxMC55Uk7v9uCq6Yi6KjbsJ9jNwAMDV84kuyK4148EGGhMTNsbgQYvNU8wuU7Hhsoz/zTbqdCbINYKM4n4iLaklIHdaGmmv1UgSAoBnDdNpl5LBHGkV2gSXVVjodP03UrypD6tMjpY+nDxu4IXVxuDzUQet6jJr6KxQrEsZpucA3o6E5lMVu2LHHRS5g7z6F664ToY6TRWolc7buCPfe1G3+np90C8CfyXB7Ei7XVRfPb45MpFJqiSujLW8Avj4QLHqEm8914xUQ3QWisKlnPHG16kSYui1A=
X70dA1tN+6/2D0w/qZRUdbtK1MVp0eeJuGVe3QwypINdtEpZR8Ygik2jQf6bDCXD/4LgoqF2OWHwzO4XfK0nuegJr1lAIwq/LHCChLFaR53sh8JVx9sDTjAoFxUuHcVWDSqqOpX8pjVLwmncHq0ZgPr/z9h/DD51fSN2uhmd8ioTa3h7BvP9Pn5d4iMQwOAWKOwJ3gG1IV2yxNDeqJOYjiDSrnPzpswXCttCAak8TKrMAEGAz0TXg5OJeKEF8riZ
元数据
IiztZBpTbdxhNSzWrup0kjuTrWbxmlgGfySCwFIOtT4DHyu567/iEZaarfxbVHIK3v7mxdHBNh46HE7tIsIT7CbemY7M8kCpERi8B/CvikjFYQ4ebRmInixYm6EKJhog81YAbo5N881m7do8azvxxF8ElnVzlfgKAv+xY07d1VV9L5FBHmWpUKSBUS6S//QiWvvIaS2degGW0DuRloXKI7eR0H3t/8uUoe350pk+qVqCyEDMNDrbs4/XGE1jWp36VAASgKEP6VNRBtUdc/Af1l8t8N9yIa2PoDM8u+/WHEzbAVy61aOIBtVh/Fz30esJzfgLKGIQZDToft9oX5yic2AM0n2TBP1jZ9PlRrn4lVgsGa3k1ZevRRPYjQJarOrsbqCx1VL8COVuLLm+YwDwyIx+V8rzgdTkdFCJYRYkcYCtZ5dMLMP5nDcTxQPL5LT+
DtuiSFsuC/ngo68vUqf0yCe0F37uTzxg9ideMMvjZon4b9RFdvcyYmvyKDuldrH7
npm i reflect-metadata --save
l07RsYclkRpou/mP59IZSD1wQGoMklNDEazrG9beJ0wjbKcIh0WeHHcdN1Lg9vw+fWMgxozHbjRwjRutRSrY//N5NOrvVZEMD1pjsKXiQJrkXVPb7Il5WvTwhv5bQ8bdb6u5LDu4BBCBV0Yf9SxCFf92GK4S8HX1fybtisnJHjae4Jkuie3iMIj8i2CFO6VpDQiADwN1Uv5ZO3Dvpcla+3X4v85bt/8TUQQa6pRCzvVMM+AQL+nvHABw7lnehMPnkyqX5qs+BdCsnIGlFvq7DK/kfxwAfN8ot097JIEnj/s9VvtudHkFS7gL6Ens2JdqcAiGRRXK25zjEbJBi5svzXmB97YGzM+Cv6jyggqh0haDIihV7mL9chhy9o08tmKMwIBNJwsZ9aaXxK3MeylRRg==
LVmpK5gi1Kwl7ME78JadPFV8ksAwvFhWQdLhodE2s34=
tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata
E87U01gasrw6O20S1tQzWw8FjNwsnpF4A8XER1/IdRY0IEd298Truy02TvSYDcJ/
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
vB+xh8aLg+pUx6hqjBnzl58Kg3nvncuHMzsTTlND8xGhU3Eqn0QdA7SqnL1IOhYU9HbXlhplxFPPwH1yppuDmLwuAhKII86/YTGFB/9ZDQyFKPpPXNzCidGizKGa9vq4g7vhYGi7M2OAyxP2Ld1JE71FXHLI3wIrfLBiBgzNOAM=
w5LmJFTdF/yO5HGI9EFtOhSZ2OUEylAYKRqxlUJ4r78nA1lg9xTXLHH1NggSlxUEFqce3u8kMrsoXFl0VJfvBA==
import "reflect-metadata";
class Point {
constructor(public x: number, public y: number) {}
}
class Line {
private _start: Point;
private _end: Point;
@validate
set start(value: Point) {
this._start = value;
}
get start() {
return this._start;
}
@validate
set end(value: Point) {
this._end = value;
}
get end() {
return this._end;
}
}
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, got ${typeof value} not ${type.name}.`);
}
set.call(this, value);
};
}
const line = new Line()
line.start = new Point(0, 0)
// line.end = {}
// Fails at runtime with:
// > Invalid type, got object not Point
QXrMPzlOkqSHkeVxgiISB2qY4WyQBFYHOftRy4q5cDsI4V6EMlMvY16p+POC6cDiuUhjeMzbXyFH0fGO0SB9vB/3duZnftvAI470noIpNybPLwIroc93hWVF+1PlSpFpNI7NUhLSahVqcMtZIkwYu7J/gH+f/KpwosqSXPvBqb+Bx3TEMuq50t0y8wlN3vEyhr02i/hRj0cg6B/SmdqJYQ==
class Line {
private _start: Point;
private _end: Point;
@validate
@Reflect.metadata("design:type", Point)
set start(value: Point) {
this._start = value;
}
get start() {
return this._start;
}
@validate
@Reflect.metadata("design:type", Point)
set end(value: Point) {
this._end = value;
}
get end() {
return this._end;
}
}
1q0D1S/6mjazlTjW54cwl6Ak4GrmYCDV65I2qzPSIhYW5LTHsryA4y4qXp43e0pXRNPZnTsWtV2nyF1fGx+juDDvzdCFhEvivAqdGgfowxJaznFURw3EY2VqM1HG207W8YokMnw4l6ZPqARHlVxuBg==