确保枚举类型的所有值都包含在函数体中
Ensure all values of enum type are covered within function body
我的类型是:
export enum ApiFunctions {
"setHidden" = "HIDE",
"setReadOnly" = "SET_READ_ONLY",
"setDescription" = "DESCRIPTION"
}
export type ValueOfApiFunction = `${ApiFunctions}`
和逻辑正在监听 window 上的事件,就像这样
window.addEventListener("message", (event) => {
if(event.data.type === "COMPLETE") {
event.data.changes.forEach((change: { fieldId: string, action: ValueOfApiFunction }) => {
const field = api.getFieldById(change.fieldId);
//I want to make sure that within this forEach all values of the type above are covered and if not, through a compilation error
// in this case "DESCRIPTION" isn't included so I would want a compilation error being thrown
if(change.action === "HIDE") {
field?.setVisible(false);
}
else if(change.action === "SET_READ_ONLY") {
field?.setName("This field is now read only")
}
})
resolve();
}
if(event.data.type === "MAKE_REQUEST") {
invoke('makeRequest', { url: event.data.url }).then(result => {
console.log(result);
iframe.contentWindow?.postMessage({
type: "REQUEST_COMPLETE",
response: result
}, "*")
});
}
})
我已经在上面代码块的注释中解释了我想要实现的目标,但基本上我想确保我的类型的所有值都包含在 forEach 逻辑中,否则,编译错误。
非常感谢
您可以像这样利用 'never' 类型:
event.data.changes.forEach((change: { fieldId: string, action: ValueOfApiFunction }) => {
const field = api.getFieldById(change.fieldId);
if(change.action === "HIDE") {
field?.setVisible(false);
}
else if(change.action === "SET_READ_ONLY") {
field?.setName("This field is now read only")
} else {
const _shouldNeverBeReached: never = change.action
}
})
现在,如果您忘记处理 change.action
,类型将不会是 never,因此将无法编译。
更新:更明确的消息:
const exaustiveCheck = <T extends any>(t: T extends never ? never : "One of the cases was not handled") => {
throw new Error("One of the cases was not handled")
}
然后
} else {
exaustiveCheck(change.action)
}
TypeScript 没有在代码库中强制使用特定逻辑的本机功能。它主要关心的是对象没有被错误地操作,而不是检查正确的代码在做什么。不过,有一种解决方法可以让您确保针对枚举的每种可能性执行逻辑:
您可以创建一个 JSON 对象,将所有枚举值作为其键,每个键都有一个函数值,这意味着每个枚举都会执行一段逻辑,如下所示:
const fieldToAction: { [key in ValueOfApiFunction]: (field?: Field) => void } = {
"HIDE": (field?: Field) => field?.setVisible(false),
"SET_READ_ONLY": (field?: Field) => field?.setName("This field is now read only"),
"DESCRIPTION": (field?: Field) => field?.setName("This field is now read only"),
}
(Field
类型可能有所不同,因为示例中未提供)
您现在需要做的就是在您的 forEach
中调用它,如下所示:
fieldToAction[change.action](field);
可以找到说明此行为的游乐场 link here。
我的类型是:
export enum ApiFunctions {
"setHidden" = "HIDE",
"setReadOnly" = "SET_READ_ONLY",
"setDescription" = "DESCRIPTION"
}
export type ValueOfApiFunction = `${ApiFunctions}`
和逻辑正在监听 window 上的事件,就像这样
window.addEventListener("message", (event) => {
if(event.data.type === "COMPLETE") {
event.data.changes.forEach((change: { fieldId: string, action: ValueOfApiFunction }) => {
const field = api.getFieldById(change.fieldId);
//I want to make sure that within this forEach all values of the type above are covered and if not, through a compilation error
// in this case "DESCRIPTION" isn't included so I would want a compilation error being thrown
if(change.action === "HIDE") {
field?.setVisible(false);
}
else if(change.action === "SET_READ_ONLY") {
field?.setName("This field is now read only")
}
})
resolve();
}
if(event.data.type === "MAKE_REQUEST") {
invoke('makeRequest', { url: event.data.url }).then(result => {
console.log(result);
iframe.contentWindow?.postMessage({
type: "REQUEST_COMPLETE",
response: result
}, "*")
});
}
})
我已经在上面代码块的注释中解释了我想要实现的目标,但基本上我想确保我的类型的所有值都包含在 forEach 逻辑中,否则,编译错误。
非常感谢
您可以像这样利用 'never' 类型:
event.data.changes.forEach((change: { fieldId: string, action: ValueOfApiFunction }) => {
const field = api.getFieldById(change.fieldId);
if(change.action === "HIDE") {
field?.setVisible(false);
}
else if(change.action === "SET_READ_ONLY") {
field?.setName("This field is now read only")
} else {
const _shouldNeverBeReached: never = change.action
}
})
现在,如果您忘记处理 change.action
,类型将不会是 never,因此将无法编译。
更新:更明确的消息:
const exaustiveCheck = <T extends any>(t: T extends never ? never : "One of the cases was not handled") => {
throw new Error("One of the cases was not handled")
}
然后
} else {
exaustiveCheck(change.action)
}
TypeScript 没有在代码库中强制使用特定逻辑的本机功能。它主要关心的是对象没有被错误地操作,而不是检查正确的代码在做什么。不过,有一种解决方法可以让您确保针对枚举的每种可能性执行逻辑:
您可以创建一个 JSON 对象,将所有枚举值作为其键,每个键都有一个函数值,这意味着每个枚举都会执行一段逻辑,如下所示:
const fieldToAction: { [key in ValueOfApiFunction]: (field?: Field) => void } = {
"HIDE": (field?: Field) => field?.setVisible(false),
"SET_READ_ONLY": (field?: Field) => field?.setName("This field is now read only"),
"DESCRIPTION": (field?: Field) => field?.setName("This field is now read only"),
}
(Field
类型可能有所不同,因为示例中未提供)
您现在需要做的就是在您的 forEach
中调用它,如下所示:
fieldToAction[change.action](field);
可以找到说明此行为的游乐场 link here。