簡體   English   中英

如何在存在重載函數的情況下映射可區分聯合列表?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM