Typescript使用枚举键迭代对象

时间:2019-02-21 14:18:24

标签: typescript

我想用枚举键遍历一个对象。问题是类型总是在干扰,我宁愿不要强制转换所有内容。

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

如果我尝试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'.
});

我可以投射钥匙,但是甚至不能直接做钥匙...

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:也许不是)

2 个答案:

答案 0 :(得分:1)

如果您不想使用anyunknown

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