我有两个对象,我的自定义map函数将一个对象的prop映射到另一个对象的值,例如:
const obj1 = {
host: 'clientNameHost',
pass: 'clientNamePass',
};
const obj2 = {
clientNamePass: '12345',
clientNameHost: 'http://localhost:3000',
};
const mapParams = <T, K>(source: T, params: K) => Object.entries(params)
.reduce((acc, [param, sourceProp]) => ({ ...acc, [param]: source[sourceProp] }), {});
mapParams(obj2, obj1) //{host: "http://localhost:3000", pass: "12345"}
我很难输入此函数。有什么方法可以正确键入mapParams函数吗?
答案 0 :(得分:0)
解决方案是缩小泛型类型,以显示两个参数中键和值之间的关系:
const obj1 = {
host: 'clientNameHost',
pass: 'clientNamePass',
} as const;
const obj2 = {
clientNamePass: '12345',
clientNameHost: 'http://localhost:3000',
} as const;
const mapParams = <T extends Record<string, any>, K extends keyof T, P extends Record<T[K], any>>(source: T, params: P) => Object.entries(params)
.reduce((acc, [param, value]) => ({ ...acc, [param]: source[value as T[K]] }), {});
console.log(mapParams(obj1, obj2)) //{host: "http://localhost:3000", pass: "12345"}
关键部分:
T extends Record<string, any>
的第一种类型是带有字符串键的记录K extends keyof T
代表T
P extends Record<T[K], any>
的关键部分-我们希望对象在T
中具有相等的键值as const
是为了正确推断缩小的类型以上类型会在第一个参数值和第二个参数键之间创建一个边界。
PS。很抱歉还原参数顺序。
答案 1 :(得分:0)
在键入函数时,我最关心的是参数和返回类型。
您可以这样输入参数:
<InputProps, TargetProps extends Record<keyof TargetProps, keyof InputProps>>(
source: InputProps,
params: TargetProps
) => ...
如果第二个对象与第一个对象不匹配,Typescript将抱怨。
对于返回值,您可以定义以下实用程序类型:
type MapFrom<A, B> = Record<keyof A, B[keyof B]>;
通过使用Object.proptotype.entries
类型的参数,我们不必强制转换sourceProp
。
要保留函数签名,我们需要在reduce中声明initialValue
的类型。
我还使用const断言为对象文字赋予只读属性
这是完整的结果:
type MapFrom<A, B> = Record<keyof A, B[keyof B]>;
const obj1 = {
host: "clientNameHost",
pass: "clientNamePass"
} as const;
const obj2 = {
clientNamePass: "12345",
clientNameHost: "http://localhost:3000"
} as const;
const mapParams = <InputProps, TargetProps extends Record<keyof TargetProps, keyof InputProps>>(
source: InputProps,
params: TargetProps
) =>
Object.entries<keyof InputProps>(params).reduce(
(acc, [param, sourceProp]) => ({
...acc,
[param]: source[sourceProp]
}),
{} as MapFrom<TargetProps, InputProps>
);
const obj3 = mapParams(obj2, obj1);
Here,您可以尝试一下。