【发布时间】:2022-01-13 08:26:14
【问题描述】:
我正在尝试创建一个可以接收两条记录的函数,其中:
- 第二个依赖于第一个并且两个记录具有相同的键
- 它们都将函数作为具有相同参数但返回类型不同的值。
我尝试了以下方法(及其许多变体):
export const withGenericLogging = (
logger: Logger,
component: string,
subcomponent: string,
) => <
Keys extends string,
ObjFn extends (...args: any[]) => unknown,
Obj extends Record<Keys, ObjFn>,
Mappers extends Record<Keys, (...args: Parameters<ObjFn>) => unknown>,
>(
obj: Obj,
mappers: Mappers,
) =>
Object.keys(obj).reduce<Obj>(
(acc, key) => {
if (typeof obj[key] !== 'function') {
return acc;
}
const mapper = mappers?.[key]
acc[key] = withLogging(
logger,
component,
subcomponent ? `${subcomponent}.${key}` : key,
)(obj[key], mapper);
return acc;
},
{ ...obj },
);
注意:withLogging、Logger 和 logger 的实现与此问题无关。
这很好用,因为打字稿知道如果我执行以下操作:
const create = (id: string) => 'value'
const repository = withGenericLogging(
log,
'Module',
'Submodule'
)(
{ create },
{ create: id => 'mappedId' },
);
会发生以下情况:
-
repository将完全继承obj的类型(如预期的那样,它将是{ create: (id: string) => string }类型) - IDE 将为
mappers参数提供某种类型的支持(IDE 建议{ create: id => 'mappedId' }中的create键) -
id => 'mappedId'中的id是any类型,它应该是string类型
withGenericLogging能否提供:
- 支持对其返回值的类型推断(在上面的示例中:
repository) - 支持
mappers的密钥类型(应与obj的密钥相同) - 支持
mappers记录右侧函数的参数,该参数应与obj记录右侧函数的参数相同(如@987654342 @是{ create: (id: string) => Promise<void> },mappers应该是{ create: (id: string) => unknown }) - 只是一种处理类型的通用方式,而不是固定的(
obj应该支持任何类型的Record<string, (...args: unknown[]) => unknown>,而不是固定的type Something = { create: (id: string) => Promise<void> })
【问题讨论】:
标签: typescript types