for循环中丢失枚举类型信息

时间:2019-07-01 09:04:44

标签: typescript enums

在下面的示例中,myColors的键的类型为Color。但是,在遍历myColor对象时,我很难保留该信息。

enum Color {
  Red = 'RED',
  Green = 'GREEN',
}

type MyColors = {
  [C in Color]?: string;
}

const myColors: MyColors = {
  [Color.Red]: '#8B0000',
}

for (const [name, hex] of Object.entries(myColors)) {
  // name is of type string here instead of Color
}

使用常规的for in循环或Object.keys(myColors)还将枚举键转换为字符串。

在遍历对象的属性时,是否可以保留键的类型?如果不是,我如何断言循环中的nameColor类型?

1 个答案:

答案 0 :(得分:3)

TypeScript对Object.entries的定义已重载,但两个重载都显式地使用字符串作为键类型。来自lib/lib.es2017.object.d.ts

/**
 * Returns an array of key/values of the enumerable properties of an object
 * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
 */
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];

/**
 * Returns an array of key/values of the enumerable properties of an object
 * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
 */
entries(o: {}): [string, any][];

我敢肯定有充分的理由。 :-)但是您可以定义自己的entries,而不使用string

// Our `entries` function
function entries<T>(o: T): [keyof T, T[keyof T]][] {
    return Object.entries(o) as unknown as [keyof T, T[keyof T]][];
}

然后它起作用了

for (const [name, hex] of entries(myColors)) {
  // type of `name` is `Color` now
}

进一步说,我发现如果添加以下声明:

interface ObjectConstructor {
    /**
     * Returns an array of key/values of the enumerable properties of an object
     * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
     */
    entries<T>(o: T): [keyof T, T[keyof T]][];
}

这样,您的原始代码将按预期工作:

for (const [name, hex] of Object.entries(myColors)) {
  // type of `name` is `Color` now
}

(我通过在循环主体中使用const n: Color = name;来使用真正的编译器(不仅是游乐场进行了仔细检查。TypeScript抱怨它没有声明,但声明很高兴。)

但是,TypeScript问题列表中的一些问题使我认为,定义可能会对您要传递的Object.entries,特别是this one和{ {3}}。因此,您可能希望拥有单独的功能(很可能会取消JIT)并在相关位置使用它。