我正在寻找一种连接这两种类型并具有映射的方法:
type MappingForEnum<T extends string, A extends string, B extends string> = {
[key in T]: {[key in A]: B};
[key in T]: {[key in B]: A};
};
enum Greek {
ALPHA = 'A',
BETA = 'B',
}
enum English {
A = 'A',
B = 'B',
}
enum types{
TO_ENGLISH = 'toEnglish',
TO_GREEK = 'toGreek',
}
const mapping: MappingForEnum<Types, Greek, English> = {
toEnglish: {
[Greek.ALPHA]: English.A,
[Greek.BETA]: English.B,
},
toGreek: {
[English.A]: Greek.ALPHA,
[English.B]: Greek.BETA,
},
};
如何修改MappingForEnum
使其起作用?
更新
有没有一种方法可以设置这种PureMapping
并将其包装起来以匹配下面的注释。
type PureMapping = {
toGreek: Greek,
toEnglish: English,
};
type Mapping = WrapMapping<PureMapping>;
// type Mapping = {
// toGreek: MappingForEnum<Greek, English>,
// toEnglish: MappingForEnum<English, Greek>,
// };
答案 0 :(得分:0)
问题是您的types
枚举不能保证只有两个成员。此外,也无法知道哪个成员将英语映射为希腊语,哪个成员将反向映射。如果types
只有一个或三个成员,怎么办?
一种解决方案是摆脱第一个泛型类型参数,而仅依赖于硬编码的属性名称(例如,选择比convert
/ reverse
更好的名称):>
type MappingForEnum<A extends string, B extends string> = {
convert: {[key in A]: B};
reverse: {[key in B]: A};
};
...
const mapping: MappingForEnum<Greek, English> = {
convert: {
[Greek.ALPHA]: English.A,
[Greek.BETA]: English.B,
},
reverse: {
[English.A]: Greek.ALPHA,
[English.B]: Greek.BETA,
},
};
或者,您可以将类型分解为较小的单向映射,然后将它们组合在一起:
type MappingForEnum<A extends string, B extends string> = { [key in A]: B };
type GreekEnglishMapping = {
toEnglish: MappingForEnum<Greek, English>;
toGreek: MappingForEnum<English, Greek>;
};
...
const mapping: GreekEnglishMapping = {
toEnglish: {
[Greek.ALPHA]: English.A,
[Greek.BETA]: English.B,
},
toGreek: {
[English.A]: Greek.ALPHA,
[English.B]: Greek.BETA,
},
};
请注意,使用第二种解决方案,获得与原始types
枚举类似的联合类型非常容易:
type supportedMappings = keyof GreekEnglishMapping; // "toEnglish" | "toGreek"
这是另一种方法:
type MappingForEnum<A extends string, B extends string> = { [key in A]: B };
type TwoWayMapping<T extends { [0]: string, [1]: string }, A extends string, B extends string> =
{ [key in T[0]]: MappingForEnum<A, B> } &
{ [key in T[1]]: MappingForEnum<B, A> };
type GreekEnglishMapping = TwoWayMapping<[ 'toEnglish', 'toGreek' ], Greek, English>;
遗憾的是,即使您定义
enum MappingNames {
toEnglish,
toGreek,
}
在运行时定义了MappingNames[0]
的情况下,编译器将不了解它,因此以下代码将不起作用:
type GreekEnglishMapping = TwoWayMapping<MappingNames, Greek, English>;
// Type 'MappingNames' does not satisfy the constraint '{ [0]: string; [1]: string; }'.
再刺一击:
type MappingForEnum<A extends string, B extends string> = { [key in A]: B };
type TwoWayMapping<T extends { [k: string]: A | B }, A extends string, B extends string> = {
[key in keyof T]: T[key] extends A ? MappingForEnum<A, B> : MappingForEnum<B, A>
};
type PureMapping = {
toEnglish: Greek,
toGreek: English,
};
type GreekEnglishMapping = TwoWayMapping<PureMapping, Greek, English>;
我觉得这可能与您最初想要的差不多。我认为不必两次指定Greek
/ English
(一次在映射类型中,一次作为通用参数)。