TypeScript 参数装饰器怎么用
在写前端代码时,你有没有遇到过这样的情况:一个函数的参数需要加权限校验,另一个函数的参数要做格式转换,要是每个函数都重复写这些逻辑,代码会越来越乱,维护起来特别麻烦。
其实TypeScript里有个叫“参数装饰器”的东西,就能帮我们解决这个重复代码的问题,它就像给函数参数贴个“标签”,让代码更整洁、更易维护。

先搞懂:什么是参数装饰器?
简单来说,参数装饰器是一个作用在函数参数上的特殊函数,不是作用在整个函数,也不是作用在类。它的核心作用就是在不修改原函数代码的前提下,给参数添加额外的逻辑——比如校验、转换、日志记录这些,就像给水杯套个防烫套,水杯本身没改,但拿的时候不会烫手。
举个生活化的例子:你去咖啡店点单,店员给咖啡杯套了个“隔热套”,这个“隔热套”就相当于参数装饰器,咖啡杯(原参数)还是那个杯子,但加了套之后拿的时候更方便(多了防烫功能)。
怎么用?先搞定2个前提
要写参数装饰器,得先做2件小事,不然代码跑不起来:
第一,开启TypeScript的装饰器功能。在项目的tsconfig.json里,把experimentalDecorators设为true,这就像给手机开了“装饰器应用权限”;
第二,装饰器函数的格式要对,它会自动收到3个参数:目标对象(如果是类方法的参数,就是这个类的原型)、方法名、参数在函数里的位置序号,不用手动传。
写个实用例子:给参数加必填校验
很多时候我们需要函数参数不能是空,比如用户提交地址时,“收货人姓名”不能空。用参数装饰器就能统一写校验逻辑,不用每个函数都写if(!name) throw...。
我们先写一个Required装饰器:
`typescript
function Required(target: any, methodName: string, paramIndex: number) {
// 这里加校验逻辑:当函数被调用时,检查这个位置的参数是不是空
console.log(给${methodName}方法的第${paramIndex}个参数加了必填校验);
}
`
然后在函数里用它:
`typescript
class User {
// 给第1个参数加Required装饰器,注意位置是@Required,在参数前面
saveUser(@Required name: string, age: number) {
console.log(保存用户:姓名${name},年龄${age});
}
}
`
现在调用saveUser试试:
- 当传
saveUser("张三", 25)时,控制台会打印校验日志,函数正常执行; - 当传
saveUser("", 25)时,装饰器的逻辑会触发(虽然上面的例子只打了日志,实际可以改成抛出错误),提醒你姓名不能为空,不用修改原saveUser函数的代码。
进阶一点:带参数的装饰器更灵活
刚才的Required是固定校验,要是想校验不同的参数,比如“姓名长度不能少于2”“手机号格式正确”,可以写带参数的装饰器,就像给隔热套选不同厚度,适配不同需求。
比如写一个MinLength装饰器,用来限制参数的最小长度:
`typescript
// 这里加个参数length,就是给装饰器传值,返回真正的装饰器函数
function MinLength(length: number) {
return function(target: any, methodName: string, paramIndex: number) {
console.log(${methodName}方法的第${paramIndex}个参数,要求最小长度${length});
}
}
`
用的时候只要传需要的长度就行:
`typescript
class User {
// 姓名最少2个字符
saveUser(@MinLength(2) name: string, age: number) {}
// 手机号最少11个字符
savePhone(@MinLength(11) phone: string) {}
}
`
这样同一个装饰器,能适配不同参数的校验需求,不用重复写函数。
注意这2个小坑
用参数装饰器时,要避开两个常见问题:
第一,它只作用在类方法的参数上,普通函数的参数不能用,就像隔热套只能套在带把手的水杯上,不能套在一次性纸杯上;
第二,装饰器的执行时机是“类定义的时候”,不是函数调用的时候,刚才例子里的日志,是在你定义User类时就会打印,不是调用saveUser时,这点要搞清楚,别和函数执行时的逻辑搞混。
其实参数装饰器的本质,就是把“和业务无关的通用逻辑”从函数里抽出来,统一用装饰器管理,让业务代码只写核心逻辑,不会被重复的校验、日志打乱,就像把水杯的防烫、防漏功能都用配套的套子实现,不用每个杯子单独做这些设计,代码自然更清爽。