我希望函数的调用者提供一个关联的函数数组。 我的函数将返回一个新的关联函数数组,它们具有相同的键,返回类型相同,但函数将采用与传递给函数的映射函数不同的参数。
我无法弄清楚如何创建此函数的返回类型。
到目前为止,我的尝试是:
type FunctionMap<A> = {
[functionName: string]: <R>(a: A) => R
}
type B = {};
const b: B = {};
const FunctionMapArg: FunctionMap<B> = {
getA: b => 1,
getB: b => "two"
};
type TypeOfFunctionMapArg = typeof FunctionMapArg;
type ReturnedFunctionMap<T extends TypeOfFunctionMapArg> = {
[P in keyof T]: () => ???; // using Typescript 2.6
// [P in keyof T]: () => ReturnType<T[P]); // using Typescript 2.8
}
然而,这在第一步失败了 - 我甚至无法宣布FunctionMapArg
常数。我从编译器中收到以下错误:
Type '{ getA: <R>(a: any) => number; getB: <R>(a: any) => string; }' is not assignable to type 'FunctionMap<any>'.
Property 'getA' is incompatible with index signature.
Type '<R>(a: any) => number' is not assignable to type '<R>(a: any) => R'.
Type 'number' is not assignable to type 'R'.
请有人请我指明正确的方向吗?理想情况下,我正在寻找适用于Typescript 2.6的解决方案。
答案 0 :(得分:2)
我不确定你想要输入和输出函数的参数是什么,所以这是猜测。主要思想是使用mapped types和inference from mapped types来表示您想要实现的转换。 (这两个功能都应该适用于TypeScript 2.6。)例如,假设您的输入函数如下所示:
type B = {
// input function argument type here
};
const functionMapArg = {
getA: (b: B) => 1,
getB: (b: B) => "two"
};
declare const b: B;
const gotA = functionMapArg.getA(b); // number
const gotB = functionMapArg.getB(b); // string
然后,这是改变functionMapArg
的一种方式:
type Functionize<T, A> = { [K in keyof T]: (a: A) => T[K] };
type C = {
// output function argument type here
};
declare function alterFunctions<T>(fs: Functionize<T, B>): Functionize<T, C>;
Functionize<T, A>
采用常规对象类型T
并生成一个映射类型,其键K
与T
的键相同,其值是来自{{的函数1}}到A
。 T[K]
将alterFunctions()
作为输入(例如Functionize<T, B>
),并生成functionMapArg
作为输出...其中TypeScript编译器推断类型Functionize<T, C>
为了你。让我们看看它是否有效:
T
因此const alteredFunctions = alterFunctions(functionMapArg);
declare const c: C;
const gotAnotherA = alteredFunctions.getA(c); // number
const gotAnotherB = alteredFunctions.getB(c); // string
与alteredFunctions
类似,但其方法采用类型为functionMapArg
的参数,而不是C
类型的参数。这就是你要找的东西吗?
希望有所帮助;祝你好运!
更新:如果你想避免为B
中的每个函数编写参数类型,你可以创建一个辅助函数,它需要输入类型functionMapArg
并返回输入不变,如下所示:
Functionize<any, B>
这样编译器就会推断出参数类型:
function asFunctionsOfB<F extends Functionize<any, B>>(fs: F): F {
return fs;
}
希望有所帮助。