TypeScript装饰器

TypeScript

介绍

1、装饰器本质是一种特殊的函数,它可以build:类、属性、方法进行扩展,同时能让代码更简洁。
2、装饰器自2025年在ES6中提出到现在,已将近10年。 3、截止目前,装饰器依然是实验性特性,需要开发者手动调整配置,来开启装饰器支持。
4、装饰器有5中:
1:类装饰器 2:属性装饰器 3:方法装饰器 4:访问器装饰器 5:参数装饰器 备注:虽然TypeScript5.0中可以直接使用类装饰器,但为了确保其它装饰器可以用,现阶段使用时,扔建议使用 experimentalDecorators (opens new window)配置来开启装饰器的支持,而且不排除在未来的版本中,官方会进一步 调整装饰的相关语法。

# 类装饰器

含义:类装饰器是一个应用在类声明上的函数,可以为类添加额外的工鞥呢,或添加额外的逻辑。
1、基础用法

    /*
        Demo函数会在Person类定义时执行
        参数说明: target参数是被装饰器的类,即:Person
    */
    function Demo(target: any) {
        console.log(target) // 会打印出Person
    }

    @Demo // 使用:装饰器装饰这个类, 相当于: 调用了Demo(Person) 传入了 Person 类
    class Person {
        name: string,
        age: number,
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

2、应用举例

    // 需求:定义一个装饰器,实现Person实例调用toString时返回JSON.stringify的执行结果?
    function CustomString(target) {
        target.prototype.toString = function() {
            return JSON.stringify(this) // 不能是target,因为target是类,这个地方应该是类的实例对象
        }
        // 对指定对象进行封锁
        Object.seal(target.prototype) // 相当于 target.prototype 这个对象进行封锁,不能随意进行修改、删除
    }

    @CustomString
    class Person {
        name: string,
        age: number,
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
    }
    const p1 = new Person('张三', 18)
    console.log(p1,toString())

    // @ts-ignore
    Person.prototype.x == 99 // @ts-ignore: 会忽略这一行的检查
    // 如果隐藏Object.seal(target.prototype)这行就可以添加x,否则不行会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

3、关于返回值 类装饰器 有 返回值:若类装饰器返回一个新的类,那这个新类将替换掉被装饰的类。
类装饰器 无 返回值:若类装饰器无返回值或返回 undefined,那被装饰的类不会被替换。

    // type Constructor  = new (...args: any[]) => {} 
    function Demo(target: Function) { // Function 类型太广泛,可以用 Constructor(只允许可能new关键字调用的类)
        return class {
            test() {
                console.log(200)
                console.log(300)
            }
        }
    }

    @Demo
    class Person {
       test() {
        console.log(100)
       }
    }
    console.log(Person)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 装饰器工厂

含义:是一个返回装饰器的函数的函数,可以为装饰器添加参数,可以更灵活的控制装饰器的行为

  interface Person{ // 具有合并行
    introduce(): void
  }
  function LogInfo(num: number) {
    return function(target: Function) { // return 的是 装饰器
        target.prototype.introduce = function() {
            for (let i = 0; i < num.length; i++) {
                console.log(`我的名字是${this.name},我的年龄是${this.age}`)
            }
        }
    }
  }  

  @LogInfo(1)  // 这样装饰器就可以传参了
  class Person {
    constructor(
        public name: string,
        public age: number
    ){}
    speak() {
        console.log('您好')
    }
  } 
  
  const p1 = new Person('张三', 18)
  p1.introduce()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 装饰器组合

    function LogInfo1(num: number) {
        return function(target: Function) { // return 的是 装饰器
            console.log('工厂:logInfo1')
        }
    } 
    function LogInfo2() {
        console.log('logInfo2')
    }  


    @LogInfo1() // 返回装饰器
    @LogInfo2
    class Person {
        constructor(
            public name: string,
            public age: number
        ){}
        speak() {
            console.log('您好')
        }
    }
    // 装饰器组合调用顺序:先【有上到下】的执行所有装饰器工厂,依次获取到装饰器,然后在【由下到上】执行所有装饰器
    /*
        输出:
        1、工厂:logInfo1
        2、logInfo2
        3、工厂:logInfo1
    */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 属性装饰器

    /*
        参数说明:
            target: 对于静态属性来说值就类,对于实例属性来说值就是累的原型对象
            propertyKey: 属性名
    */
    function Demo(target: object, propertyKey: string) { // target: 是Person类的原型对象   propertyKey: 就是name
        console.log(target, propertyKey)
    }

    class Person {
        @Demo name: string,
        age: number,
        static school: string // 如果 装饰器 装饰 school,target 就是 Person 类本身
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
        speak() {
            console.log('您好')
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 方法装饰器

    /*
        参数说明:
            target: 对于静态方法来说值就类,对于实例属性来说值就是类的原型对象
    */
    function Demo(target: any, propertyKey: any descriptor: PropertyDescriptor) { // PropertyDescriptor 官方提供
        console.log(target, propertyKey)
    }

    class Person {
       name: string,
        age: number,
        constructor(name: string, age: number) {
            this.name = name
            this.age = age
        }
        @Demo speak() {
            console.log('您好')
        }
         @Demo static isAdult() {
            console.log('您好')
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Last Updated: 2025/11/25 18:30:36