我想编写一个使用服务的通用函数。基于此服务,应提供一组可用的操作。根据所选择的动作,应提供所需的参数。
下面是一个最小的例子:
class BaseService {
declare baseAction: (base: string) => void // Must not be shown as an `action` option
}
class MyService extends BaseService {
declare fooAction: (foo1: number, foo2: string) => void
declare barAction: (bar: string) => void
}
class MyOtherService extends BaseService {
declare otherAction: (other: number) => void
}
function invokeAction<TService extends BaseService>(
action: Exclude<keyof TService, keyof BaseService> & string,
...args: Parameters<Extract<TService[typeof action], (...args: any) => any>>
) {}
invokeAction<MyService>("fooAction", 1, "foo") // This is supposed to work â
invokeAction<MyService>("barAction", "bar") // This is supposed to work â
invokeAction<MyService>("barAction", 1, "foo") // This is NOT supposed to work â
invokeAction<MyOtherService>("otherAction", 1) // This is supposed to work â
invokeAction<MyOtherService>("barAction", "bar) // This is NOT supposed to work â
有了这个,the
action
根据服务正确选择选项。但是
...args
包括中可用的所有操作的参数
TService
。我能否以某种方式缩小范围,而不需要像这样键入两次动作:
function invokeActionWorkaround<
TService extends BaseService,
TAction extends Exclude<keyof TService, keyof BaseService> & string
>(
action: TAction,
...args: Parameters<Extract<TService[TAction], (...args: any) => any>>
) {}
在这里,我必须指定两次操作名称(没有IntelliSense),但操作的参数是正确确定的。