装饰器
@ 符号后面跟的一定是函数或者返回函数
类装饰器
类装饰器接收一个参数,参数是类的本身,所以可以在其原型上新增方法或者属性。有两种返回类型:
- void:没有返回值时类的行为不会被返回值影响
- new Class:返回一个新类,原本的类会被替换,一般不这么做,倾向给原型添加方法或者重写原来的方法
const classDecorator:ClassDecorator = (target: Function) => {
console.log('类装饰器')
target.prototype.getName = (name:string) => {
return '装饰器:' + name;
}
}
function classDecoratorFun (age: number) {
console.log('工厂函数:', age)
// return classDecorator
// 目前只知道以闭包的形式访问工厂函数的变量
return (target: Function) => {
console.log('类装饰器:', age)
target.prototype.getName = (name:string) => {
return '装饰器:' + name;
}
}
}
// @classDecorator
@classDecoratorFun(18)
class Person {
public getName(name:string){
return '类:' + name
}
}
const p1 = new Person()
console.log(p1.getName('先执行装饰器方法')) //装饰器:先执行装饰器方法
方法装饰器
接收3个参数:原型对象(实例方法)或构造函数(静态方法)、方法名字、成员属性描述符
成员属性描述符:
- value:方法引用地址,可以用来重写原本方法;
- writable:true 代表属性可修改;
- enumerable:true 代表可以枚举,即可以 fou 遍历出成员的键值:getName;
- configurable:设置是否可设置属性特性,默认为 true。如果为 false,将无法删除该属性,不能够修改属性值,也不能修改属性的属性描述符.
注:设置没有效果,原因未知
const methodDecorator:MethodDecorator = (...args: any[]) => {
//实例方法=>原型对象
// args[0].testFun() // 调用原型的方法
// console.log('属性key:', args[1]) // getName
// args[2]:描述符'
args[2].value = function () {
console.log('重写实例方法')
}
}
function methodDecoratorFun (age: number) {
console.log('工厂函数:', age)
// return methodDecorator
// 目前只知道以闭包的形式访问工厂函数的变量
return (prop: any, key: string | symbol, desc: PropertyDescriptor) => {
// 静态方法=>构造函数
let p2 = new prop('测试2')
console.log('静态方法=>构造函数:', p2)
// console.log('属性key:', key) // getName
desc.value = function () {
console.log('重写静态方法:', age)
}
}
}
class Test {
testFun () {
console.log('调用原型的方法')
}
}
class Person extends Test {
name: string;
constructor (name: string) {
super()
this.name = name
}
@methodDecorator
getName(){
console.log('原来方法:', this.name)
}
@methodDecoratorFun(18)
static getAge (age:number) {
console.log('静态方法:', age)
}
}
const p1 = new Person('测试1')
p1.getName()
Person.getAge(28)
属性装饰器
和方法装饰器参数类似,但是第3个参数是 undefined
const propertyDecorator:PropertyDecorator = (...args: any[]) => {
//实例属性=>原型对象
args[0].Test()// Test
console.log('属性key:', args[1]) // name
}
function propertyDecoratorFun (age: number) {
console.log('工厂函数:', age)
// return methodDecorator
// 目前只知道以闭包的形式访问工厂函数的变量
return (prop: any, key: string | symbol) => {
// 静态方法=>构造函数
prop[key] = age
console.log('静态方法=>构造函数:', prop[key]) // 18
console.log('属性key:', key) // getName
}
}
class Person {
// @propertyDecorator
name?: string;
@propertyDecoratorFun(18)
static age = 28
constructor (name: string) {
this.name = name
}
Test () {
console.log('给原型添加方法')
}
}
const p1 = new Person('测试1')
参数装饰器
第一个参数和方法装饰器一样,第2个是方法名称而不是参数名称,第三个参数是参数的下标值
const parameterDecorator:ParameterDecorator = (...args: any[]) => {
//实例方法参数=>原型对象
console.log(args[0])
console.log('方法名称:', args[1]) // showInfo
console.log('参数下标:',args[2]) // 1
}
function parameterDecoratorFun (age: number) {
console.log('工厂函数:', age)
// return methodDecorator
// 目前只知道以闭包的形式访问工厂函数的变量
return (prop: any, key: string | symbol, index: number) => {
// 静态方法=>构造函数
console.log(prop)
console.log('方法名称:', key) // showInfo
console.log('参数下标:', index) // 1
}
}
class Person {
name?: string;
constructor (name: string) {
this.name = name
}
// showInfo (age: number, @parameterDecorator sex: string) {}
static showInfo (age: number, @parameterDecoratorFun(18) sex: string) {}
}
const p1 = new Person('测试1')
访问装饰器
参数:
- 静态成员:构造函数,实例成员:原型对象;
- 成员的名字;
- 成员的属性描述符 只能作用于 get、set 访问器,属性修饰符的 get、set 只有这种情况才会有值,其他情况 undefine
function getConfigName(descirbe?:string){
return function(target:any,propertyKey:string,descriptor:PropertyDescriptor){
const get = descriptor.get
descriptor.get = function(){
return `${descirbe||""}${(get as any).call(this)}`
}
}
}
class ConfigMan {
private _name:string
private _age:number
constructor(_name:string,_age:number){
this._name = _name
this._age = _age
}
@getConfigName("这是姓名:")
get name():string {
return this._name
}
@getConfigName("这是年龄:")
get age():number {
return this._age
}
}
let configMan = new ConfigMan("jack",19)
console.log(configMan.name);
console.log(configMan.age);
>>这是姓名:jack
>>这是年龄:19
内置工具类型:
- ReturnType:提取函数返回类型
- ConstructorParameters:提取构造函数参数的类型
- Parameters:提取函数参数的类型
- NonNullable:过滤类型中的 null 和 undefined
- Omit:过滤对象类型中指定的属性类型,代码原理还不理解
- Pick:和 Omit 相反,提取对象类型中指定属性类型
- Extract:提取类型交集
- Exclude:和 Extract 相反
- Record:定义一个对象类型,Record<string, number>,键是 string,值是 number
- Readonly:将对象类型的所有属性设为只读,注意顶层属性生效
- Require:将对象类型的所有可选类型变成必须,注意顶层属性生效
- Partial:将对象类型的所有必须类型变成可选,注意顶层属性生效
不理解用法
- ThisType:指定 this 类型
- OmitThisParameter:移除 this 参数类型
- ThisParameterType:提取函数类型中 this 参数的类型
- NoInfer:提醒编译器不进行类型推断
- InstanceType:提取构造函数类型
- infer