分享几个TypeScript泛型的使用场景

最近使用TypeScript写了一个项目,过程当中不断感觉到TypeScript的魅力,如今来分享几个业务中关于泛型的场景数组

1. 深度Partial

TS内置了一个Partial类型,用于把一个类型的成员属性设置为成可选模式,例如编辑器

type Person = {
  name: string;
  age: number;
}

Person类型中有两个成员属性,若是咱们要把这个类型赋予变量tom,那tom必须拥有nameage两个属性函数

let tom:Person = {
    name: 'tom',
    age: 20
};

如今咱们要让Person的两个属性都变为可选,能够使用Partial类型进行转换学习

type PartialPerson = Partial<Person>;

let partialPerson: PartialPerson = {
  name: 'tom'
};

这时PartialPersonnameage属性都已经变为可选的了,可是若是咱们在Person中再加一点东西this

type Person = {
  name: string;
  age: number;
  contact: {
    email: string;
    phone: number;
    wechat: string;
  }
}

如今咱们加入了一个contact属性值是一个对象,若是咱们想把contact里面的属性也变为可选Partial就不灵了spa

clipboard.png

能够看到Partial是把contact变成了可选而不是里面的属性,插个题外话一般的作法是为contact另外建立一个类型,若是是这样的话Partial就能够用了,可是咱们不使用这种方法,咱们先来看看TS是怎么定义Partialcode

/**
 * Make all properties in T optional
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};

很容易理解关键点是在?:上,如今咱们改造一下对象

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends Object ? DeepPartial<T[P]> : T[P];
}

能够看到改造的DeepPartialPartial差异在把直接赋值T[P]换成了T[P] extends Object ? DeepPartial<T[P]> : T[P], 即判断T的属性P的类型是不是Object而后进行再次DeepPartial或者返回T[P]的类型ip

clipboard.png
这时编译器就不会再提示错误了文档

2. 更智能的array_column函数

在PHP中有一个array_column函数,用于在数组中提取一列的内容,用JavaScript表现就是

function array_column(arr, key) {
  return arr.map(item => item[key])
}

假如如今有一个persons数组

type Person = {
  name: string;
  age: number;
}

let persons: Person[] = [];

咱们须要提取数组中的name属性,能够很方便的使用Array.map方法提取,可是若是又有别的数组须要提取,咱们能够实现一个更优雅的array_column函数

function array_column<T, K extends keyof T>(input: T[], key: K) {
  return input.map(item => item[key])
}

如今咱们使用这个函数提取persons数组

clipboard.png
能够看到当咱们输入persons时,编辑器已经推断出了key的类型,再来一个animals数组

clipboard.png

3. Proxy

在刚开始学习TS的时候看官方文档有一个Proxy的例子,只给出了类型声明但却没有给出实现,当时花了很多时间琢磨,如今来实现它

class Proxy<T>{
  constructor(private data: T) { }

  get<K extends keyof T>(key: K) {
    return this.data[key]
  }

  set<K extends keyof T, V extends T[K]>(key: K, value: V) {
    this.data[key] = value;
  }
}

能够看到Proxy类提供了getter方法getsetter方法set,如今咱们基于上面的Person类型建立一个Proxy实例

let person: Person = {
  name: 'tom',
  age: 18
};

let proxy = new Proxy(person);

如今咱们来看看调用get方法

clipboard.png
能够看到编辑器也推断出了参数key的类型,再来看看set方法

clipboard.png
get方法同样,编辑器也推断出了参数key的类型,同时也推断出了参数value的类型为string

相关文章
相关标签/搜索