打字稿:键入一组部分应用的函数,这些函数具有可变数量和参数类型,所有 return 相同类型的函数

Typescript: Type a group of partially applied functions with variable number and type of parameters that all return function of same type

我正在寻找一种方法来对一组仅第一个参数不同的部分应用函数进行分组。或者换句话说;该组包含接受任意数量的任意类型参数的函数,但第一个应用程序始终必须 return 类型为 (state: State) => Event[] 的函数。

例如一组这样的函数:

const group = { 
  func1: () => (state: State) => Event[],
  func2: (arg: string) => (state: State) => Event[],
  func3: (arg: string, arg2: number) => (state: State) => Event[],
}

所有这些函数都遵循以下模式(未更新为接受多个参数):

export type Command = <T>(arg: T) => (state: State) => Partial<Event>[];

但是,当我尝试像这样输入组时:

const command: Record<string, Command> = {
  func1: () => (state: State) => [{}],
  func2: (arg: string) => (state: State) => [{}],
  func3: (arg: string, arg2: number) => (state: State) => [{}],
};

Typescript 警告我类型 T 不可分配给类型字符串。

Type '(arg: string) => (state: State) => {}[]' is not assignable to type 'Command'.
  Types of parameters 'arg' and 'arg' are incompatible.
    Type 'T' is not assignable to type 'string'

我明白为什么它不可分配,但我不知道我将如何键入这组部分应用的函数。我基本上想确保此分组中的每个函数都遵循命令类型的模式。也就是说,它应该是一个部分应用的函数,具有任何类型的任何参数 return 类型的函数:(state: State) => Event[]

这可能吗?如果可以,我该怎么做?

像这样在您的类型声明中使用 any 并稍后在您的组中键入函数参数是否有帮助?

export type Command = (...arg: any[]) => (state: State) => Partial<Event>[];

const command: Record<string, Command> = {
  func1: () => (state: State) => [{}],
  func2: (arg: string) => (state: State) => [{}],
  func3: (arg: string, arg2: number) => (state: State) => [{}],
};

更新

为了更具体地使用参数,我会让 Typescript 推断函数签名:

export type Command = (state: State) => Partial<Event>[];

const command = {
  func1: (): Command => (state: State) => [{}],
  func2: (arg: string): Command  => (state: State) => [{}],
  func3: (arg: string, arg2: number): Command => (state: State) => [{}],
};

command.func1() // OK
command.func1("test") // Err
command.func2() // Err
command.func2("test") // OK
command.func2([]) // Err
command.func3() // Err
command.func3("test", 2) // OK
command.func3([]) // Err

或明确键入组:

export type Command = (state: State) => Partial<Event>[];
interface CommandsGroup {
    func1: () => Command;
    func2: (arg: string) => Command;
    func3: (arg: string, arg2: number) => Command
}

const command: CommandsGroup = {
  func1: () => (state: State) => [{}],
  func2: (arg: string) => (state: State) => [{}],
  func3: (arg: string, arg2: number) => (state: State) => [{}],
};

command.func1() // OK
command.func1("test") // Err
command.func2() // Err
command.func2("test") // OK
command.func2([]) // Err
command.func3() // Err
command.func3("test", 2) // OK
command.func3([]) // Err