簡體   English   中英

如何實現打字稿函數重載

[英]how to implement typescript function overload

如何實現打字稿函數重載?

interface Fn <T>{
  (payload: string): T;
  (payload: string, a: T): T;
}

let fn: Fn<number> =  function(a: string, b: number) {
  return b
}

報告Type '(a: string, b: number) => string' is not assignable to type 'Fn<number>'.Vetur(2322)

為了使這兩個重載都適用於fn ,您必須在實現中將b設為可選。 當你這樣做時,你會看到一個不同的錯誤,因為我們的類型說我們必須返回一個number ,所以當b可能undefined時返回b並不能減少它。 我們可以為b設置一個默認值,或者在函數體內返回一些默認值。

let fn: Fn<number> =  function(a: string, b: number = 0) {
  return b;
}
let fn: Fn<number> =  function(a: string, b?: number) {
  return b === undefined ? 0 : b;
}

為了滿足具有多個(即重載)調用簽名的接口,函數的實現必須能夠處理所有此類簽名。 如果fnFn<number> ,那么您必須能夠像這樣調用它:

fn("someString"); // first overload
fn("someString", 1234); // second overload

但實施

function (a: string, b: number) {
  return b 
}

不滿足第一個重載(因為b將是undefined ),因此不可分配給Fn<number>

相反,您應該考慮提出與兩個調用簽名兼容的實現。 例如:

let fn: Fn<number> = function (a: string, b?: number) {
  return b ?? a.length
}

在這里,實現要求它的第一個參數a是一個string並采用一個可選的第二個參數b類型為number 由於b可能undefined並且您必須返回一個number ,因此您不能直接返回b 在上面我返回b除非它是undefined ,在這種情況下我返回a.length 這始終是一個number ,編譯器可以驗證分配是否有效。


注意:在重載調用簽名具有不同返回類型的情況下會出現復雜情況。 除非您的函數表達式的實現返回所有返回類型的交集,否則編譯器將無法驗證類型安全並會出錯,因此您需要使用類型斷言

interface OtherFn {
  (payload: string): string;
  (payload: string, a: number): number;
}

let fn2: OtherFn = (a: string, b?: number) => b ?? a; // error!
//  ~~~ <-- string | number not assignable to string

console.log(fn2("abc").toUpperCase()) // ABC
console.log(fn2("abc", Math.PI).toFixed(2)) // 3.14

在這里您可以看到fn2確實滿足OtherFn兩個調用簽名,但是由於返回類型不同,編譯器無法對其進行驗證。 如果要使用函數表達式執行此操作,則需要類型斷言:

let fn3 = ((a: string, b?: number) => b ?? a) as OtherFn; // okay

或者你可以放棄函數表達式和使用功能的語句,檢查較為松散,允許返回類型是聯合所有的呼叫簽名返回類型:

function fn4(payload: string): string;
function fn4(payload: string, a: number): number;
function fn4(a: string, b?: number) {
  return b ?? a;
}

盡管沒有像這樣手動注釋,但可以看出滿足OtherFn

let fn5: OtherFn = fn4; // okay

Playground 鏈接到代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM