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

          在條件類型中使用 infer 關(guān)鍵字

          共 2926字,需瀏覽 6分鐘

           ·

          2021-04-08 20:40


          在 TypeScript 中條件類型的用法是:

          T extends U ? X : Y

          跟 JS 中的條件表達(dá)式一樣,如果 extends 語句為真,則取X類型 ,反之得到Y(jié)類型 。我們這里把X稱為條件類型的真分支,Y 稱為假分支。


          現(xiàn)在,在 TypeScript 2.8 之后,我們可以在 extends 條件語句中使用 infer 關(guān)鍵字引入一個變量表示推斷的類型,這個變量可以被用在真分支中,也就是說 infer 實(shí)際上是一個聲明關(guān)鍵字,我們可以用它來聲明一個變量,而該變量表示的是 infer 所處位置的類型。


          以標(biāo)準(zhǔn)庫的 ReturnType 為例:

          type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
          const getFullName = (firstName: string, lastName: string): string { return `${firstName}_${lastName}`;}const fullName: ReturnType<typeof getFullName> = getFullName('foo', 'bar');


          這里 ReturnType<T> 接收一個任意函數(shù),在 extends 分支把推斷的函數(shù)返回值的類型賦給變量 R,從而得到該類型。這里需要注意的是,我們只能在 extends 條件語句中使用 infer 關(guān)鍵字,不能在諸如類型參數(shù)這樣的地方使用它:

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


          既然可以獲取到函數(shù)的返回值的類型,同樣也可以推斷出函數(shù)的參數(shù)類型,標(biāo)準(zhǔn)庫的Paramaters<T>把函數(shù)的每個參數(shù)類型提取到一個元組中:

          type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
          const getFullName = (firstName: string, lastName: string, age: number): string =>{ return `${firstName}_${lastName}`;}type params = Parameters<typeof getFullName> // [string, string, number]


          除了把函數(shù)參數(shù)列表的類型提取出來,進(jìn)一步深入,假如函數(shù)的參數(shù)是單個對象,我們可以利用 infer 把參數(shù)的結(jié)構(gòu)推斷出來:

          type FunctionWithMappedArgument<P extends { [key: string]: any }> = (args: P) => any;type DestructuredArguments<F extends FunctionWithMappedArgument<any>> = F extends FunctionWithMappedArgument<infer R> ? R : never;
          declare function drawPoint(config: { x: number, y: number, color: string}): any;const args: DestructuredArguments<typeof drawPoint> = { x: 4, y: 6,}


          這里我們先定義出參數(shù)類型為單個對象的通用函數(shù) FunctionWithMappedArgument<T>,接著定義解構(gòu)參數(shù)的方法 DestructuredArguments<T>,這個方法做的事情是接收一個FunctionWithMappedArgument<T> 類型的函數(shù),然后把函數(shù)的泛型參數(shù)T推斷為新的變量 R,這樣編譯器就會替我們計算出 R 的解構(gòu)。


          通過上面的代碼,我們就可以把函數(shù)的參數(shù)類型提取出來,無需再聲明一個類型,編碼過程中編輯器的智能感知也能很好地進(jìn)行代碼補(bǔ)全提示。


          多處 infer 推斷一個變量

          上面展示的例子都只用到了一個 infer,在 extends 條件語句中,我們可以有多個 infer,只不過它們只能作用于同一個變量,根據(jù)推斷位置的不同產(chǎn)生的類型也有所不同。


          在共變的位置,會推斷出聯(lián)合類型:

          type Foo<T> = T extends { a: infer U, b: infer U } ? U : never;type T10 = Foo<{ a: string, b: string }>;  // stringtype T11 = Foo<{ a: string, b: number }>;  // string | number


          在逆變的位置,推斷的是交叉類型:

          type Bar<T> = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;type T20 = Bar<{ a: (x: string) => void, b: (x: string) => void }>;  // stringtype T21 = Bar<{ a: (x: string) => void, b: (x: number) => void }>;  // string & number


          函數(shù)重載中的推斷

          當(dāng)作用于一個有多處調(diào)用簽名(函數(shù)重載)的類型時,infer 只對最后一個簽名生效,不可能基于參數(shù)列表的不同進(jìn)行重載。

          declare function foo(x: string): number;declare function foo(x: number): string;declare function foo(x: string | number): string | number;type T30 = ReturnType<typeof foo>;  // string | number


          瀏覽 60
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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在线 | 日本黄色日逼视频 | 日本国产高清视频 | 视频国产91 |