分享幾個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

相關文章
相關標籤/搜索