装饰器:能够带来额外的信息量,达到分离关注点的目的
- 关注点的问题,在定义某个东西的时候,应该最清楚该东西的情况
- 重复代码的问题
- 问题产生的根源:某些信息在定义时,能够附件的信息量有限
作用:能到为某些属性,类,参数,方法提供元数据信息
本质: 在JS 中,装饰器就是一个函数。(是会参与运行的)
在TS中使用装饰器需要开启”experimentalDecorators”: true
使用装饰器 @装饰器(一个函数)
可以有多个装饰器进行修饰
类装饰器
类装饰的本质是一个函数,该函数接收一个参数,表示类本身(构造函数本身)
将变量定义为类的方法:Function, new () => object
装饰器函数的运行时间,在类定义后直接运行
类装饰器具有的返回值:
- void
- 返回一个新的类,会将新的类替换掉装饰器目标
多个装饰器的情况: 会按照后加入先调用的顺序进行调用
function test(target: new (...args: ang[]) => object){console.log(target)}@testclass U {loginid:string; //账号,验证规则:1.必填, 2.必须是3-5个字符loginPwd:string;}
成员装饰器
属性装饰器是一个函数,该函数需要两个参数;
1. 如果是静态属性,则为类本身,如果是实例属性,则为类的原型<br /> 2. 固定为一个字符串,表示属性名
方法装饰器也是一个函数,该函数需要三个参数:
1. 如果是静态方法,则为类本身,如果是实例方法,则为类的原型<br /> 2.固定为一个字符串,表示方法名<br /> 3. 属性描述对象
function test(target:any,key:string){console.log(target === A.prototype,key)}class A {@testprop:string@teststatic name:string}
类和属性的描述
//装饰器工厂function classDesciptor(description:string){return function(target:Function){//保存到该类的原型之中target.prototype.$classDescript = description}}function propDescriptior(description:string){return function (target:any,propName:string){//把所有属性信息保存在该类的原型中if(!target.$propDescriptions){target.$propDescriptions = []}target.$propDescriptions.push({propName,descriotion})}}function printObj(obj:object){//输出类的名字if(obj.$classDescription){console.log(obj.$classDescription)}else{console.log(Object.getPrototypeof(obj).cunstuctor.name)}if(!obj.$propDescriptions){obj.$propDescriptions = [];}//输出所有的属性描述和属性值for(const key in obj){if(obj.hasOwnProperty(key)){const prop = obj.$propDescriptions.find((p:any) => p.propName === key)if(prop){console.log('\t${prop.description}:${obj[key]}')}else{console.log('\t${key}:${obj[key]}')}}}}@classDescriptor("文章")class Article {@propDescriptor("标题")title:string;@propDescriptor("内容")content:string;@propDescriptor("日期")date:Date;}const newAr = new Article();newAr.title = "好日子"newAr.content = "今天天气真好"newAr.date = new Date;printObj(newAr)
reflect-metadata库
安装 yarn add reflect-metadata
保存元数据的库
https://www.npmjs.com/package/reflect-metadata
import "reflect-metadata"const key = Symbol.for('desciptor');function desciptor(description:string){return Reflect.metadata(key,description)}function printObj(obj:object){const getProtoObj = Object.getPrototypeOf(obj)//输出类的名字if(Reflect.hasMetadata(key,getProtoObj)){console.log(Reflect,getMetadata(key,getProtoObj))}else{console.log(getProtoObj.cunstuctor.name)}//输出所有的属性描述和属性值for(const prop in obj){if(Reflect.hasMetadata(key,obj,prop)){console.log('\t${Reflect.getMetadata(key,obj,prop)}:${obj[prop]}')}else{console.log('\t${prop}:${obj[prop]}')}}}@desciptor("文章")class Article {@desciptor("标题")title:string;@desciptor("内容")content:string;@desciptor("日期")date:Date;}const newAr = new Article();newAr.title = "好日子"newAr.content = "今天天气真好"newAr.date = new Date;printObj(newAr)
class-validator
https://www.npmjs.com/package/class-validator
class-transformer
https://www.npmjs.com/package/class-transformer
参数装饰器
依赖注入,依赖倒置
要求函数有三个参数:
- 如果是静态方法,则为类本身,如果是实例方法,则为类的原型
- 方法名称
- 在参数列表中的索引 ```javascript class myMath{ sum(a:number, @test b:number){ return a + b } }
function test(target:any,method:string,index:number){ console.log(target,method,index) }
<a name="xaBWo"></a>### 关于TS 自动注入的元数据如果安装了```reflect-metadata```,并且导入了该库,而且在某个成员上添加了元数据,同时也启用了```emitDecoratorMetadata:true```<br />则TS在编译结果中,会将约束的类型,作为元数据加入到对应的位置中<br />可以让TS的类型检查(约束)将有机会在运行时进行。<a name="vnA2Y"></a>### AOP属于面向对象开发的编程方式<br />将一些在业务中共同出现的功能块,横向切分,已达到分离关注点的目的<a name="WbIXt"></a>### 类型演算根据已知的信息,计算出新的类型三个关键字 :- typeof : TS中的typeof,书写的位置在类型约束的位置上面就表示获取某 个数据的类型当typeof作用与类的时候,得到的类型就是该类型的构造函数```javascriptclass U {name:String,age:number}function createUser(cls: typeof U):U {return new cls();}const Us = createUser(U)
keyof: 作用与类,接口,类型别名(联合类型)用于获取其他类型中的所有成员名组成的联合类型
interface U {loginId: stringloginPwd: stringname: string}function printUser(obj:U, prop: typeof U){console.log(obj[prop]);}const user:U {loginId:'ssfff',loginPwd:"11wss",name:"1122"}printUser(user,'name')
in ```javascript interface Article{ title:string, content: string, date: string, }
type Readonly
const A: Readonly
<a name="42e65168"></a>### TS 类型演算```javascriptPartial<T> // 将类型T中的成员变成可选Required<T> // 将类型T中的成员变成必填Readonly<T> // 将类型T中的成员变成只读Exclued<T,U> // 提取T中可以赋值给U的类型NonNullable<T> // 从T中剔除Null 和 undefinedReturnType<T> // 获取函数返回值类型InstanceType<T> // 获取构造函数类型的实例类型
