2017-10-14 73 views
0

我試圖在TypeScript中創建async庫的*-as-promised version,重用@types/async類型。如何在TypeScript中合併單獨的函數聲明?

我的問題是@types/async at the .filter function是出口兩個函數類型具有相同的名稱:

export function filter<T, E>(arr: T[] | IterableIterator<T>, iterator: AsyncBooleanIterator<T, E>, callback?: AsyncResultArrayCallback<T, E>): void; 
export function filter<T, E>(arr: Dictionary<T>, iterator: AsyncBooleanIterator<T, E>, callback?: AsyncResultArrayCallback<T, E>): void; 

但我only export one .filter function

function filter<T>(
    arr: async.Dictionary<T> | T[] | IterableIterator<T>, 
    iterator: (item: T) => Promise<boolean> 
): Promise<Array<(T | undefined)> | undefined> { 
    return new Promise((resolve, reject) => { 
    async.filter(arr, (item, cb) => { 
     iterator(item) 
     .then(res => cb(undefined, res)) 
     .catch(err => cb(err)); 
    }, (err, results) => 
     err 
     ? reject(err) 
     : resolve(results) 
    ); 
    }); 
} 

編譯時,這給了我以下錯誤:

lib/filter.ts(32,18): error TS2345: Argument of type 'Dictionary<T> | IterableIterator<T> | T[]' is not assignable to parameter of type 'Dictionary<T>'. 
    Type 'IterableIterator<T>' is not assignable to type 'Dictionary<T>'. 

那麼,我怎樣才能合併這些聲明在一個?

謝謝你。

回答

1

奇怪的是,鍵入不是一個單一的函數簽名,並且參數爲arr的三種可能類型的聯合。您可能需要考慮向async輸入庫提交問題或拉取請求以解決問題。

即便如此,如果編譯器允許您按照自己的方式調用該函數,那將會很不錯,因爲您知道這樣做是安全的。但正如你所看到的,至少在TypeScript v2.5中是這樣的,it won't

最簡單的解決辦法:既然你知道一個事實,什麼編譯器不知道......即,現有的filter功能確實會接受T[] | IterableIterator<T> | Dictionary<T>類型的arr,它是安全的告訴編譯器不要擔心通過斷言arrany類型的即禁用類型檢查:

function filter<T>(
    arr: async.Dictionary<T> | T[] | IterableIterator<T>, 
    iterator: (item: T) => Promise<boolean> 
): Promise<Array<(T | undefined)> | undefined> { 
    return new Promise((resolve, reject) => { 
    async.filter(arr as any, (item, cb) => { 
     iterator(item) 
     .then(res => cb(undefined, res)) 
     .catch(err => cb(err)); 
    }, (err, results) => 
     err 
     ? reject(err) 
     : resolve(results) 
    ); 
    }); 
} 

還有其他的解決方法,如寫user-defined type guard到呼叫到async.filter()分成取決於arr類型兩個呼叫;或者用類似於intersectFunction()的東西包裝async.filter函數,以便它接受你想要的聯合,但是這些解決方法體積較大並且具有運行時效果,所以我堅持上面的as any方法。

希望有幫助;祝你好運!

+0

我會用這個解決方案,謝謝@jcalz! –