[英]How to map over a List of Discriminate Unions in the presence of overloaded functions?
鑒於以下代碼:
type Foo = {
foo: number
}
type Bar = {
bar: string
}
type FooOrBar =
| Foo
| Bar
type FooOrBarList =
| Foo[]
| Bar[]
function processFooOrBar(x: Foo): Foo;
function processFooOrBar(x: Bar): Bar;
function processFooOrBar(x: FooOrBar): FooOrBar {
return x
}
function processFooOrBarList(x: Foo[]): Foo[];
function processFooOrBarList(x: Bar[]): Bar[];
function processFooOrBarList(x: FooOrBarList): FooOrBarList {
return x.map(processFooOrBar)
}
我在x.map(processFooOrBar)
上收到以下錯誤
This expression is not callable. Each member of the union type ' (<U>(callbackfn: (value: Foo, index: number, array: Foo[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: Bar, index: number, array: Bar[]) => U, thisArg?: any) => U[])' has signatures, but none of those signatures are compatible with each other.ts(2349)
我確實理解錯誤消息告訴我的內容,但我不明白為什么。
這是一個編譯器錯誤(因為編譯器應該能夠統一這些錯誤)還是我遇到了一些關於類型理論的硬限制?
上面的代碼有3個問題。
首先是Array.map
是泛型的,不能正確調用聯合類型。
此處描述了問題( https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html#improved-behavior-for-calling-union-types )和可能的解決方案( 打字稿:如何映射聯合數組類型? )
所以上面案例中的soution看起來像這樣
function processFooOrBarList(x: FooOrBarList): FooOrBarList { return (x as Array<Foo | Bar>).map(processFooOrBar) }
然而,這還不夠,因為推斷的返回類型與定義的返回類型不匹配,因此我們必須再次轉換。
function processFooOrBarList(x: FooOrBarList): FooOrBarList { return (x as Array<Foo | Bar>).map(processFooOrBar) as FooBarList }
由於存在重載的processFooOrBar
函數以及編譯器無法選擇正確的重載,現在仍然存在問題。 所以我們需要通過強制轉換給編譯器另一個提示。
function processFooOrBarList(x: FooOrBarList): FooOrBarList { const f = processFooOrBar as (x: FooOrBar) => FooOrBar return (x as Array<Foo | Bar>).map(y => f(y)) as FooOrBarList }
我們通過為Array.map
調用的函數f
顯式選擇正確的函數簽名來做到這Array.map
readonly
以通過更改由於轉換而找不到的底層數組來防止錯誤。可以在此處找到完整的工作示例Playground 鏈接
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.