2017-08-15 133 views
1

是否可以爲重載的函數簽名創建一個類型別名?TypeScript:我可以提供重載函數簽名的類型別名嗎?

例如,我有這樣一個功能:

function whenChanged(scope: ng.IScope, fn:()=>void):()=>void; 
function whenChanged(fn:()=>void, truthy:any):()=>void; 
function whenChanged(a,b):()=>void { 
    //... 
} 

我想創建類型別名到重載的簽名,以節省重複,並利用在其他地方,我需要描述的類型這個功能。

我想:

type WC1 = (scope: ng.IScope, fn:()=>void) =>()=>void; 
type WC2 = (fn:()=>void, truthy:any) =>()=>void; 
type WhenChanged = WC1 | WC2; 

const whenChanged: WhenChanged = (a,b) => { 
    //... 
}; 

但試圖利用這個功能,我沿着「不能調用其類型缺乏調用簽名表達」線得到一個錯誤。

我不能在文檔中看到關於類型別名函數重載的任何內容。

回答

1

既然你已經具備的功能whenChanged

function whenChanged(scope: ng.IScope, fn:()=>void):()=>void; 
function whenChanged(fn:()=>void, truthy:any):()=>void; 
function whenChanged(a,b):()=>void { 
    //... 
} 

簡單的方式來獲得它的類型是類型別名是使用typeoftype query

type WhenChanged = typeof whenChanged; 

的接下來,創建類型別名最直接的方法是使用overloaded function signature(這是wh你正在尋找):

type WhenChanged = { 
    (scope: ng.IScope, fn:() => void):() => void; 
    (fn:() => void, truthy: any):() => void; 
} 

(這是你會在quickinfo看到,如果你懸停在編輯器中typeof定義)請注意,你並不需要,如果你不使用的interface。不想要。


你可以做的下一件事就是類似於你在做什麼,但問題是,過載是路口,不是工會。這是簽名:

type WC1 = (scope: ng.IScope, fn:()=>void) =>()=>void; 
type WC2 = (fn:()=>void, truthy:any) =>()=>void; 
type WhenChanged = WC1 & WC2; // and, not or 

要小心,intersections of function signatures are not commutative,特別是因爲它們代表重載。這意味着以下類型在技術上並不相同:

type NotWhenChanged = WC2 & WC1; // different type 

因爲重載解析會發生在不同的順序。

請注意,由於呼叫簽名不同,因此不能調用WC1 | WC2類型的函數,編譯器無法確定函數是WC1還是WC2


好的,你去了。希望能幫助到你;祝你好運!

+0

這是一個很好的答案;正是我所追求的!謝謝! – jsdw

1

經過一番玩,結果是(至少部分)使用接口的答案。這似乎工作:

interface WhenChanged { 
    (scope: ng.IScope, fn:()=>void):()=>void 
    (fn:()=>void, truthy:any):()=>void 
} 

const whenChanged: WhenChanged = (a,b) => { 
    //... 
}; 
+0

我想你會發現只有當函數匹配所需的類型簽名時纔有效。所以,當你將'a'改爲'scope:ng.IScope'時,它會拒絕,因爲'iscope'與'()=> void'不兼容。 – Duncan

+0

您可以使用'type'而不是'interface';請參閱我的回答以獲取更多信息 – jcalz

0

「不能調用其類型缺乏調用簽名表達」是指一個類型的工會是不可調用的,你必須選擇一個類型或其他。

的問題是,在這個例子中,你給了你沒有爲ab定義的類型,所以編譯器無法分辨其中WC1WC2實際使用。如果你改變whenChanged定義:

const whenChanged: WhenChanged = (a: ng.IScope, b:()=>void) => { 
    return b; 
}; 

現在編譯器知道它可以限制whenChangedWC1類型,所以你可以安全地調用它。

如果不是一個常量,你有一個變量,whenChanged可能是因爲存在的方式WC1WC2編譯器則不能告訴你將不得不調用之前使用某種類型的斷言的類型限制一方或另一方它:

(whenChanged as WC1)(some_scope, some_fn); 

或:

(whenChanged as WC2)(some_fn, some_truthy); 

什麼,你不能做的是從whenChanged其中鍵入包含以適當的參數來調用它工作了。你必須從其他地方獲取這些信息。

+0

jsdw實際上並不是試圖調用函數類型的聯合。問題是關於重載的函數簽名,而jsdw的嘗試解決方案是使用交叉點合適的聯合。 – jcalz

相關問題