2016-01-26 79 views
0

我寫這個API庫:打字稿:強制仿製T和U

export var reduce = <T, U>(
    tArray: T[], 
    tReducer: (current: U, tItem: T, index: number, tArray: T[]) => U, 
    options: IChunkifyOptions = DEFAULT_OPTIONS, 
    memo?: U 
): Promise<U> 

實施,像標準的JavaScript reduce使用的tArray第一項爲memo如果沒有memo提供了依據。

if (memo === undefined) { 
    memo = tArray[0]; // Type 'T' is not assignable to Type 'U' 
} 

鑄造(<U>)給出,合理,Neither Type 'T' nor Type 'U' is assignable to the other.

什麼是一個合理的方式來定義的API?

+0

回答[here](http://stackoverflow.com/a/28310171/2419669)。首先投給「」! – yangmillstheory

+0

使用''鑄造時要謹慎。重寫TypeScript的類型安全性可能會導致許多無法預料的問題。我只允許在測試嘲笑和我的團隊存根,並有充分的理由。在採用''演員陣容之前,請花點時間考慮下面的答案。 – SnareChops

回答

1

問題是T不能指定爲U,因爲錯誤解釋。下面是如果memo沒有定義,那麼在tArray

if (memo === undefined) { 
    memo = tArray[0]; 
} 

分配memo的第一個項目你已經宣佈memoU,你試圖給它分配的值破敗......

在你的榜樣a T

T !== U因此您會收到錯誤消息。

現在,簡單地使用memo = <U><any>tArray[0]來施放它們可能很誘人,但問自己:「爲什麼這是必要的?」

您打算如何保留memo?當有人使用不同的物體時會發生什麼

reduce<Car, Watermelon>(...) 

我懷疑你在這裏有不同的意圖。難道memo真的應該是T | UT extend U

走下<U><any>路徑可能會導致許多意想不到的運行時錯誤,並且在您的API增加時很難找到錯誤。我認爲在採取簡單的方法之前,你需要再看看你想要的行爲,然後用<U><any>

+0

感謝您的意見。我之前嘗試過'extends',但是不能基於同一個「括號」中的另一個類型來約束一個類型。我會更多地考慮這一點,但是當我使用導出的API玩時,編譯器似乎表現得像預期的那樣,有或沒有提供的「備忘錄」。 但我絕對不認爲'T'或'U'應該限制對方。 – yangmillstheory

+0

然後我會推薦'備忘錄:T | U'因爲這基本上就是你在用'' – SnareChops