如何基于作为联合类型的接口属性确定函数的参数行为?

问题描述 投票:0回答:1

我有一个接口,该接口带有一个可以是函数类型或字符串的函数(对于异步函数,因此tsc不会转换它们)。问题出在我的任务运行程序上,我似乎无法弄清楚如何根据接口上的func属性确定函数的参数行为。例如,将其推断为string | (...args: any[]) => number)。问题是当我尝试检查func: (x: number) => x + 1)函数调用中的func参数以使其需要带有参数的函数上的参数时,它没有正确地检查它是否扩展了函数,而是将参数推断为runany[]大。有人知道该怎么做吗?

我的意思示例:

number

typescript
1个回答
0
投票

如果您希望编译器对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;

© www.soinside.com 2019 - 2024. All rights reserved.