TypeScript 装饰器入门核心用法

一、什么是装饰器?

装饰器就是普通函数 ,用 @装饰器名 贴在类、方法、属性上,作用就是给被装饰的东西加额外功能,仅此而已。

二、最基础用法:类装饰器

直接贴在类上,函数唯一参数是被装饰类的构造函数,最简单的例子:给类加静态属性。

typescript 复制代码
// 定义装饰器函数:给类加版本号
function addVersion(target) {
  target.version = '1.0.0'; // 给类挂载静态属性
}

// 用@贴在类上,完成装饰
@addVersion
class MyClass {}

// 直接使用装饰器加的属性
console.log(MyClass.version); // 输出:1.0.0

核心逻辑:@addVersion 等价于 addVersion(MyClass),把类传给装饰器函数就行。

三、最常用用法:方法装饰器

贴在类的方法上,日常用得最多,函数有 3 个固定参数:不用死记含义,跟着案例用就会。

简单案例1:给方法加日志

执行方法时,自动打印"方法被调用了",不用在方法里写重复代码。

typescript 复制代码
// 方法装饰器:打印方法调用日志
function showLog(target, name, descriptor) {
  // 保存原方法
  const oldFn = descriptor.value;
  // 重写方法,加日志逻辑
  descriptor.value = function() {
    console.log(`【日志】${name}方法被调用了`);
    oldFn.apply(this); // 执行原来的方法
  };
}

class MyClass {
  // 装饰器贴在方法上
  @showLog
  sayHi() {
    console.log('hello TS');
  }
}

new MyClass().sayHi();
// 输出:【日志】sayHi方法被调用了 → hello TS

简单案例2:禁止方法被修改

让方法只读,不能被重新赋值,避免误改方法逻辑。

typescript 复制代码
// 方法装饰器:禁止方法修改
function noChange(target, name, descriptor) {
  descriptor.writable = false; // 设为不可写
}

class MyClass {
  @noChange
  fn() {
    console.log('不能改我');
  }
}

const obj = new MyClass();
obj.fn = () => {}; // 报错:无法分配到 "fn",因为它是只读属性

四、属性装饰器:给属性加默认值

贴在类的属性上,函数有 2 个参数,最简单的用法:给属性设置默认值,不用在构造函数里初始化。

typescript 复制代码
// 属性装饰器:设置默认值
function setDefault(val) {
  return function(target, name) {
    target[name] = val;
  };
}

class MyClass {
  // 贴在属性上,传默认值
  @setDefault('张三')
  name;

  @setDefault(20)
  age;
}

console.log(new MyClass().name); // 输出:张三
console.log(new MyClass().age); // 输出:20

五、装饰器工厂:给装饰器传参

想给装饰器传自定义参数(比如日志加前缀、默认值自定义),就写装饰器工厂------本质是「返回装饰器的函数」,写法超简单,看案例就会。

案例:带前缀的日志装饰器

让日志有自定义前缀,不用写多个装饰器函数。

typescript 复制代码
// 装饰器工厂:接收自定义前缀
function log(prefix) {
  // 返回真正的装饰器函数
  return function(target, name, descriptor) {
    const oldFn = descriptor.value;
    descriptor.value = function() {
      console.log(`【${prefix}】${name}方法执行了`);
      oldFn.apply(this);
    };
  };
}

class MyClass {
  // 传参使用:自定义前缀"接口请求"
  @log('接口请求')
  getData() {}

  // 传参使用:自定义前缀"操作"
  @log('操作')
  saveData() {}
}

new MyClass().getData(); // 输出:【接口请求】getData方法执行了
new MyClass().saveData(); // 输出:【操作】saveData方法执行了

六、必记规则:多个装饰器的执行顺序

一个类/方法上贴多个装饰器时,从下往上执行------谁离被装饰的东西近,谁先执行。

typescript 复制代码
// 定义两个简单装饰器
function A(target) {
  console.log('执行装饰器A');
  return target;
}
function B(target) {
  console.log('执行装饰器B');
  return target;
}

// B离类更近,先执行;A后执行
@A
@B
class MyClass {}

// 运行结果:先打印「执行装饰器B」,再打印「执行装饰器A」

等价理解:MyClass = A(B(MyClass)),先执行内层的 B,再执行外层的 A。

七、使用前提:开启TS配置

装饰器是 TS 实验性特性,必须在 tsconfig.json 里加一行配置,否则报错,就加这一个核心项就行:

json 复制代码
{
  "compilerOptions": {
    "experimentalDecorators": true, // 必须开启,启用装饰器
    "target": "ES5" // 项目基本配置,一般都有
  }
}
相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax