xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

TypeScript @decorator in depth

TypeScript @decorator in depth

@decorator


function log(...args: any): void {
  console.log('decorator', args)
}

@log('abc')
class Test {
  constructor() {
    console.log('app');
  }
}

const test = new Test();


Reflect & Object.defineProperty


"use strict";

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    // ✅
    console.log('decorators =', decorators);
    console.log('target =', target);
    console.log('key =', key);
    console.log('desc =', desc);
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};

var __metadata = (this && this.__metadata) || function (k, v) {
    // ✅
    console.log('(k, v =', k, v);
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};

function log(...args) {
    console.log('decorator', args);
}

let Test = class Test {
    constructor() {
        console.log('app');
    }
};

Test = __decorate([
    log('abc'),
    __metadata("design:paramtypes", [])
], Test);

const test = new Test();

https://www.typescriptlang.org/play?target=2#code/GYVwdgxgLglg9mABAGzgcwBQDocEMBOaAzgFyK5gCeAlGQG5wwAmiA3gFCKIQJFzIBTLKkwByJgJ75cUOPlEAacoSLV2AX3bsAAiIyjcAIwii1EZLiJFEAFQFEobTt15R8IaHIzUnXLjzA+QWF0fVwAB3DTAG5nTU12AIdEKHtHAF5EMAEAd1s071igA

@decorator()



DecoratorFactory

// js function 科里化 / js 高阶函数
function DecoratorFactory(...params: any) {
  console.log('\nparams =', params, 0);
  // new 表示包含构造函数 (ES6 class / ES5 constructor function)
  return function <T extends new (...args: any[]) => any>(passedClass: T) {
    return class extends passedClass {
      name: string;
      constructor(...args: any[]) {
        super();
        this.name = args[0] + '👻';
        console.log('this.name =', this.name, 2);
        console.log('...args', args, 3);
      }
    }
  }
}

const App = DecoratorFactory('xgqfrms')(
  // 传入 class 作为参数
  class {
    name: string;
    constructor(name: string) {
      this.name = name;
      console.log('app name =', name, 1);
    }
  }
);


const app = new App('xgqfrms');
console.log('app =', app);

https://www.typescriptlang.org/play?target=2#code/PTAECsGdQMwVwHYGMAuBLA9g0hFz0DOJgaMqhhSiAbWYGxpgv4qAOpgFDzLpagAiApkhgE4CGKPAGK9UPAJ4AKAHQyADrz4BbSAC5QvBGICUoAN51QoLgkgYANuylmMAcwkByADoJ5S6AF57AGlCveynwAGLQBuA2IwBHYAd1BACwjALk9AUGVAahVAEPNAAgTaUAkAUQBlADYjM15IaDACgFYjLEgUbjhRblhEVEwELXDudhQ4bmxGdpYAHgAVUHYADxR2BAATaCjY6RkFG1V1TQBtAF0ddwA+LbFDiXly9nmAYVLytTGdfUNDHr6BkrLoadmF6AvIFdbl89OEXqAEP52Gp6tw0AgbGFwYZjLCmgJuKspOtNhoxHsnmDkZA4LJ2JjQkTwSgABZoSBSSGKdigdzqbgbbaBXagADUoHsgF4NwDeO-YkciUXVzJZrHZ7LT6YyoazvKAFQymewfAAmSkSyUmaVWWwOGTYjmQVU4nwAZj1yIAvkSnYYnU66KiUKAAIKyWSsticHj8IQiDGSexTGwARxg3GU9i0EnCIFAgAJ5QCmip9yqBADrygC45QBDyvQUXdoM8XpqYQ14YiiZ7Gs0JFXQLDa4SJeqlcyA5rxeDUUbZQ5eH6IcrPD5NT4AIz213hJ2Uugeupe0f+tnLH1+hxR2Pxy2UwcWY1yjcqnwb0JAA

class decorator

fields decorator

// Decorator function return type is 'PropertyDescriptor' but is expected to be 'void' or 'any'.ts(1271)
function fieldDecorator(target: any, prop: string): any {
  console.log('target: =', target);
  console.log('prop =', prop);
  // 修改的是原型链上属性
  target[prop] = 'prototype prop value 👻';
  // 手动返回新的 description, 替换原来的属性描述符
  const description: PropertyDescriptor = {
    // writable: false,
    value: '👻',
    // Uncaught TypeError: Cannot assign to read only property 'name' of object '#<App>'
  }
  return description;
}

class App {
  @fieldDecorator
  name: string = 'default';
  constructor(name: string) {
    this.name = name;
  }
}

const app = new App('xgqfrms');
// app.name = '2022';
console.log('app =', app);
console.log('app.name =', app.name);
console.log('app.__proto__.name =', (app as any).__proto__.name);


accessor decorator

methods decorator

static methods decorator

refs



©xgqfrms 2012-2020

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-04-15 23:45  xgqfrms  阅读(95)  评论(3编辑  收藏  举报