<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【TS】1294- 搞懂 TypeScript 中的映射類型(Mapped Types)

          共 5198字,需瀏覽 11分鐘

           ·

          2022-04-18 21:12

          本文會和大家詳細(xì)介紹 TypeScript 中的映射類型(Mapped Type),看完本文你將學(xué)到以下知識點:
          • 數(shù)學(xué)中的映射和 TS 中的映射類型的關(guān)系;
          • TS 中映射類型的應(yīng)用;
          • TS 中映射類型修飾符的應(yīng)用;

          接下來會先從「數(shù)學(xué)中的映射」開始介紹。

          本文使用到的 TypeScript 版本為 v4.6.2

          如果你對 TypeScript 還不熟悉,可以看下面幾篇資料:

          1. 一份不可多得的 TS 學(xué)習(xí)指南(1.8W字)
          2. 了不起的 TypeScript 入門教程

          一、什么是映射?

          在學(xué)習(xí) TypeScript 類型系統(tǒng)時,盡量多和數(shù)學(xué)中的集合類比學(xué)習(xí),比如 TypeScript 中的聯(lián)合類型,類似數(shù)學(xué)中的并集等。

          在數(shù)學(xué)中,映射是指兩個元素的集合之間元素相互對應(yīng)的關(guān)系,比如下圖:

          (來源:https://baike.baidu.com/item/%E6%98%A0%E5%B0%84/20402621)

          可以將映射理解為函數(shù),如上圖,當(dāng)我們需要將集合 A 的元素轉(zhuǎn)換為集合 B 的元素,可以通過 f函數(shù)做映射,比如將集合 A 的元素 1對應(yīng)到集合 B 中的元素 2。這樣就能很好的實現(xiàn)映射過程的復(fù)用

          二、TypeScript 中的映射類型是什么?

          1. 概念介紹

          TypeScript 中的映射類型和數(shù)學(xué)中的映射類似,能夠?qū)⒁粋€集合的元素轉(zhuǎn)換為新集合的元素,只是 TypeScript 映射類型是將一個類型映射成另一個類型

          在我們實際開發(fā)中,經(jīng)常會需要一個類型的所有屬性轉(zhuǎn)換為可選類型,這時候你可以直接使用 TypeScript 中的 Partial工具類型:

          type?User?=?{
          ??name:?string;
          ??location:?string;
          ??age:?number;
          }

          type?User2?=?Partial;
          /*
          ? User2 的類型:
          ??
          ??type?User2?=?{
          ??????name?:?string?|?undefined;
          ??????location?:?string?|?undefined;
          ??????age?:?number?|?undefined;
          ??}
          */

          這樣我們就實現(xiàn)了將 User類型映射成 User2類型,并且將 User類型中的所有屬性轉(zhuǎn)為可選類型。

          image.png

          2. 實現(xiàn)方法

          TypeScript 映射類型的語法如下:

          type?TypeName?=?{
          ??[Property?in?keyof?Type]:?boolean;
          };

          我們既然可以通過 Partial工具類型非常簡單的實現(xiàn)將指定類型的所有屬性轉(zhuǎn)換為可選類型,那其內(nèi)容原理又是如何?

          我們可以在編輯器中,將鼠標(biāo)懸停在 Partial名稱上面,可以看到編輯器提示如下:

          image.png

          拆解一下其中每個部分:

          • type Partial:定義一個類型別名 Partial和泛型 T
          • keyof T:通過 keyof操作符獲取泛型 T中所有 key,返回一個聯(lián)合類型(如果不清楚什么是聯(lián)合類型,可以理解為一個數(shù)組);
          type?User?=?{
          ??name:?string;
          ??location:?string;
          ??age:?number;
          }

          type?KeyOfUser?=?keyof?User;?//?"name"?|?"location"?|?"age"
          • in:類似 JS 中 for...in中的 in,用來遍歷目標(biāo)類型的公開屬性名;
          • T[P]:是個索引訪問類型(也稱查找類型),獲取泛型 TP類型,類似 JS 中的訪問對象的方式;
          • ?:將類型值設(shè)置為可選類型;
          • { [P in keyof T] ?: T[P] | undefined}:遍歷 keyof T返回的聯(lián)合類型,并定義用 P變量接收,其每次遍歷返回的值為可選類型的 T[P]

          這樣就實現(xiàn)了 Partial工具類型,這種操作方法非常重要,是后面進行 TypeScript 類型體操的重要基礎(chǔ)。

          關(guān)于類型體操的練習(xí),有興趣可以看看這篇文章:
          《這 30 道 TS 練習(xí)題,你能答對幾道?》https://juejin.cn/post/7009046640308781063

          三、映射類型的應(yīng)用

          TypeScript 映射類型經(jīng)常用來復(fù)用一些對類型的操作過程,比如 TypeScript 目前支持的 21 種工具類型,將我們常用的一些類型操作定義成這些工具類型,方便開發(fā)者復(fù)用這些類型。

          所有已支持的工具類型可以看下官方文檔:
          https://www.typescriptlang.org/docs/handbook/utility-types.html

          下面我們挑幾個常用的工具類型,看下其實現(xiàn)過程中是如何使用映射類型的。

          在學(xué)習(xí) TypeScript 過程中,推薦多在官方的 Playground 練習(xí)和學(xué)習(xí):
          https://www.typescriptlang.org/zh/play

          1. Required 必選屬性

          用來將類型的所有屬性設(shè)置為必選屬性

          實現(xiàn)如下:

          type?Required?=?{
          ????[P?in?keyof?T]-?:?T[P];
          };

          使用方式:

          type?User?=?{
          ??name?:?string;
          ??location?:?string;
          ??age?:?number;
          }

          type?User2?=?Required;
          /*
          ??type?User2?=?{
          ??????name:?string;
          ??????location:?string;
          ??????age:?number;
          ??}
          */


          const?user:?User2?=?{
          ??name:?'pingan8787',
          ??age:?18
          }
          /*
          ??報錯:
          ??Property?'location'?is?missing?in?type?'{?name:?string;?age:?number;?}'
          ??but?required?in?type?'Required'.
          */

          這邊的 -?符號可以暫時理解為“將可選屬性轉(zhuǎn)換為必選屬性”,下一節(jié)會詳細(xì)介紹這些符號。

          2. Readonly 只讀屬性

          用來將所有屬性的類型設(shè)置為只讀類型,即不能重新分配類型。

          實現(xiàn)如下:

          type?Readonly?=?{
          ??readonly?[P?in?keyof?T]:?T[P];
          }

          使用方式:

          type?User?=?{
          ??name?:?string;
          ??location?:?string;
          ??age?:?number;
          }

          type?User2?=?Readonly;
          /*
          ??type?User2?=?{
          ??????readonly?name?:?string?|?undefined;
          ??????readonly?location?:?string?|?undefined;
          ??????readonly?age?:?number?|?undefined;
          ??}
          */


          const?user:?User2?=?{
          ??name:?'pingan8787',
          ??age:?18
          }

          user.age?=?20;
          /*
          ??報錯:
          ??Cannot?assign?to?'age'?because?it?is?a?read-only?property.
          */

          3. Pick 選擇指定屬性

          用來從指定類型中選擇指定屬性并返回

          實現(xiàn)如下:

          type?Pickextends?keyof?T>?=?{
          ??[P?in?K]:?T[P];
          }

          使用如下:

          type?User?=?{
          ??name?:?string;
          ??location?:?string;
          ??age?:?number;
          }

          type?User2?=?Pick'name'?|?'age'>;
          /*
          ??type?User2?=?{
          ??????name?:?string?|?undefined;
          ??????age?:?number?|?undefined;
          ??}
          */


          const?user1:?User2?=?{
          ??name:?'pingan8787',
          ??age:?18
          }

          const?user2:?User2?=?{
          ??name:?'pingan8787',
          ??location:?'xiamen',?//?報錯
          ??age:?18
          }
          /*
          ??報錯
          ??Type?'{?name:?string;?location:?string;?age:?number;?}'?is?not?assignable?to?type?'User2'.
          ??Object?literal?may?only?specify?known?properties,?and?'location'?does?not?exist?in?type?'User2'.
          */

          4. Omit 忽略指定屬性

          作用類似與 Pick工具類型相反,可以從指定類型中忽略指定的屬性并返回。

          實現(xiàn)如下:

          type?Omitextends?string?|?number?|?symbol>?=?{
          ??[P?in?Exclude]:?T[P];
          }

          使用方式:

          type?User?=?{
          ??name?:?string;
          ??location?:?string;
          ??age?:?number;
          }

          type?User2?=?Omit'name'?|?'age'>;
          /*
          ??type?User2?=?{
          ??????location?:?string?|?undefined;
          ??}
          */


          const?user1:?User2?=?{
          ??location:?'xiamen',
          }

          const?user2:?User2?=?{
          ??name:?'pingan8787',?//?報錯
          ??location:?'xiamen'
          }
          /*
          ??報錯:
          ??Type?'{?name:?string;?location:?string;?}'?is?not?assignable?to?type?'User2'.
          ??Object?literal?may?only?specify?known?properties,?and?'name'?does?not?exist?in?type?'User2'.
          */

          5. Exclude 從聯(lián)合類型中排除指定類型

          用來從指定的聯(lián)合類型中排除指定類型

          實現(xiàn)如下:

          type?Exclude?=?T?extends?U???never?:?T;

          使用方式:

          type?User?=?{
          ??name?:?string;
          ??location?:?string;
          ??age?:?number;
          }

          type?User2?=?Exclude'name'>;
          /*
          ??type?User2?=?"location"?|?"age"
          */


          const?user1:?User2?=?'age';
          const?user2:?User2?=?'location';
          const?user3:?User2?=?'name';??//?報錯
          /*
          ??報錯:
          ??Type?'"name"'?is?not?assignable?to?type?'User2'.
          */

          四、映射修飾符的應(yīng)用

          在自定義映射類型的時候,我們可以使用兩個映射類型的修飾符來實現(xiàn)我們的需求:

          • readonly修飾符:將指定屬性設(shè)置為只讀類型
          • ?修飾符:將指定屬性設(shè)置為可選類型

          前面介紹 ReadonlyPartial工具類型的時候已經(jīng)使用到:

          type?Readonly?=?{
          ??readonly?[P?in?keyof?T]:?T[P];
          }

          type?Partial?=?{
          ??[P?in?keyof?T]?:?T[P]?|?undefined;
          }

          當(dāng)然,也可以對修飾符進行操作:

          • +添加修飾符(默認(rèn)使用);
          • -刪除修飾符;

          比如:

          type?Required?=?{
          ????[P?in?keyof?T]-?:?T[P];?//?通過?-?刪除???修飾符
          };

          也可以放在前面使用:

          type?NoReadonly?=?{
          ??-readonly?[P?in?keyof?T]:?T[P];?//?通過?-?刪除?readonly?修飾符
          }

          五、總結(jié)

          本文從數(shù)學(xué)中的映射作為切入點,詳細(xì)介紹 TypeScript 映射類型(Mapped Type)并介紹映射類型的應(yīng)用和修飾符的應(yīng)用。

          在學(xué)習(xí) TypeScript 類型系統(tǒng)時,盡量多和數(shù)學(xué)中的集合類比學(xué)習(xí),比如 TypeScript 中的聯(lián)合類型,類似數(shù)學(xué)中的并集等。

          學(xué)好映射類型,是接下來做類型體操中非常重要的基礎(chǔ)~~

          參考資料

          1. TypeScript 文檔-映射類型:https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
          2. TypeScript 工具類型:https://www.typescriptlang.org/docs/handbook/utility-types.html
          瀏覽 79
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产操逼网网 | 久在线| 一卡二卡三卡免费视频 | 久久精品黄色 | 欧美级毛片一进一出 |