Search code examples
javascripttypescriptcompiler-errorslogic

Ensure all values of enum type are covered within function body


I have a type that is:

export enum ApiFunctions {
  "setHidden" = "HIDE",
  "setReadOnly" = "SET_READ_ONLY",
  "setDescription" = "DESCRIPTION"
}
export type ValueOfApiFunction = `${ApiFunctions}`

and logic that is listening for an event on the window like so

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
                            }, "*")
                        });
                    }
                })

I have explained what I want to achieve in a comment in the code block above but basically I want to ensure all values of my type are covered within the forEach logic, if not, compilation error.

Many thanks


Solution

  • TypeScript does not have a native capability to enforce the use of certain logic within a codebase. It is mostly concerned that objects are not manipulated incorrectly, rather than inspecting what the correct code is doing. Nevertheless, there is a workaround that would enable you to make sure that logic is executed for every possibility of an enum:

    You can create a JSON object that holds all enum values as its keys, and each key has a value of a function, meaning that there is a piece of logic executed for every enum as follows:

    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"),
    }
    

    (The Field type could be something different as it was not provided in the example)

    All you need to do now is to call this within your forEach as follows:

    fieldToAction[change.action](field);
    

    Playground link that illustrates this behaviour can be found here.