欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解TypeScript中的箭頭函數(shù)如何實現(xiàn)重載

 更新時間:2023年05月26日 08:30:01   作者:芋仔  
這篇文章主要為大家詳細(xì)介紹了TypeScript中的箭頭函數(shù)是如何實現(xiàn)重載的,文中的示例代碼講解詳細(xì),具有一定的參考價值,需要的可以參考一下

這個問題來自于我在網(wǎng)上搜索的時候,基本上清一色的翻譯官網(wǎng)的函數(shù)重載的章節(jié)的內(nèi)容,對于我想要的箭頭函數(shù)的重載沒有太多幫助。包括官網(wǎng),其實也沒有非常明確的說明箭頭函數(shù)該如何重載。

這里先直接上結(jié)論,在 ts 中,可以借助 Call Signatures 這個特性來實現(xiàn)箭頭函數(shù)的重載。原本是用來給函數(shù)聲明增加靜態(tài)屬性的,但是卻可以用來完成箭頭函數(shù)的類型聲明。

type Test = {
  (s: string): string;
  (s: number): number;
  (s: string, b: number): number;
};
type getState<T> = {
  (): T;
  <K extends keyof T>(key: K): T[K];
};

本質(zhì)就是定一個新的類型,鍵值就用括號包,里面就是不同的入?yún)?,函?shù)的返回值就是鍵值即可。

但是不出意外的話,意外就會發(fā)生,在實操的時候,往往這么寫非常不 ok。

實操

實戰(zhàn)中這么寫,類型聲明是好寫的,但是函數(shù)的實現(xiàn),其實并不好寫,以這樣一個函數(shù)為例:

const deal = (a: number | string, b: number | string): number | string => {
  if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
  }
  if (typeof a === 'string' || typeof b === 'string') {
    return String(a) + String(b);
  }
  return 0;
};

當(dāng)入?yún)⒍际?number 時,返回 number,入?yún)⒂幸粋€是 string 時,返回 string。

那么對于這樣一個函數(shù),其實存在幾個重載的情況:

type Deal1 = {
  (a: number, b: number): number;
  (a: number, b: string): string;
  (a: string, b: number): string;
  (a: string, b: string): string;
};

要想把上述類型賦值給 deal 函數(shù),會出現(xiàn)返回值匹配不上的問題。

// ts 會提示類型錯誤:
// Type '(a: number | string, b: number | string) => number | string' is not assignable to type 'Deal1'.
// Type 'string | number' is not assignable to type 'number'.
const deal: Deal1 = (
  a: number | string,
  b: number | string,
): number | string => {
  if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
  }
  if (typeof a === 'string' || typeof b === 'string') {
    return String(a) + String(b);
  }
???????  return 0;
};

從現(xiàn)象來看,ts 對于這樣的寫法在做檢查的時候,會將當(dāng)前函數(shù)對重載的幾個類型都進行檢查,看看類型上是否能夠賦值,相當(dāng)于:

// 偽代碼,理解意思就行
check1: (a: number, b: number) => number = (a: number | string, b: number | string) => number | string);
check2: (a: number, b: string) => string = (a: number | string, b: number | string) => number | string);
check3: (a: string, b: number) => string = (a: number | string, b: number | string) => number | string);
check4: (a: string, b: string) => string = (a: number | string, b: number | string) => number | string);

對于入?yún)ⅲ捎谑悄孀兾恢?,所?number = number | string 能夠賦值,所以參數(shù)的類型能夠通過校驗,而返回值屬于順變位置,所以 number = number | string 是不能通過類型校驗的。

想要將返回值賦值成功,返回值必須是 number & string 或者 any,前者就是 never 了,此時會發(fā)現(xiàn)雖然賦值通過了 deal 的校驗,但是函數(shù)的實現(xiàn)中,就會報返回值錯誤的問題。如果改成 any,那么雖然不會報錯,但是在函數(shù)中就缺失了對返回值的檢查。如下:

// 返回值改為 number & string,
// 賦值處能夠避免類型錯誤
const deal: Deal1 = (
  a: number | string,
  b: number | string,
): number & string => {
  if (typeof a === 'number' && typeof b === 'number') {
    // 此時返回值是 never,此處會報類型錯誤
    return a + b;
  }
  if (typeof a === 'string' || typeof b === 'string') {
    // 此時返回值是 never,此處會報類型錯誤
    return String(a) + String(b);
  }
  // 此時返回值是 never,此處會報類型錯誤
  return 0;
};
// 返回值改為 any,
// 賦值處能夠避免類型錯誤
const deal: Deal1 = (a: number | string, b: number | string): any => {
  if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
  }
  if (typeof a === 'string' || typeof b === 'string') {
    return String(a) + String(b);
  }
  // 此處寫任何類型都不會拋錯,缺失了原本的期望的校驗
  return undefined;
};

那么目前看,想要用這種方式實現(xiàn)箭頭函數(shù)的重載,就只能將返回值設(shè)定為 any,這樣,雖然在用戶使用的時候能夠進行非常好的類型提示,但是開發(fā)者本身不能再借助 ts 完成對這個函數(shù)的返回值的校驗。

此時還有一種寫法,就是 as,寫法如下:

const deal = ((a: string | number, b: number | string): number | string => {
  if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
  }
  if (typeof a === 'string' || typeof b === 'string') {
    return String(a) + String(b);
  }
  return 0;
}) as Deal1;

