如何 return 接口中方法的 ReturnType 的元组,它是一种可变参数
How to return a tuple of ReturnType of a method in the interface which is a type of variable arguments
我想完成编写如下所示的方法。接口 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]
我怎样才能做到没有任何错误?
您可以将函数表示为作用于泛型的类型 mapped tuple。如果输出是 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(...)
是否实际生成了预期类型的值;即使一般表示这种转换也需要类似 higher kinded types 之类的东西,目前 TypeScript 不支持它们(参见 microsoft/TypeScript#1213 for a relevant feature request). The easiest thing to do is what I've done above: just assert 输出类型为 T
, 通过写 x.map(...) as T
.
让我们确保它有效:
const y = f(a, b); // [string, number]
console.log(y[0].toUpperCase()) // "HELLO"
console.log(y[1].toFixed(2)) // "42.00"
是的,看起来不错。
哦,你可以用ReturnType<T>
utility type表示这个转换,但是写起来比较麻烦:
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"]>
};
}
不过,它在调用方方面的行为类似。
我想完成编写如下所示的方法。接口 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]
我怎样才能做到没有任何错误?
您可以将函数表示为作用于泛型的类型 mapped tuple。如果输出是 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(...)
是否实际生成了预期类型的值;即使一般表示这种转换也需要类似 higher kinded types 之类的东西,目前 TypeScript 不支持它们(参见 microsoft/TypeScript#1213 for a relevant feature request). The easiest thing to do is what I've done above: just assert 输出类型为 T
, 通过写 x.map(...) as T
.
让我们确保它有效:
const y = f(a, b); // [string, number]
console.log(y[0].toUpperCase()) // "HELLO"
console.log(y[1].toFixed(2)) // "42.00"
是的,看起来不错。
哦,你可以用ReturnType<T>
utility type表示这个转换,但是写起来比较麻烦:
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"]>
};
}
不过,它在调用方方面的行为类似。