<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    TypeScript 中的泛型你真搞懂了嗎?

    共 3389字,需瀏覽 7分鐘

     ·

    2021-11-04 21:36

    點擊上方?程序員成長指北,關(guān)注公眾號

    回復(fù)1,加入高級Node交流群

    在學(xué)習(xí)ts源碼的時候,發(fā)現(xiàn)很多泛型還是看不懂,于是想寫一篇文章,總結(jié)一下常用的泛型。

    基礎(chǔ)必備知識

    聯(lián)合類型vs交叉類型

    //?聯(lián)合類型
    interface?Bird?{
    ??name:?string;
    ??fly():?void;
    }
    interface?Person?{
    ??name:?string;
    ??talk():?void;
    }
    type?BirdPerson?=?Bird?|?Person;
    let?p:?BirdPerson?=?{?name:?"zfeng",?fly()?{}?};?
    let?p1:?BirdPerson?=?{?name:?"zfeng",?talk()?{}?};

    聯(lián)合類型使用 “|”表示或的關(guān)系, 滿足其中的一個情況即可。

    interface?Bird?{
    ??name:?string;
    ??fly():?void;
    }
    interface?Person?{
    ??name:?string;
    ??talk():?void;
    }
    type?BirdPerson?=?Bird?&?Person;
    let?p:?BirdPerson?=?{?name:?"zhufeng",?fly()?{},?talk()?{}?};

    交叉類型使用“&”,表示與的關(guān)系,需要滿足所有的情況。

    內(nèi)置條件類型

    type?Extract?=?T?extends?U???T?:?never;
    type?Exclude?=?T?extends?U???never?:?T;
    type?NonNullable?=?T?extends?null?|?undefined???never?:?T;

    type?N?=?NonNullable<string?|?number?|?null?|?undefined>;//?刪除null和undifined;
    type?E?=?Exclude<string?|?number,?string>;?//?排除關(guān)系?輸出?string;
    type?I?=?Extract<string?|?number,?string>;?//?包含關(guān)系?輸出?number;

    函數(shù)的類型推斷

    獲取函數(shù)返回值的類型

    type?ReturnType?=?T?extends?(...args:?any[])?=>?infer?R???R?:?any;

    function?getUserInfo(name:?string,?age:?number)?{
    ??return?{?name,?age?};
    }
    type?UserInfo?=?ReturnType<typeof?getUserInfo>;

    const?userA:?UserInfo?=?{
    ??name:?"zhufeng",
    ??age:?10,
    };

    獲取函數(shù)參數(shù)的類型

    type?Parameters?=?T?extends?(...args:?infer?R)?=>?any???R?:?any;
    function?getUserInfo(name:?string,?age:?number)?{
    ??return?{?name,?age?};
    }
    type?T1?=?Parameters<typeof?getUserInfo>;??//?[name:?string,?age:?number]


    泛型進階

    很多人對于泛型的理解還停留在基礎(chǔ)的層面,我講站在集合的視角去理解一下什么叫泛型。

    案例一:字段的提取

    給定一個接口 Persion, ?里面有name,age,visiable,三個字段,現(xiàn)在的要求是:得到一個新的接口,里面只有name,age。一般人常見的思路:

    interface?Person?{
    ??name:?string;
    ??age:?number;
    ??visiable:?boolean;
    }

    interface?Person1?{
    ??name:?string;
    ??age:?number;
    }

    我們從寫一個接口,就可以達到要求。但是這樣子的寫法,顯得十分冗余。其實ts提供了方法,讓我們可以實現(xiàn),讓我們一起看一下的例子。

    方式一:Pick 提取字段

    //?pick?的原理
    //?type?Pick?=?{?[P?in?K]:?T[P]?};
    interface?Person?{
    ??name:?string;
    ??age:?number;
    ??visiable:?boolean;
    }
    type?Person1?=?Pick'name'|'age'>?;

    Person1 就包含 name,age 字段。

    方式二:Omit 反向獲取

    interface?Person?{
    ??name:?string;
    ??age:?number;
    ??visiable:?boolean;
    }
    type?Exclude?=?T?extends?U???never?:?T;
    type?Omitextends?keyof?T>?=?Pick>;
    type?Person2?=?Omit"age">;

    案例二:兩個接口的操作

    我們把一個接口當作一個集合,那么兩個集合的操作主要有:并集,交集,差集。

    交集

    type?Extract?=?T?extends?U???T?:?never;
    type?Intersectionextends?object,?U?extends?object>?=?Pick<
    ??T,
    ??Extract?&?Extract
    >;

    type?C1?=?{?name:?string;?age:?number;?visible:?boolean?};
    type?C2?=?{?name:?string;?age:?number;?sex:?number?};

    type?C3?=?Intersection;

    交集的定義:對于給定的兩個集合,返回一個包含兩個集合中共有元素的新集合。通過Intersection實現(xiàn)交集,可以獲得一個新接口,C3只包含 name.age。如上圖。

    差集

    type?Exclude?=?T?extends?U???never?:?T;
    type?Diffextends?object,?U?extends?object>?=?Pick<
    ??T,
    ??Exclude
    >;

    type?C1?=?{?name:?string;?age:?number;?visible:?boolean?};
    type?C2?=?{?name:?string;?age:?number;?sex:?number?};

    type?C11?=?Diff;

    差集的定義:對于給定的兩個集合,返回一個包含所有存在于第一個集合且不存在于第二個集合的元素的新集合。通過Diff實現(xiàn)差集,可以獲得一個新接口,接口只有visiable。如上圖。

    并集

    并集的定義:對于給定的兩個集合,返回一個包含兩個集合中所有元素的新集合。通過Merge實現(xiàn)并集,可以獲得一個新接口,接口包含C1,C2 的所有屬性。如上圖。

    //Compute的作用是將交叉類型合并
    type?Computeextends?any>?=?A?extends?Function???A?:?{?[K?in?keyof?A]:?A[K]?};
    type?Omit?=?Pick>;
    type?Mergeextends?object,?O2?extends?object>?=?Compute>;
    type?C1C2?=?Merge;

    特殊的情況:Overwrite(覆蓋)

    type?C1?=?{?name:?string;?age:?number;?visible:?boolean?};
    type?C2?=?{?name:?string;?age:?string;?sex:?number?};

    C1,C2做merge, C1中有age,類型為number,C2中有age,類型為string,那么合并之后,age是string,還是number類型呢?

    Overwrite 泛型,解決了誰覆蓋誰的問題。

    type?C1?=?{?name:?string;?age:?number;?visible:?boolean?};
    type?C2?=?{?name:?string;?age:?string;?sex:?number?};

    type?Overwrite<
    ??T?extends?object,
    ??U?extends?object,
    ??I?=?Diff?&?Intersection
    >?=?Pick;
    ??
    type?overwrite?=?Overwrite;


    Node 社群


    我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。


    ???“分享、點贊、在看” 支持一波??

    瀏覽 80
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    俺去也俺来也 | 中文字幕成人网 | 91aaa国产精品 | 丰满老熟女一级AA片色欲 | 免费一级A毛片夜夜看 |