<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>

          TypeScript高級(jí)類型入門手冊(cè):附大量代碼實(shí)例(收藏?。?/h1>

          共 10039字,需瀏覽 21分鐘

           ·

          2021-06-24 08:13


          原文:https://juejin.cn/post/6904150785966211086

          作者:望道

          點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)

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

          TypeScript 是一種類型化的語(yǔ)言,允許你指定變量的類型,函數(shù)參數(shù),返回的值和對(duì)象屬性。

          你可以把本文看做一個(gè)帶有示例的 TypeScript 高級(jí)類型備忘單

          讓我們開始吧!

          Intersection Types(交叉類型)

          交叉類型是一種將多種類型組合為一種類型的方法。這意味著你可以將給定的類型 A 與類型 B 或更多類型合并,并獲得具有所有屬性的單個(gè)類型。

          type LeftType = {
          id: number;
          left: string;
          };

          type RightType = {
          id: number;
          right: string;
          };

          type IntersectionType = LeftType & RightType;

          function showType(args: IntersectionType) {
          console.log(args);
          }

          showType({ id: 1, left: 'test', right: 'test' });
          // Output: {id: 1, left: "test", right: "test"}

          如你所見,IntersectionType組合了兩種類型-LeftTypeRightType,并使用符號(hào)形成了交叉類型。

          Union Types(聯(lián)合類型)

          聯(lián)合類型使你可以賦予同一個(gè)變量不同的類型

          type UnionType = string | number;

          function showType(arg: UnionType) {
          console.log(arg);
          }

          showType('test');
          // Output: test

          showType(7);
          // Output: 7

          函數(shù)showType是一個(gè)聯(lián)合類型函數(shù),它接受字符串或者數(shù)字作為參數(shù)。

          Generic Types(泛型)

          泛型類型是復(fù)用給定類型的一部分的一種方式。它有助于捕獲作為參數(shù)傳遞的類型 T。

          優(yōu)點(diǎn): 創(chuàng)建可重用的函數(shù),一個(gè)函數(shù)可以支持多種類型的數(shù)據(jù)。這樣開發(fā)者就可以根據(jù)自己的數(shù)據(jù)類型來使用函數(shù)

          泛型函數(shù)

          function showType<T>(args: T) {
          console.log(args);
          }

          showType('test');
          // Output: "test"

          showType(1);
          // Output: 1

          如何創(chuàng)建泛型類型:需要使用<>并將 T(名稱可自定義)作為參數(shù)傳遞。上面的 ?? 栗子中, 我們給 showType 添加了類型變量 TT幫助我們捕獲用戶傳入的參數(shù)的類型(比如:number/string)之后我們就可以使用這個(gè)類型

          我們把 showType 函數(shù)叫做泛型函數(shù),因?yàn)樗梢赃m用于多個(gè)類型

          泛型接口

          interface GenericType<T> {
          id: number;
          name: T;
          }

          function showType(args: GenericType<string>) {
          console.log(args);
          }

          showType({ id: 1, name: 'test' });
          // Output: {id: 1, name: "test"}

          function showTypeTwo(args: GenericType<number>) {
          console.log(args);
          }

          showTypeTwo({ id: 1, name: 4 });
          // Output: {id: 1, name: 4}

          在上面的栗子中,聲明了一個(gè) GenericType 接口,該接口接收泛型類型 T, 并通過類型 T來約束接口內(nèi) name 的類型

          注:泛型變量約束了整個(gè)接口后,在實(shí)現(xiàn)的時(shí)候,必須指定一個(gè)類型

          因此在使用時(shí)我們可以將name設(shè)置為任意類型的值,示例中為字符串或數(shù)字

          多參數(shù)的泛型類型

          interface GenericType<T, U> {
          id: T;
          name: U;
          }

          function showType(args: GenericType<number, string>) {
          console.log(args);
          }

          showType({ id: 1, name: 'test' });
          // Output: {id: 1, name: "test"}

          function showTypeTwo(args: GenericType<string, string[]>) {
          console.log(args);
          }

          showTypeTwo({ id: '001', name: ['This', 'is', 'a', 'Test'] });
          // Output: {id: "001", name: Array["This", "is", "a", "Test"]}

          泛型類型可以接收多個(gè)參數(shù)。在上面的代碼中,我們傳入兩個(gè)參數(shù):TU,然后將它們用作id,name的類型。也就是說,我們現(xiàn)在可以使用該接口并提供不同的類型作為參數(shù)。

          Utility Types

          TypeScript 內(nèi)部也提供了很多方便實(shí)用的工具,可幫助我們更輕松地操作類型。如果要使用它們,你需要將類型傳遞給<>

          Partial

          • Partial<T>

          Partial 允許你將T類型的所有屬性設(shè)為可選。它將在每一個(gè)字段后面添加一個(gè)?。

          interface PartialType {
          id: number;
          firstName: string;
          lastName: string;
          }

          /*
          等效于
          interface PartialType {
          id?: number
          firstName?: string
          lastName?: string
          }
          */


          function showType(args: Partial<PartialType>) {
          console.log(args);
          }

          showType({ id: 1 });
          // Output: {id: 1}

          showType({ firstName: 'John', lastName: 'Doe' });
          // Output: {firstName: "John", lastName: "Doe"}

          上面代碼中聲明了一個(gè)PartialType接口,它用作函數(shù)showType()的參數(shù)的類型。為了使所有字段都變?yōu)榭蛇x,我們使用Partial關(guān)鍵字并將PartialType類型作為參數(shù)傳遞。

          Required

          • Required<T>

          將某個(gè)類型里的屬性全部變?yōu)楸剡x項(xiàng)

          interface RequiredType {
          id: number;
          firstName?: string;
          lastName?: string;
          }

          function showType(args: Required<RequiredType>) {
          console.log(args);
          }

          showType({ id: 1, firstName: 'John', lastName: 'Doe' });
          // Output: { id: 1, firstName: "John", lastName: "Doe" }

          showType({ id: 1 });
          // Error: Type '{ id: number: }' is missing the following properties from type 'Required<RequiredType>': firstName, lastName

          上面的代碼中,即使我們?cè)谑褂媒涌谥跋葘⒛承傩栽O(shè)為可選,但Required被加入后也會(huì)使所有屬性成為必選。如果省略某些必選參數(shù),TypeScript 將報(bào)錯(cuò)。

          Readonly

          • Readonly<T>

          會(huì)轉(zhuǎn)換類型的所有屬性,以使它們無法被修改

          interface ReadonlyType {
          id: number;
          name: string;
          }

          function showType(args: Readonly<ReadonlyType>) {
          args.id = 4;
          console.log(args);
          }

          showType({ id: 1, name: 'Doe' });
          // Error: Cannot assign to 'id' because it is a read-only property.

          我們使用Readonly來使ReadonlyType的屬性不可被修改。也就是說,如果你嘗試為這些字段之一賦予新值,則會(huì)引發(fā)錯(cuò)誤。

          除此之外,你還可以在指定的屬性前面使用關(guān)鍵字readonly使其無法被重新賦值

          interface ReadonlyType {
          readonly id: number;
          name: string;
          }

          Pick

          • Pick<T, K>

          此方法允許你從一個(gè)已存在的類型 T中選擇一些屬性作為K, 從而創(chuàng)建一個(gè)新類型

          即 抽取一個(gè)類型/接口中的一些子集作為一個(gè)新的類型

          T代表要抽取的對(duì)象 K有一個(gè)約束: 一定是來自T所有屬性字面量的聯(lián)合類型 新的類型/屬性一定要從K中選取,

          /**
          源碼實(shí)現(xiàn)
          * From T, pick a set of properties whose keys are in the union K
          */

          type Pick<T, K extends keyof T> = {
          [P in K]: T[P];
          };
          interface PickType {
          id: number;
          firstName: string;
          lastName: string;
          }

          function showType(args: Pick<PickType, 'firstName' | 'lastName'>) {
          console.log(args);
          }

          showType({ firstName: 'John', lastName: 'Doe' });
          // Output: {firstName: "John"}

          showType({ id: 3 });
          // Error: Object literal may only specify known properties, and 'id' does not exist in type 'Pick<PickType, "firstName" | "lastName">'

          Pick 與我們前面討論的工具有一些不同,它需要兩個(gè)參數(shù)

          • T是要從中選擇元素的類型
          • K是要選擇的屬性(可以使使用聯(lián)合類型來選擇多個(gè)字段)

          Omit

          • Omit<T, K>

          Omit的作用與Pick類型正好相反。不是選擇元素,而是從類型T中刪除K個(gè)屬性。

          interface PickType {
          id: number;
          firstName: string;
          lastName: string;
          }

          function showType(args: Omit<PickType, 'firstName' | 'lastName'>) {
          console.log(args);
          }

          showType({ id: 7 });
          // Output: {id: 7}

          showType({ firstName: 'John' });
          // Error: Object literal may only specify known properties, and 'firstName' does not exist in type 'Pick<PickType, "id">'

          Extract

          • Extract<T, U>

          提取T中可以賦值給U的類型--取交集

          Extract允許你通過選擇兩種不同類型中的共有屬性來構(gòu)造新的類型。也就是從T中提取所有可分配給U的屬性。

          interface FirstType {
          id: number;
          firstName: string;
          lastName: string;
          }

          interface SecondType {
          id: number;
          address: string;
          city: string;
          }

          type ExtractType = Extract<keyof FirstType, keyof SecondType>;
          // Output: "id"

          在上面的代碼中,FirstType接口和SecondType接口,都存在 id:number屬性。因此,通過使用Extract,即提取出了新的類型 {id:number}

          Exclude

          Exclude<T, U> --從 T 中剔除可以賦值給 U 的類型。

          Extract不同,Exclude通過排除兩個(gè)不同類型中已經(jīng)存在的共有屬性來構(gòu)造新的類型。它會(huì)從T中排除所有可分配給U的字段。

          interface FirstType {
          id: number;
          firstName: string;
          lastName: string;
          }

          interface SecondType {
          id: number;
          address: string;
          city: string;
          }

          type ExcludeType = Exclude<keyof FirstType, keyof SecondType>;

          // Output; "firstName" | "lastName"

          上面的代碼可以看到,屬性firstNamelastNameSecondType類型中不存在。通過使用Extract關(guān)鍵字,我們可以獲得T中存在而U中不存在的字段。

          Record

          • Record<K,T>

          此工具可幫助你構(gòu)造具有給定類型T的一組屬性K的類型。將一個(gè)類型的屬性映射到另一個(gè)類型的屬性時(shí),Record非常方便。

          interface EmployeeType {
          id: number;
          fullname: string;
          role: string;
          }

          let employees: Record<number, EmployeeType> = {
          0: { id: 1, fullname: 'John Doe', role: 'Designer' },
          1: { id: 2, fullname: 'Ibrahima Fall', role: 'Developer' },
          2: { id: 3, fullname: 'Sara Duckson', role: 'Developer' },
          };

          // 0: { id: 1, fullname: "John Doe", role: "Designer" },
          // 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" },
          // 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }

          Record的工作方式相對(duì)簡(jiǎn)單。在代碼中,它期望一個(gè)number作為類型,這就是為什么我們將 0、1 和 2 作為employees變量的鍵的原因。如果你嘗試使用字符串作為屬性,則會(huì)引發(fā)錯(cuò)誤,因?yàn)閷傩允怯?code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #28ca71;">EmployeeType給出的具有 ID,fullName 和 role 字段的對(duì)象。

          NonNullable

          • NonNullable<T>

          -- 從 T 中剔除 nullundefined

          type NonNullableType = string | number | null | undefined;

          function showType(args: NonNullable<NonNullableType>) {
          console.log(args);
          }

          showType('test');
          // Output: "test"

          showType(1);
          // Output: 1

          showType(null);
          // Error: Argument of type 'null' is not assignable to parameter of type 'string | number'.

          showType(undefined);
          // Error: Argument of type 'undefined' is not assignable to parameter of type 'string | number'.

          我們將類型NonNullableType作為參數(shù)傳遞給NonNullable,NonNullable通過排除nullundefined來構(gòu)造新類型。也就是說,如果你傳遞可為空的值,TypeScript 將引發(fā)錯(cuò)誤。

          順便說一句,如果將--strictNullChecks標(biāo)志添加到tsconfig文件,TypeScript 將應(yīng)用非空性規(guī)則。

          Mapped Types( 映射類型)

          映射類型允許你從一個(gè)舊的類型,生成一個(gè)新的類型。

          請(qǐng)注意,前面介紹的某些高級(jí)類型也是映射類型。如:

          /*
          Readonly, Partial和 Pick是同態(tài)的,但 Record不是。因?yàn)?Record并不需要輸入類型來拷貝屬性,所以它不屬于同態(tài):
          */

          type Readonly<T> = {
          readonly [P in keyof T]: T[P];
          };
          type Partial<T> = {
          [P in keyof T]?: T[P];
          };
          type Pick<T, K extends keyof T> = {
          [P in K]: T[P];
          };

          Record;
          type StringMap<T> = {
          [P in keyof T]: string;
          };

          function showType(arg: StringMap<{ id: number; name: string }>) {
          console.log(arg);
          }

          showType({ id: 1, name: 'Test' });
          // Error: Type 'number' is not assignable to type 'string'.

          showType({ id: 'testId', name: 'This is a Test' });
          // Output: {id: "testId", name: "This is a Test"}

          StringMap<>會(huì)將傳入的任何類型轉(zhuǎn)換為字符串。就是說,如果我們?cè)诤瘮?shù)showType()中使用它,則接收到的參數(shù)必須是字符串-否則,TypeScript 將引發(fā)錯(cuò)誤。

          Type Guards(類型保護(hù))

          類型保護(hù)使你可以使用運(yùn)算符檢查變量或?qū)ο蟮念愋?。這是一個(gè)條件塊,它使用typeof,instanceofin返回類型。

          typescript 能夠在特定區(qū)塊中保證變量屬于某種確定類型??梢栽诖藚^(qū)塊中放心地引用此類型的屬性,或者調(diào)用此類型的方法

          typeof

          function showType(x: number | string) {
          if (typeof x === 'number') {
          return `The result is ${x + x}`;
          }
          throw new Error(`This operation can't be done on a ${typeof x}`);
          }

          showType("I'm not a number");
          // Error: This operation can't be done on a string

          showType(7);
          // Output: The result is 14

          什么代碼中,有一個(gè)普通的 JavaScript 條件塊,通過typeof檢查接收到的參數(shù)的類型。

          instanceof

          class Foo {
          bar() {
          return 'Hello World';
          }
          }

          class Bar {
          baz = '123';
          }

          function showType(arg: Foo | Bar) {
          if (arg instanceof Foo) {
          console.log(arg.bar());
          return arg.bar();
          }

          throw new Error('The type is not supported');
          }

          showType(new Foo());
          // Output: Hello World

          showType(new Bar());
          // Error: The type is not supported

          像前面的示例一樣,這也是一個(gè)類型保護(hù),它檢查接收到的參數(shù)是否是Foo類的一部分,并對(duì)其進(jìn)行處理。

          in

          interface FirstType {
          x: number;
          }
          interface SecondType {
          y: string;
          }

          function showType(arg: FirstType | SecondType) {
          if ('x' in arg) {
          console.log(`The property ${arg.x} exists`);
          return `The property ${arg.x} exists`;
          }
          throw new Error('This type is not expected');
          }

          showType({ x: 7 });
          // Output: The property 7 exists

          showType({ y: 'ccc' });
          // Error: This type is not expected

          什么的栗子中,使用in檢查參數(shù)對(duì)象上是否存在屬性x。

          Conditional Types(條件類型)

          條件類型測(cè)試兩種類型,然后根據(jù)該測(cè)試的結(jié)果選擇其中一種。

          一種由條件表達(dá)式所決定的類型, 表現(xiàn)形式為 T extends U ? X : Y , 即如果類型T可以被賦值給類型U,那么結(jié)果類型就是X類型,否則為Y類型。

          條件類型使類型具有了不唯一性,增加了語(yǔ)言的靈活性,

          // 源碼實(shí)現(xiàn)
          type NonNullable<T> = T extends null | undefined ? never : T;

          // NotNull<T> 等價(jià)于 NoneNullable<T,U>

          // 用法示例
          type resType = NonNullable<string | number | null | undefined>; // string|number

          上面的代碼中, NonNullable檢查類型是否為 null,并根據(jù)該類型進(jìn)行處理。正如你所看到的,它使用了 JavaScript 三元運(yùn)算符。

          感謝閱讀。

          如果覺得這篇文章還不錯(cuò)
          點(diǎn)擊下面卡片關(guān)注我
          來個(gè)【分享、點(diǎn)贊、在看】三連支持一下吧

             “分享、點(diǎn)贊在看” 支持一波 

          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)

          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  日韩A片在线 | 亚洲五月天激情 | 免费一级黄色视频 | 国产精品久久久久久爽爽爽麻豆色哟哟 | 天天色天天射天天干 |