TypeScript 装饰器需先启用编译选项,是运行时元编程机制,用于修改类、方法或属性行为而不侵入原始逻辑;旧版启用 experimentalDecorators 和 emitDecoratorMetadata,新版启用 decorators 并设 target 为 ES2022+。

要在 TypeScript 中使用装饰器,必须先启用编译选项,再按类型正确声明和应用。它不是语法糖,而是运行时生效的元编程机制,核心是修改类、方法或属性的行为,不侵入原始逻辑。
开启装饰器支持
装饰器是实验性特性(旧版)或标准特性(新版),配置方式不同:
-
旧版(ES7 提案风格,广泛兼容):在 tsconfig.json 中启用两个选项:
"experimentalDecorators": true(必需,启用装饰器语法)"emitDecoratorMetadata": true(可选,仅在依赖注入等需反射类型时需要) -
新版(ECMAScript 标准装饰器,TypeScript 5.0+):关闭旧选项,启用新标准:
"experimentalDecorators": false"decorators": true"target": "ES2022"或更高(因标准装饰器依赖现代引擎能力)
类装饰器用法
作用于整个类,接收类构造函数(旧版)或 { value, context }(新版),常用于注册、增强、替换类。
-
旧版写法:直接修饰类声明前,参数为
target: Function
function sealed(target: Function) {<br> Object.seal(target);<br> Object.seal(target.prototype);<br>}<br>@sealed<br>class Person { name: string; } -
新版写法:更清晰暴露元数据,如获取类名、添加初始化逻辑
function logCreation<T extends new (...args: any[]) => any>(<br> value: T,<br> context: ClassDecoratorContext<br>) {<br> console.log(`[${context.name}] created`);<br> return class extends value { };<br>}<br>@logCreation<br>class DataService { }
方法装饰器用法
修饰类中的方法,可用于日志、权限、重试、性能监控等。旧版接收三个参数;新版通过 context 提供更多控制。
-
旧版签名:
decorator(target, methodName, descriptor)target是类原型,descriptor是属性描述符(含value即原方法)
可包装原方法并返回新 descriptor:
function log(target: any, name: string, desc: PropertyDescriptor) {<br> const original = desc.value;<br> desc.value = function(...args: any[]) {<br> console.log(`→ ${name} called with`, args);<br> const res = original.apply(this, args);<br> console.log(`← ${name} returned`, res);<br> return res;<br> };<br>} -
使用位置:紧贴方法定义上方,不能放在访问器(
get/set)或箭头函数上
属性装饰器用法
修饰类字段(非构造函数内赋值的属性),常用于验证、响应式绑定、序列化控制等。注意:它不触发 setter/getter 定义,而是操作类原型或实例本身。
-
旧版签名:
decorator(target, propertyName)target是类原型(静态属性)或构造函数(实例属性,需配合Object.defineProperty操作实例)
示例:限制数量不能为负
function positive(target: any, key: string) {<br> let val = target[key];<br> Object.defineProperty(target, key, {<br> get: () => val,<br> set: (v: number) => {<br> if (v < 0) throw new Error(`${key} must be ≥ 0`);<br> val = v;<br> },<br> });<br>}<br>class Cart { @positive quantity: number = 0; } -
注意:TS 不允许在属性装饰器中直接读取类型信息(除非开启
emitDecoratorMetadata并配合反射库)


















