我正在创建这个类(playground link):
export class CascadeStrategies<
T extends Record<any, (...args: any[]) => unknown>
> {
private strategies: T = {} as T;
constructor(strategyMap: T) {
this.registerStrategies(strategyMap);
}
private registerStrategies(strategyMap: T) {
this.strategies = strategyMap;
}
use(
strategies: (keyof T)[],
...args: Parameters<T[keyof T]>
): ReturnType<T[keyof T]> {
return this.strategies[strategies[0]](...args);
}
}
此类的预期用途应为
const myMap = {
test: (arg1: number, arg2: string) => arg1,
otherTest: (arg1: number, arg2: string) => arg2,
thirdTest: (arg1: number, arg2: string) => null
}
const cascadeStrats = new CascadeStrategies(myMap);
const shouldBeNumber = cascadeStrats.use(["test"], 0, "");
const shouldBeString = cascadeStrats.use(["otherTest"], 0, "");
const shouldBeNull = cascadeStrats.use(["thirdTest"], 0, "");
I want T
to be an object whose entries are functions that can accept the same set of parameters and returns a string
, so I am using T extends Record<any, (...args: unknown[]) => string
.
With this typing, this.strategies[strategies[0]](...args)
has type unknown
which is incompatible with the expected ReturnType<T[keyof T]>
.
如果我将strategies
的类型从T
更改为Record<any, any>
,this.strategies[strategies[0]](...args)
将具有正确的类型,并且在使用时正确推断.即使strategies
只是一个内部变量,在使用类时不会影响DX,我想知道我在这里缺少什么来实现预期的结果:
- 用户定义
strategyMap
时正确推断(即,其条目是接受相同参数集并返回string
的函数的对象). -
strategies
不是Record<any, any>
类型 - 当用户使用
cascadeStrats.use
时,他在函数的参数和返回的类型中得到了正确的推断.