我有一个接口,该接口带有一个可以是函数类型或字符串的函数(对于异步函数,因此tsc不会转换它们)。问题出在我的任务运行程序上,我似乎无法弄清楚如何根据接口上的func
属性确定函数的参数行为。例如,将其推断为string | (...args: any[]) => number)
。问题是当我尝试检查func: (x: number) => x + 1)
函数调用中的func参数以使其需要带有参数的函数上的参数时,它没有正确地检查它是否扩展了函数,而是将参数推断为run
比any[]
大。有人知道该怎么做吗?
我的意思示例:
number
如果您希望编译器对TS Playground Link属性的类型有足够的了解,以了解其参数,则需要通用类型参数来包含这些参数。您的func
具有ITask<T>
,如果它是一个函数,则仅表示T
的返回类型,并且参数类型为func
,这根本不是通用的。这是另一种可能的类型,它能够跟踪函数参数和返回类型:
any[]
这里interface ITask<F extends string | ((...args: any) => any)> {
id: number;
func: F;
};
属性只是通用类型func
,它已被F
用作函数类型或字符串。
constrained的定义相应更改:
Task
您的class Task<F extends string | ((...args: any) => any)> implements ITask<F> {
public id: number;
public func: F
constructor(opts: ITask<F>) {
this.id = opts.id;
this.func = opts.func;
}
}
类几乎保持相同(尽管最好避免Runner
),尽管您可能会或可能不想更强地键入其返回值(之前只是eval()
:]
any
现在您得到这种行为:
class Runner {
constructor() { }
public run<T>(
task: { func: T },
...args: T extends (...args: infer Args) => any ? Args : any[]
): T extends (...args: any) => infer R ? R : any {
if (typeof task.func === 'function')
return task.func(...args);
else
return eval(`(${task.func})`);
}
}
这对我来说看起来都很合理。好的,希望能有所帮助;祝你好运!
const task = new Task({ id: 1, func: (x: number) => x + 1 });
const runner = new Runner();
runner.run(task); // error! expected 2 arguments but got one
const numVal = runner.run(task, 10); // okay
// const numVal: number;
const anyVal = runner.run(new Task({ id: 2, func: "someString" })); //okay
// const anyVal: any;