打字稿:键入一组部分应用的函数,这些函数的数量和参数类型可变,都返回相同类型的函数

问题描述

我正在寻找一种方法来对一组部分应用的函数进行分组,只有第一个参数不同。或者换句话说;该组包含接受任意数量的任意类型参数的函数,但第一个应用程序始终必须返回类型为 (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) => [{}],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'

我明白为什么它不可分配,但我不知道我将如何输入这组部分应用的函数。我基本上想确保这个分组中的每个函数都遵循命令类型的模式。也就是说,它应该是一个部分应用函数,任何类型的任何参数都返回一个类型的函数(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) => [{}],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) => [{}],2) // OK
command.func3([]) // Err