我需要根据一些规则将一个对象转换为另一个对象。
Types
枚举; Color
和Number
; ValuesByType
接口,其中Types
枚举映射到接口Color
和Number
; source
对象(字典/记录),具有type
枚举的Types
属性。我需要为convert
函数编写类型,该函数返回一个具有与source
对象相同键的新对象,但值应引用到映射到ValuesByType
的接口。
示例:
interface Color {}
interface Number {}
enum Types {
Color,
Number,
}
interface ValuesByType {
[Types.Color]: Color,
[Types.Number]: Number,
}
interface SourceValue<T extends Types = Types> {
type: T;
}
// Need to define types for this function
function convert(source: SourceValue) {
...
}
const source: SourceValue = {
foo: {
type: Types.Color,
},
bar: {
type: Types.Number,
},
};
const result = convert(source);
// The type of "result" veriable should be:
// {
// foo: Color,
// bar: Number
// }
我尝试过这种方法,但是它不起作用:
export type Convert = <
T extends Types,
S extends Record<keyof S, SourceValue<T>>
>(
source: S,
) => Record<keyof S, ValuesByType[T]>;
答案 0 :(得分:1)
解决此问题时要解决的一个问题是输入_sources
对象的类型。在您的TS Playground链接上,当前键入为:
const _source: {
foo: { type: Types; };
bar: { type: Types; };
};
注意如何将type
参数设置为Types
而不是具体的Types.Color
或Types.Number
。
在Typescript 3.4上,您可以通过在定义之后添加as const
来解决此问题:
const _source = {
foo: { type: Types.Color },
bar: { type: Types.Number },
} as const;
或者,在3.4之前,您可以使用Types.Color as Types.Color
来获取打字稿,将其视为文字值。
清除后,“映射类型”将获取您需要的返回值。我将其编写为通用帮助程序类型。
type ConvertedSources<T extends Record<string, SourceValue<any>>> = {
[key in keyof T]: ValuesByType[T[key]['type']]
};
如果将typeof _source
传递给它,您将看到_source
中的每个属性如何基于您的ValuesByType
接口映射到相应的值类型。
然后,您只需要让函数在其签名中使用它,并保留相同的类型约束即可即可:
function convert<
TSources extends Record<string, SourceValue<any>>
>(source: TSources): ConvertedSources<TSources> { ... }
请注意,您还需要将reduce()
调用的结果强制转换为ConvertedSources<TSources>
,或更改一些内部代码以保留类型。