避免任何类型在打字稿中获取枚举值
Posted
技术标签:
【中文标题】避免任何类型在打字稿中获取枚举值【英文标题】:Avoid any type getting enum values in typescript 【发布时间】:2021-07-08 22:47:24 【问题描述】:我需要遍历枚举类型以填充反应组件中的一些选项。 在枚举下方找到从中返回键和值的函数。
export enum ProyectType
time,
hits,
value,
results
function projectTypeValues()
const values = Object.keys(ProyectType).filter(k => typeof ProyectType[k as any] === "number"); // ["time", "hits", "value", "results"]
const keys = values.map(k => ProyectType[k as any]); // [0, 1, 2, 3]
我不喜欢ProyectType[k as any]
中的any
类型所以我尝试了:
type EnumIndex = number | string;
ProyectType[k as EnumIndex]
但我得到:Element implicitly has an 'any' type because index expression is not of type 'number'.ts(7015)
我认为索引器可以是数字或字符串类型,因为Object.Keys
是一个包含 8 个元素的数组:["0","1","2","3","time","hits","value","results"]
,但两者都不起作用。
如果枚举类型已知,在这种情况下如何删除any
类型?
【问题讨论】:
您不能改用这些解决方案吗? ***.com/questions/43100718/… 【参考方案1】:这里的主要问题是type signature for Object.keys(obj)
的返回类型为string[]
而不是Array<keyof typeof obj>
。
这是有意的:TypeScript 中的对象类型是open 而不是close;他们必须有一些已知的属性,但他们可能有额外的属性。有关详细信息,请参阅 Q/A 对 "Why doesn't Object.keys return a keyof type in TypeScript?"。
所以编译器看到你试图用任意的string
索引到ProyectType
,并且对此不满意。如果您不关心额外密钥的可能性,或者如果您碰巧知道密钥是什么,您可以使用type assertion 告诉编译器它无法弄清楚什么。
例如,您可以这样做:
type ProyectTypeKeys = Array<keyof typeof ProyectType | number>;
// type ProyectTypeKeys = (number | "time" | "hits" | "value" | "results")[]
const values = (Object.keys(ProyectType) as ProyectTypeKeys).
filter((k): k is keyof typeof ProyectType =>
typeof ProyectType[k] === "number");
// const values: ("time" | "hits" | "value" | "results")[]
const keys = values.map(k => ProyectType[k]);
// const keys: ProyectType[]
在这里,我将 ProyectTypeKeys
定义为数组类型,其元素要么是枚举对象的已知字符串键,要么是 number
... 这是您希望看到的,也是您这样做的原因 @987654335 @步骤。
同样,我已将 filter()
回调注释为 user-defined type guard function,以便编译器使用 a call signature for filter()
将 filter()
的输出类型从完整数组类型 ProyectTypeKeys
缩小到仅出来:keyof typeof ProyectType
,又名,"time" | "hits" | "value" | "results"
。
在此之后,keys
的推断类型是 ProyectType[]
,根据需要。
Playground link to code
【讨论】:
【参考方案2】:是的,这真的很奇怪,它似乎只发生在某些功能中。
看看这个方法:
const keys = [];
const values = [];
for(const index in ProyectType)
//typescript infers string to index const but here there is no error
typeof ProyectType[index] === "number" ? values.push(index) : keys.push(index)
一种可能的解决方案是使用您编写代码的方式而不会出错。使用未知类型 + 编号。
const values = Object.keys(ProyectType).filter(k => typeof ProyectType[k as unknown as number] === "number"); // ["time", "hits", "value", "results"]
【讨论】:
我尽量避免任何未知,并且接受的答案方法似乎更正确((k): k is keyof typeof ProyectType
)。那是我一直在寻找的,但是您的也是有用的 sn-p,谢谢您的回答。【参考方案3】:
使用类型断言
这是一种优雅的替代方式;)考虑到enum
s 只能包含string
和number
类型,并且您的操作是有意的,您可以使用类型断言 获取您的值和键。类型转换(或断言)是一种告诉编译器你知道你在做什么的方式。你可以在this link找到更多信息。
在你的情况下,函数应该是这样的:
function projectTypeValues()
const values = Object.values(ProyectType)
.filter((val) => isNaN(val as number));
const keys = Object.keys(ProyectType)
.filter(key => !isNaN(key as unknown as number))
.map(key => +key);
我使用了key as unknown as number
,因为在这种情况下我们的密钥是string
。然后我映射它们以将字符串转换为您所写的数字。
【讨论】:
我尽量避免使用any
和unknow
,但这是一个有用的sn-p,感谢您的回答以上是关于避免任何类型在打字稿中获取枚举值的主要内容,如果未能解决你的问题,请参考以下文章