• 首页
  • 技术
  • 旅行
  • 车模
  • 关于

JZ's Blog

{技术, 绘画, 旅行, 摄影, 多肉}
  • 首页
  • 技术
  • 旅行
  • 车模
  • 关于
首页  /  未分类  /  TypeScript 中的装饰器
05 三月 2021

TypeScript 中的装饰器

作者:jz1108
未分类 写评论

简介

TypeScript 中的装饰器(Decorators)提供了一种实现注解(annotations)机制和元编程(meta-programming)的语法。

如果要使用装饰器这个特性,需要在编译 ts 时增加相应的配置。experimentalDecorators 需要配置为 true

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true
  }
}

装饰器可以用在如下场合:

  • 类定义(class declaration)
  • 方法(method)
  • 访问器(accessor)
  • 属性(property)
  • 参数(parameter)

类装饰器

我们先看一个简单的例子,看看装饰器是怎么用的以及能干什么事情。

@sealed
class Person {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log('Hello, my name is ' + this.name);
    }
}

在上面代码中,第一行的 @sealed 就是装饰器,用来装饰下一行的 Person 类型,从名字上看,sealed 应该是把和 Person 相关的对象密封了,但是具体行为是怎么样的还要看这个装饰器是如何实现的。

本质上讲,一个装饰器就是一个函数,不同类型的装饰器接受特定的参数。下面是 sealed 的具体实现:

function sealed(constructor: new(...args: any[]) => {}) {
    Object.seal(constructor);
    Object.seal(constructor.prototype);
}

这里,sealed 方法将构造函数以及构造函数的 prototype 属性都被密封了,从而禁止了对象的扩展。

接下来我们看看如何通过类装饰器重载原有的构造函数


function modifyConstructor<T extends new(...args: any[]) => {}>(constructor: T) {
    return class extends constructor {
        hometown = 'Beijing'
    };
}

@modifyConstructor
class Person {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log('Hello, my name is ' + this.name);
    }
}

interface ExtPerson extends Person {
    hometown: string;
};

const p = new Person('老三') as ExtPerson;
console.log(p.hometown); // Beijing

类装饰器写在类声明的前一行,可以用来修改或者替换原来的类构造函数。装饰器函数只接受一个参数,即类的构造函数。如果累装饰器函数有返回值,那么这个返回值将会做为新的构造函数替代原有的内容。
这里有两点需要注意:

  • 装饰器函数 modifyConstructor 使用了泛型用来描述参数类型,泛型 T 扩展了构造函数的基础类型定义。这样才能支持任意参数格式的构造函数。
  • 对于通过装饰器扩展的属性,ts 是无法获悉的,因此这里额外增加了一个接口声明 ExtPerson 来描述 p 的类型,否则使用 p.hometown 会提示错误。

 Previous Article iOS 13 Safari 的一些变化
Next Article   记录一次解决 no buffer is bound to enabled attribute 报错的过程

相关文章

  • 记录一次解决 no buffer is bound to enabled attribute 报错的过程

    2021年3月5日
  • 我在英格兰——第三日

    2017年11月12日
  • Vincent的一个翻译版本

    2014年3月4日

留言

取消回复

近期文章

  • 记录一次解决 no buffer is bound to enabled attribute 报错的过程
  • TypeScript 中的装饰器
  • iOS 13 Safari 的一些变化
  • WebGL 文章汇总
  • 高性能 WebGL —— 使用 ImageBitmap 提升纹理性能

近期评论

  • jz1108发表在《记录一次解决 no buffer is bound to enabled attribute 报错的过程》
  • xiangnan发表在《记录一次解决 no buffer is bound to enabled attribute 报错的过程》
  • lew发表在《WebGL绘制详解之五:Stencil Buffer》
  • jz1108发表在《WebGL基础绘制之一:绘制一个点》
  • jz1108发表在《WebGL 文章汇总》

文章归档

  • 2021年三月
  • 2019年十一月
  • 2019年九月
  • 2019年三月
  • 2018年十二月
  • 2018年十一月
  • 2018年十月
  • 2017年十一月
  • 2017年十月
  • 2017年九月
  • 2017年五月
  • 2017年四月
  • 2017年三月
  • 2017年二月
  • 2017年一月
  • 2016年十一月
  • 2016年十月
  • 2016年四月
  • 2016年三月
  • 2016年二月
  • 2016年一月
  • 2015年十二月
  • 2015年十一月
  • 2015年十月
  • 2015年九月
  • 2015年八月
  • 2015年七月
  • 2015年六月
  • 2015年三月
  • 2014年十二月
  • 2014年十一月
  • 2014年十月
  • 2014年八月
  • 2014年七月
  • 2014年六月
  • 2014年五月
  • 2014年四月
  • 2014年三月
  • 2014年二月
  • 2014年一月
  • 2013年十二月
  • 2013年十一月
  • 2013年十月
  • 2013年九月
  • 2013年八月
  • 2013年七月
  • 2013年六月
  • 2013年五月
  • 2013年四月
  • 2013年三月
  • 2013年二月
  • 2013年一月
  • 2012年十二月
  • 2012年十月
  • 2012年九月
  • 2012年七月
  • 2012年六月
  • 2012年五月
  • 2012年一月
  • 2011年十一月
  • 2011年十月
  • 2011年九月
  • 2011年八月
  • 2011年七月
  • 2011年六月
  • 2011年五月
  • 2011年四月
  • 2011年二月
  • 2011年一月
  • 2010年十二月
  • 2010年十月
  • 2010年九月
  • 2010年六月
  • 2010年五月
  • 2010年四月
  • 2010年三月
  • 2010年二月
  • 2010年一月
  • 2009年十二月
  • 2009年十一月
  • 2009年九月
  • 2009年八月
  • 2009年六月
  • 2009年三月
  • 2009年二月
  • 2009年一月

分类目录

  • 地图API
  • 多肉
  • 开发
  • 技术
  • 摄影
  • 旅行
  • 未分类
  • 汽车
  • 绘画
  • 美食
  • 车模
  • 随笔

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org
© Copyright 2015. Theme by BloomPixel.