带有联合类型的打字稿

Typescript with union types

我有一个接受回调参数的通用函数 fetcher。此回调稍后将在 fetcher 函数中执行(我在这里使用 Vue 可组合模式)。此外,这些回调接受不同的参数作为参数。我输入了 fetcher 回调,它接受“params”参数作为可能参数的联合类型。然后我可以使用这个 fetcher 函数并传递具有不同参数的回调。

代码示例:

type Param1 = {
  a: string;
}
type Param2 = {
  a: string;
  b: string;
}
type Params = Param1 | Param2
declare function fetcher(func: (params: Params) => void): void
declare function testFunc(obj: Param2): void
fetcher(testFunc)

打字稿错误:

Argument of type '(obj: Param2) => void' is not assignable to parameter of type '(params: Params) => void'.
  Types of parameters 'obj' and 'params' are incompatible.
    Type 'Params' is not assignable to type 'Param2'.
      Property 'b' is missing in type 'Param1' but required in type 'Param2'.(2345)

如何键入 fetcher 函数并传递带有声明参数的回调,例如 fetcher 可以接受的 Param1Param2

Playground example

TLDR:declare function fetcher(func: (params: Param1 & Param2) => void): void

解释:

声明:

declare function fetcher(func: (params: Param1 | Param2) => void): void

指示编译器 func 必须同时支持 Param1 和 Param2 类型。

记住:

{ a: string; b: string } | { a: string; } !== { a: string; } & { b?: string }

函数参数的类型联合:

  1. 表示该函数可以处理这两种情况:{a} 和 {a,b}
  2. 并不意味着参数{b}是可选的,所以{a}|{a,b} != {a,b?}

如果你想告诉编译器 fetcher 接受 func(p: Param1)func(p: Param2) 你有两种可能性:

// 1:
declare function fetcher(func: (params: Param1 & Param2) => void): void

// 2:
declare function fetcher(func: ((p: Param1) => void) | ((p: Param2) => void)): void

第二个在语义上更正确,因为它告诉编译器欢迎使用两个参数的函数。