[英]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;
}
為了滿足具有多個(即重載)調用簽名的接口,函數的實現必須能夠處理所有此類簽名。 如果fn
是Fn<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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.