TypeScript (三)

162 阅读2分钟

事前准备

  • npm init -y
  • tsc --init
  • npm install ts-node --save-dev
  • npm install typescript --save
  • package.json 配置 "dev": "ts-node ./src/index.ts"

类的装饰器(一)

  • 我们有一个calss类,对类做修饰
  • 什么时候执行,他会在class类创建好之后,立即就去执行这个装饰器@,不是每次实例化的时候才执行
const test = new Test();
(test as any).getName();
装饰器本身是一个函数
类装饰器接受的参数是构造函数
装饰器通过 @ 符号来使用

装饰器是实验性语法,需要打开tsconfig.json里的配置项
"experimentalDecorators": true
"emitDecoratorMetadata": true

// 方法一
 function testDecorator(constructor: any) {
     constructor.prototype.getName = () => {
         console.log()
     }
 }
 // 方法二
 function testDecorator(flag: boolean) {
     if(flag) {
         return function (constructor: any) {
             constructor.prototype.getName = () => { 
                 console.log() 
             }
         }
     }else{
         return function (constructor: any) {}
     }
 }
 
@testDecorator(true)
class Test{}

const test = new Test();
(test as any).getName()

类的装饰器(二)

function testDecorator() {
    return function <T extends new (...arg: any[]) => any> (constructor: T) {
        return class extends constructor { 
            name = 'duke',
            getName() { return this.name }
        } 
     }
}
 
const Test = testDecorator()(
    class {
        name: string,
        constructor(name: string) { this.name = name }
    }
)

const test = new Test('jack');
// (test as any).getName();
test.getName();

方法装饰器

// 普通方法,target对应的是类的prototype
// 静态方法,target对应的是类的构造函数    
function getNameDecorator(target:any, key:string, descriptor: PropertyDescriptor ) {
    // getName不能被重写
    descriptor.writable = false;
    // 对方法的变更
    descriptor.value = function() {
        return "over"
    }  
}

class Test {
    name: string,
    constructor(name: string) { this.name = name }
    
    @getNameDecorator
    getName() { return this.name }
}
const test = new Test('jack');

访问器的装饰器

  • get 和 set 不能同时加 decorator,不然会报错
function visitDecorator(target:any, key:string, descriptor: PropertyDescriptor ) {
    // name不能被修改
    descriptor.writable = false;
 }

class Test {
    private _name: string,
    constructor(name: string) { this._name = name }
    get name() { return this._name }
    
    @visitDecorator
    set name(name: string) { this._name = name }
}
const test = new Test('jack');
test.name = "over"

属性的装饰器

  • 只能接受2个参数 target and key
function nameDecorator(target:any, key:string): any {
   const descriptor: PropertyDescriptor = {
       writable: false
   }
   // 修改的并不是实例上的 name, 而是原型上的 name
   targrt[key] = 'dragon'
   
   return descriptor
 }
 
 // name是放在实例上的,并不是在原型上
 class Test {
     @nameDecorator
     name = string,
 }
 const test = new Test('jack');

参数装饰器

// 原型,方法名,参数所在的位置
function paramDecorator (target:any, method:string, paramIndex:number) { }
class Test {
    getInfo(@paramDecorator name:string, age:number) {}
}

const test = new Test();
test.getInfo('jack', 30)

装饰器实际使用的小例子

const userInfo: any = undefined;

function catchError(target:any, key:string, descriptor: PropertyDescriptor ) {
    const fn = descriptor.value;
    descriptor.value = function() {
        try{
            fn()
        }catch(e){
            console.log("有错误")
        }
    }
}

class Test {
    @catchError
    getName() {
        return userInfo.name
    }
}

结语

前端react QQ群:788023830 ---- React/Redux - 地下老英雄

前端交流 QQ群:249620372 ---- FRONT-END-JS前端

(我们的宗旨是,为了加班,为了秃顶……,仰望大佬),希望小伙伴们加群一起学习