這樣的寫法,即能夠滿足函數(shù)本身的返回值校驗 (可以把 0 改成其他類型試試),同時,又具備了 Deal1 的重載的類型聲明:

// case1: number
const case1 = deal(1, 2);
// case2: string
const case2 = deal('1', 2);
// case3: never,入?yún)㈩愋湾e誤
const case3 = deal({}, 2);

最佳實踐

附上完整的代碼:

// 重載類型聲明
type Deal1 = {
  (a: number, b: number): number;
  (a: number, b: string): string;
  (a: string, b: number): string;
  (a: string, b: string): string;
};
const deal = ((
  // 此時入?yún)?,返回值的類型可自行限?
  // 無需掛念 Deal1 中的定義
  a: string | number,
  b: number | string,
): number | string => {
  if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
  }
  if (typeof a === 'string' || typeof b === 'string') {
    return String(a) + String(b);
  }
  // 這樣寫,原函數(shù)具備校驗的能力
  return 0;
  // 通過 as 指定類型
}) as Deal1;
const case1 = deal(1, 2);
const case2 = deal('1', 2);
const case3 = deal({}, 2);

核心就是原函數(shù)類型寫法一致,重載的類型通過 as 進行賦值,這樣就兼顧了類型提示和原函數(shù)的類型校驗。

其他方法

由于 type 和 interface 的用法在此處并無歧義,所以換成 interface 也是 ok。

另一種就是函數(shù)的交叉,也是實現(xiàn)重載的一種方案,如下:

type Deal3 = ((a: number, b: number) => number) &
  ((a: number, b: string) => string) &
  ((a: string, b: number) => string) &
  ((a: string, b: string) => string);

總結(jié)

本文介紹了 TS 實現(xiàn)箭頭函數(shù)重載的幾種方案,借助了 Call Signatures 的特性。

同時給出了這樣寫,在實戰(zhàn)中可能會遇到的類型不匹配的問題及解決方案。希望能夠?qū)τ龅酵瑯訂栴}的同學(xué)有所幫助吧。

到此這篇關(guān)于詳解TypeScript中的箭頭函數(shù)如何實現(xiàn)重載的文章就介紹到這了,更多相關(guān)TypeScript函數(shù)重載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • window.onload 加載完畢的問題及解決方案(上)

    window.onload 加載完畢的問題及解決方案(上)

    我們經(jīng)常使用 window.onload 來處理頁面,當(dāng)頁面加載完成做一些事情。但這個 window.onload 是頁面全部加載完成,甚至包括圖片,而我們實際上經(jīng)常需要的是文檔 DOM 加載完畢!
    2009-07-07
  • JavaScript實現(xiàn)淺拷貝與深拷貝的方法分析

    JavaScript實現(xiàn)淺拷貝與深拷貝的方法分析

    這篇文章主要介紹了JavaScript實現(xiàn)淺拷貝與深拷貝的方法,結(jié)合實例形式總結(jié)分析了JavaScript淺拷貝與深拷貝的定義與使用方法,需要的朋友可以參考下
    2018-07-07
  • JS實現(xiàn)拖動模態(tài)框案例

    JS實現(xiàn)拖動模態(tài)框案例

    這篇文章主要為大家詳細(xì)介紹了JS實現(xiàn)拖動模態(tài)框案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • ES6中l(wèi)et、const的區(qū)別及變量的解構(gòu)賦值操作方法實例分析

    ES6中l(wèi)et、const的區(qū)別及變量的解構(gòu)賦值操作方法實例分析

    這篇文章主要介紹了ES6中l(wèi)et、const的區(qū)別及變量的解構(gòu)賦值操作方法,結(jié)合實例形式分析了ES6中l(wèi)et、const的功能、原理、使用方法及數(shù)組、字符串、函數(shù)參數(shù)等解構(gòu)賦值相關(guān)操作技巧,需要的朋友可以參考下
    2019-10-10
  • 用JavaScript實現(xiàn)簡單網(wǎng)頁時鐘

    用JavaScript實現(xiàn)簡單網(wǎng)頁時鐘

    這篇文章主要為大家詳細(xì)介紹了用JavaScript實現(xiàn)簡單網(wǎng)頁時鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • js實時獲取窗口大小變化的實例代碼

    js實時獲取窗口大小變化的實例代碼

    下面小編就為大家?guī)硪黄猨s實時獲取窗口大小變化的實例代碼。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • JavaScript?排他思想的具體實現(xiàn)

    JavaScript?排他思想的具體實現(xiàn)

    排他思想的算法就是排除掉其他的,本文主要介紹了JavaScript?排他思想的實現(xiàn),以及介紹了兩個示例,感興趣的可以了解一下
    2021-11-11
  • 輪播圖組件js代碼

    輪播圖組件js代碼

    這篇文章主要為大家介紹了輪播圖組件JavaScript代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • 微信小程序仿微信運動步數(shù)排行(交互)

    微信小程序仿微信運動步數(shù)排行(交互)

    這篇文章主要介紹了微信小程序仿微信運動步數(shù)排行(交互),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • 使用Cookies保存網(wǎng)站歷史瀏覽記錄實例代碼

    使用Cookies保存網(wǎng)站歷史瀏覽記錄實例代碼

    仿淘寶網(wǎng)的最近瀏覽記錄功能,喜歡的朋友可以參考下。
    2010-07-07

最新評論