我正在处理来自第 3 方的一些数据,我想通过 id 将其转换为 map ,但前提是数据有效。我有一个允许的属性的枚举,但无法弄清楚如何以编译器允许的方式检查数据是否有效。我尝试在枚举上使用带有 in 运算符的 if 语句进行检查:
/** Allowed action values */
enum Actions {
Update = 'Update',
Delete = 'Delete'
}
/** Validated app events */
type AppEvent = {
id: string;
action: Actions;
}
/** 3rd party data I want to validate */
type RawEvent = {
id: string;
// ❗️I want to make sure this string is an allowed enum
action: string
}
type AppEventsById = {
[id: string]: AppEvent
}
const possiblyInvalidEvents: RawEvent[] = [
{
id: 'typescript',
action: 'Update'
},
{
id: 'uh oh',
action: 'oops'
}
]
const eventsById: AppEventsById = {}
possiblyInvalidEvents.forEach(event => {
// ❓Here I'm attempting to check that 3rd party action field is one of the allowed enums
if (event.action in Actions) {
eventsById[event.id] = {
id: event.id,
// 💥Type 'string' is not assignable to type 'Actions'
action: event.action
}
}
})
// => I want eventsById to include the { id: 'typescript' } object, but not { id: 'uh oh' }
尝试分配给 action
会引发此错误:类型“string”无法分配给类型“Actions”。
最佳答案
你想要一个user-defined type guard函数来检查string
是否是有效的Actions
成员。这是一种显式告诉编译器如果结果为 true 则应使用某些 bool 值表达式来缩小值类型的方法。最简单的代码重构如下:
function isValidAction(str: string): str is Actions {
return str in Actions;
}
possiblyInvalidEvents.forEach(event => {
if (isValidAction(event.action)) {
eventsById[event.id] = {
id: event.id,
action: event.action // no error anymore
}
}
})
这个 str in Actions
检查实际上依赖于枚举的键和值相同的事实,但这可能并不总是正确的。我可能会觉得检查枚举的实际值而不是键更舒服,这写起来有点令人讨厌,但至少不太可能突然中断:
function isValidAction(str: string): str is Actions {
return (Object.keys(Actions) as Array<keyof typeof Actions>).
some(k => Actions[k] === str);
}
但这取决于你。好的,希望有帮助;祝你好运!
关于typescript - 使用动态字符串对允许的枚举值进行类型保护?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60012770/