<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重難點:泛型

          共 4968字,需瀏覽 10分鐘

           ·

          2020-08-27 12:29

          這篇文章跟大家分享學(xué)習(xí)ts的又一個重難點「泛型」。在ts中,得泛型者,得天下!

          1

          什么是泛型

          整個ts的學(xué)習(xí),其實就是各種數(shù)據(jù)類型的類型約束的學(xué)習(xí)。當(dāng)我們規(guī)定一個變量只能是number時,它就不能是其他數(shù)據(jù)類型。

          let a: number = 20;
          a = 'string' // 類型錯誤

          在函數(shù)中也是一樣,傳入的參數(shù)類型,與返回的參數(shù)類型,都會被不同的約束規(guī)則約束。

          function foo(a: number, b: string): string {
          // todo
          }

          當(dāng)然我們也知道,還可以使用interface,type定義更為復(fù)雜的類型約束。可是這個時候我們就會面臨一個問題。

          以我們用的非常多的數(shù)組方法map為例。

          [1, 2, 3].map(item => {
          return item + 1;
          })

          我們都知道m(xù)ap方法接收的第一個參數(shù)為一個回調(diào)函數(shù)callbackcallback的第一個參數(shù)為數(shù)組的每一項。那么問題就來了,不同的數(shù)組調(diào)用map,數(shù)組的每一項數(shù)據(jù)類型必然不一樣,我們沒辦法簡單的使用某一種數(shù)據(jù)類型來準(zhǔn)確的約束數(shù)組的每一項。

          [1, 2, 3].map()
          ['a', 'b', 'c'].map()

          怎么辦?當(dāng)數(shù)組不一樣時?如何來約束呢?

          這種情況,需要借助「泛型」來幫助我們。

          單一的,明確的類型約束理解起來相對簡單,可是實踐中我們需要對約束稍微放寬一點限制,那么單一的約束就無法滿足需求。泛型,即為更廣泛的約束類型

          仔細(xì)觀察下面的三組案例,思考一下如果我們要自己描述Array類型與數(shù)組中的map方法應(yīng)該怎么做?

          interface Person {
          name: string,
          age: number
          }

          const demo1: number[] = [1, 2, 3];
          const demo2: string[] = ['a', 'b', 'c'];
          const demo3: Person[] = [{ name: 'alex', age: 20 }, { name: 'john', age: 10 }, { name: 'hx', age: 21 }];

          demo1.map((item) => item);
          demo2.map((item) => item);
          demo3.map((item) => item);
          注意觀察不同數(shù)組item的不同類型

          從圖中可以看出,當(dāng)不同的數(shù)組調(diào)用map時,回調(diào)函數(shù)的參數(shù)item,會自動推導(dǎo)為對應(yīng)的數(shù)據(jù)類型。也就是說,這里的item,必然是使用了泛型進行了更為寬松的約束。具體如下:

          interface Array {
          map(callbackfn: (value: T, index: number, array: T[]) => U): U[]
          }

          我們在聲明數(shù)組類型時,定義了一個泛型變量TT作為泛型變量的含義為:我們在定義約束條件時,暫時還不知道數(shù)組的每一項數(shù)據(jù)類型到底是什么,因此我們只能放一個占位標(biāo)識在這里,待具體使用時再來明確每一項的具體類型。

          因此針對數(shù)據(jù)的描述,我們通常可以這樣做:

          const arr1: Array = [1, 2, 3];
          const arr2: Array = ['a', 'b', 'c'];
          const arr3: Array = [{ name: 'alex', age: 20 }, { name: 'john', age: 10 }, { name: 'hx', age: 21 }];

          這里分別定義了三個數(shù)組,在約束這些數(shù)組時,我們明確了泛型變量T的具體數(shù)據(jù)類型,分別對應(yīng)為number, string, Person

          那么在描述map時的寫法就很好理解了。回調(diào)函數(shù)callbackfn的第一個參數(shù)就是數(shù)組的每一項,正好就是定義數(shù)組時傳入的泛型變量T,不過回調(diào)函數(shù)會返回一個新的數(shù)組項,因此我們需要重新定義一個新的泛型變量來表達這個新數(shù)組,即為U

          map(callbackfn: (value: T, index: number, array: T[]) => U): U[]

          于是我們就使用泛型,準(zhǔn)確的描述了map方法的含義。

          如果經(jīng)過上述的解釋還不清楚泛型概念的話,留言

          2

          基礎(chǔ)語法

          如果完整的理解了泛型的概念,那么泛型的基礎(chǔ)知識就比較簡單了,過一遍就OK。

          函數(shù)中使用泛型

          // 聲明一個泛型變量
          function identity<T> {}

          // 在參數(shù)中使用泛型變量
          function identity<T>(arg: T) {}

          // 在返回值中使用泛型變量
          function identity<T>(arg: T): T {}

          // 變量聲明函數(shù)的寫法
          let myIdentity: <T>(arg: T) => T = identity;

          接口中使用泛型

          // 使用接口約束一部分?jǐn)?shù)據(jù)類型,使用泛型變量讓剩余部分變得靈活
          interface Parseer {
          success: boolean,
          result: T,
          code: number,
          desc: string
          }

          // 接口泛型與函數(shù)泛型結(jié)合
          interface Array {
          map(callbackfn: (value: T, index: number, array: T[]) => U): U[]
          }

          class中使用泛型

          // 注意總結(jié)相似性
          declare namespace demo02 {
          class GenericNumber {
          private value: T;

          public add: (x: T, y: T) => T
          }
          }

          // 多個泛型變量傳入
          declare namespace demo02 {
          class Component {
          private constructor(props: P);
          public state: S;
          }
          }

          3

          泛型實踐場景

          描述數(shù)組

          interface Array {
          length: number,
          toString(): string,
          pop(): T | undefined,
          // 注意此處的含義
          push(...items: T[]): number,
          concat(...items: T[]): T[],
          join(separator?: string): string,
          reverse(): T[],
          shift(): T | undefined;
          slice(start?: number, end?: number): T[],
          sort(compareFn?: (a: T, b: T) => number): this,
          splice(start: number, deleteCount?: number): T[],
          // 注意此處的重載寫法
          splice(start: number, deleteCount: number, ...items: T[]): T[],
          unshift(...items: T[]): number,
          indexOf(searchElement: T, fromIndex?: number): number,
          lastIndexOf(searchElement: T, fromIndex?: number): number,
          every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean,
          some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean,
          forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void,
          map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[],
          filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[],
          filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[],
          reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T,
          reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T,
          reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U,
          // reduceRight
          // 索引調(diào)用
          [n: number]: T,
          }

          列舉了幾乎所有的數(shù)組方法與特性,如果能夠從上訴描述文件中掌握如何使用數(shù)組方法,那么就表示對于函數(shù),接口,泛型的理解已經(jīng)比較到位了。如果還不能讀懂,則多讀幾遍,留言

          描述數(shù)據(jù)返回結(jié)果

          約定所有的接口返回滿足統(tǒng)一的數(shù)據(jù)格式。但是具體的可用的數(shù)據(jù)結(jié)果則因為情況不同,會有不同的場景。因此使用泛型先定義一個基本的結(jié)構(gòu)約束。

          interface Result {
          success: true,
          code: number,
          descript: string,
          result: T
          }

          結(jié)合Promise,當(dāng)數(shù)據(jù)返回結(jié)果為number時

          Promise本身就需要接受一個泛型變量,因此這里要注意泛型的嵌套使用

          function fetchData(): Promise<Result<number>> {
          return http.get('/api/demo/number');
          }

          當(dāng)數(shù)據(jù)返回結(jié)果為普通JSON數(shù)據(jù)時

          interface Person {
          name: string,
          age: number
          }

          function fetchData(): Promise<Result<Person>> {
          return http.get('/api/demo/person');
          }

          當(dāng)數(shù)據(jù)返回為數(shù)組時

          interface Person {
          name: string,
          age: number
          }

          function fetchData(): Promise<Result<Person[]>> {
          return http.get('/api/demo/persons');
          }

          當(dāng)返回結(jié)果為分頁對象時

          interface Person {
          name: string,
          age: number
          }

          interface Page {
          current: number,
          pageSize: number,
          total: number,
          data: T[]
          }

          function fetchData(): Promise<Result<Page<Person>>> {
          return http.get('/api/demo/page/person');
          }

          分頁對象的返回結(jié)果比較復(fù)雜,因此描述清楚需要多層嵌套,如果你理解了分頁對象,那么基本上泛型就沒有什么問題啦!

          瀏覽 23
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                    深爱激情丁香五月 | 天天爽爽夜夜爽爽 | 国产乱伦黄色 | 亚州无码中文字幕日韩AV | 日日综合 |