简体   繁体   English

打字稿用枚举键迭代对象

[英]Typescript iterate object with enum keys

I would like to iterate over an object with enum keys.我想用枚举键迭代一个对象。 Problem is that the types are always interfering and I would prefer to not cast everything.问题是类型总是干扰,我宁愿不投射一切。

enum MyEnum { A, B, C }
type MyMap = { [key in MyEnum]: string };
const myMap: MyMap = {
    [MyEnum.A]: 'a?',
    [MyEnum.B]: 'b',
    [MyEnum.C]: 'c...',
};

If I try Object.keys or for..in it always shows errors.如果我尝试Object.keysfor..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'.
});

I could cast the key but can't even do it directly...我可以投钥匙,但甚至不能直接做...

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];
});

There probably is a solution somewhere but I didn't use the right keywords and didn't find it :( (edit: or maybe not)某处可能有一个解决方案,但我没有使用正确的关键字并且没有找到它:((编辑:或者可能没有)

如果您不想使用anyunknown

    const data = myMap[MyEnum[key as keyof typeof MyEnum]];

The solution I'm most happy with now is adding a helper function that does the casting of the keys.我现在最满意的解决方案是添加一个辅助函数来执行键的转换。 This is also easily reusable for all kinds of similar objects.这对于各种类似的对象也很容易重用。

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
});

Note: It's not perfect.注意:它并不完美。 eg with arrays例如使用数组

objectKeys([]).forEach(key => {
  // key: number | 'length' | ...
  // would be perfect if it returned only `number` or even `never` (empty array)
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM