我想用枚举键遍历一个对象。问题是类型总是在干扰,我宁愿不要强制转换所有内容。
enum MyEnum { A, B, C }
type MyMap = { [key in MyEnum]: string };
const myMap: MyMap = {
[MyEnum.A]: 'a?',
[MyEnum.B]: 'b',
[MyEnum.C]: 'c...',
};
如果我尝试Object.keys
或for..in
,它总是显示错误。
Object.keys(myMap).forEach(key => {
const data = myMap[key]; // <= Error TS7017: Element implicitly has an 'any' type because type 'MyMap' has no index signature.
});
// same with: for (const key in myMap) {
Object.keys(myMap).forEach((key: MyEnum) => { // Error TS2345: Argument of ... Type 'string' is not assignable to type 'MyEnum'.
});
我可以投射钥匙,但是甚至不能直接做钥匙...
Object.keys(myMap).forEach(key => {
const data = myMap[key as MyEnum]; // Error TS2352: Conversion of type 'string' to type 'MyEnum' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
// have to do this but would prefer not to
const data2 = myMap[key as unknown as MyEnum];
});
某处可能有解决方案,但我没有使用正确的关键字,也没有找到它:((edit:也许不是)
答案 0 :(得分:1)
如果您不想使用any
或unknown
const data = myMap[MyEnum[key as keyof typeof MyEnum]];
答案 1 :(得分:0)
我现在最满意的解决方案是添加一个辅助函数来进行键的转换。这对于所有相似的对象也很容易重用。
export function objectKeys<Obj extends object>(obj: Obj): (keyof Obj)[] {
return Object.keys(obj) as (keyof Obj)[];
}
// with example from above
// no specific type for the map needed
const myMap = {
[MyEnum.A]: 'a?',
[MyEnum.B]: 'b',
[MyEnum.C]: 'c...',
};
objectKeys(myMap).forEach(key => {
// key: MyEnum
// if the enum has more values that are not part of the map (D..)
// the types are still correct => key: MyEnum.A | MyEnum.B | MyEnum.C
});
注意:这并不完美。 例如与数组
objectKeys([]).forEach(key => {
// key: number | 'length' | ...
// would be perfect if it returned only `number` or even `never` (empty array)
});