TypeScript學習8:高級類型-交叉類型、聯合類型

簡介

此爲高級類型的第一部分,學習交叉類型(Intersection Types)、聯合類型(Union Types)以及在使用以上類型時如何區分具體類型。javascript

交叉類型(Intersection Types)

交叉類型把幾個類型的成員合併,造成一個擁有這幾個類型全部成員的新類型。從字面上理解,可能會誤認爲是把取出幾個類型交叉的(即交集)成員。java

交叉類型的使用場景:Mixins、不適合用類來定義。es6

我感受,交叉類型和Mixins有一點區別:交叉類型只是一個類型聲明,用於類型約束;Mixins會給類增長成員,new對象時,對象會包含增長的成員屬性。

咱們看一看示例:post

改自官方示例,官方示例有2個小問題:會提示不存在屬性「hasOwnProperty」;另外, es6下prototype是不能夠枚舉的,沒法經過枚舉合併類屬性。
interface IAnyObject {
    [prop: string]: any
  }

  function extend<First extends IAnyObject, Second extends IAnyObject>(first: First, second: Second): First & Second {
    const result: Partial<First & Second> = {};
    for (const prop in first) {
      if (first.hasOwnProperty(prop)) {
        (result as First)[prop] = first[prop];
      }
    }
    for (const prop in second) {
      if (second.hasOwnProperty(prop)) {
        (result as Second)[prop] = second[prop];
      }
    }
    return result as First & Second;
  }

  interface IPerson {
    name: string,
    age: number
  }

  interface IOrdered {
    serialNo: number,
    getSerialNo(): number
  }

  const personA: IPerson = {
    name: 'Jim',
    age: 20
  }

  const orderOne: IOrdered = {
    serialNo: 1,
    getSerialNo: function () { return this.serialNo }
  }

  const personAOrdered = extend<IPerson, IOrdered>(personA, orderOne);
  console.log(personAOrdered.getSerialNo());
  • 其中First & Second就是交叉類型的寫法。
  • 經過擴展,能夠合併兩傳入對象的成員屬性,加強現有對象的能力。

聯合類型(Union Types)

聯合類型與交叉類型相似,均可以擁有多個類型的能力,區別是:聯合類型一次只能一種類型;而交叉類型每次都是多個類型的合併類型。學習

聯合類型在實際項目中,使用場景比交叉類型普遍得多。this

  • 字符串填充:
function padLeft(value: string, padding: number | string) {
    if (typeof padding === "number") {
      return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
      return padding + value;
    }
    return value;
  }

  padLeft("Hello world", 4);
  • 再舉個常見的例子,常量的聯合類型,五分制考試打分:
type Scores = 1 | 2 | 3 | 4 | 5;

  function rating(score: Scores) {
    console.log(`Set score ${score}`);
  }

  rating(3);
  // error
  // rating(6);

枚舉也能夠實現,可是這樣更簡潔。prototype

  • 還能夠用於可爲null的參數:
function f(sn: string | null): string {
    if (typeof sn === null) {
        return 'default';
    } else {
        return sn;
    }
}
  • 還可使用類型別名定義聯合類型(上面場景2中用過):
type Method = 'get' | 'post';

類型保護和類型區分

使用聯合類型時,咱們是沒法知道編譯時的具體類型的,因此在運行時必需要肯定類型。因此代碼中須要作類型保護和類型區分。code

爲何叫類型保護?由於在運行時,必須知道明確類型,不然可能會訪問一個不存在的成員屬性,致使程序出錯。對象

  • 自定義類型保護ip

    // 先判斷是否存在成員屬性
      if(pet.swim) {
          
      }
  • in操做符

    // 先判斷是否存在成員屬性
      if('swim' in pet) {
          
      }
  • typeof操做符

    function f(sn: string | number): string {
        if (typeof sn === 'number') {
            return sn.toString();
        } else {
            return sn;
        }
    }
  • instanceof操做符

    // 判斷實例原型
    if(pet instanceof Fish) {
          
    }
  • 類型斷言

    function f(sn: string | null): string {
        if (sn === null) {
            return "default";
        } else {
            return sn;
        }
    }

聯合類型應用極普遍,能夠多實踐。

相關文章
相關標籤/搜索