如何返回接口中方法的ReturnType元组,该元组是变量参数的类型



我想写一个如下所示的方法。接口A是生成器的配置类型。我将对不同类型的生成器进行不同的配置,并在函数f中同时使用它们,以便在元组中获得所有生成的值。

interface A<Output> {
f: () => Output;
};
const a: A<string> = {
f: () => 'Hello',
};
const b: A<number> = {
f: () => 42,
};
function f(...x: ???): ??? {
return x.map(x => x.f());
}
const y: [string, number] = f(a, b);
console.log(y) // ['Hello', 42]

我如何在没有任何错误的情况下实现这一点?

您可以将函数表示为作用于泛型映射元组的类型。如果输出是T类型的元组,那么输入是{[I in keyof T]: A<T[I]>}类型,这意味着:对于T元组中的每个索引I,输入应该是A<T[I]>类型,输出是T[I]:类型

function f<T extends any[]>(...x: { [I in keyof T]: A<T[I]> }) {
return x.map(x => x.f()) as T;
}

请注意,编译器没有也可能永远无法验证x.map(...)是否实际生成了预期类型的值;即使通常表示这样的转换也需要更高级的kinded类型之类的东西,而TypeScript目前不支持这些类型(有关相关功能请求,请参阅microsoft/TypeScript#1213(。最简单的方法是我上面所做的:通过编写x.map(...) as T,断言输出的类型为T


让我们确保它有效:

const y = f(a, b); // [string, number]
console.log(y[0].toUpperCase()) // "HELLO"
console.log(y[1].toFixed(2)) // "42.00"

是的,看起来不错。


哦,您可以将此转换表示为使用ReturnType<T>实用程序类型的东西,但编写起来更麻烦:

function f<T extends A<any>[]>(...x: T) {
return x.map(x => x.f()) as { 
[I in keyof T]: ReturnType<Extract<T[I], A<any>>["f"]> 
};
}

不过,从调用方的角度来看,它的行为类似。


到代码的游乐场链接

最新更新