如何聚合作为函数聚合的对象的所有参数类型?

how to aggregate all param types of an object which is an aggregation of functions?

请看一下这个打字稿代码:

type params1 = {p:number} ;
type params2 = {p:boolean};
type params3 = {p:string};
type res = {r:string};

const fObject = {
a:(a:params1):res=>{return {r:`${a.p}`}},
b:(a:params2):res=>{return {r:`${a.p?1:0}`}},
c:(a:params3):res=>{return {r:a.p}}
}

我们如何创建如下所示的类型:

输入参数 = 参数 1 |参数2 |参数 3

我正在创建一个新对象,它将是 fObject 的所有函数,但 运行 将是每个函数结果的记录器函数

像这样:

const loggingObject: typeof fObject = Object.keys(fObject).reduce(
 (result: any, key: string) => {
   result[key] = (args: any/*reason for Q*/) => logger.report(fObject
  [key as loggingObject](args /*If i put something like 2 it says it has no properties in common with params1 & param2 & param3, thats why I know its possible*/));
   return result;
  },
  {},
);

我不想要 any 类型,我需要一个动态类型,它可以接受一个带有函数的对象,并给出对象中所有函数的所有参数类型的联合

好问题。这 可能的——有多种方式! 在此解决方案中,我们将使用以下技术:

如果您想深入了解一下并且我的解释不够连贯,这些链接可能会有所帮助。最后我们将得到一个像这样工作的类型:

// your code here...
type MyParams = ParamForKeys<typeof fObject>;
// => `type MyParams = param1 | param2 | param3`

所以我们要做的是映射fObject的键,并用其函数的参数类型替换每个键。键映射如下所示:

type MyParams<T> = { [key in keyof T]: ... }

现在我们要提取参数类型。这将使用条件类型。条件类型允许我们使用 infer 键:

type UnwrapPromise<T> = T extends Promise<infer Inner> ? Inner : never;
type A = UnwrapPromise<Promise<number>> // => number
type B = UnwrapPromise<number> // => never

这正是我们要使用的方法:

type GetFirstParam<T> = T extends ((param: infer Param) => any) ? Param : never

现在如果我们一起构建它,我们将得到:

type GetFirstParam<T> = T extends ((param: infer Param) => any) ? Param : never
type ParamForKeys<T> = { [key in keyof T]: GetFirstParam<T[key]> }

但这给了我们以下类型:

type MyParams = ParamForKeys<typeof fObject>;
// { a: param1, b: param2, c: param3 }

要以联合格式 (param1 | param2 | param3) 取回值,我们可以像这样访问它们:

type GetFirstParam<T> = T extends ((param: infer Param) => any) ? Param : never
type ParamForKeys<T> = { [key in keyof T]: GetFirstParam<T[key]> }[keyof T]

这就是解决方案。 请记住,我不确定这个解决方案是否是您正在寻找的解决方案:就您的日志记录情况而言,{a: param1, b:param2} 对我来说更有意义,但这是您问题的解决方案!

希望已经清楚了。 You can see it live in this TypeScript playground.