在下面的示例中,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)
还将枚举键转换为字符串。
在遍历对象的属性时,是否可以保留键的类型?如果不是,我如何断言循环中的name
是Color
类型?
答案 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)并在相关位置使用它。