TypeScript's enum + JavaScript's "in" = πŸ‘

andrewmcoupe

Andy Coupe

Posted on November 8, 2020

TypeScript's enum + JavaScript's "in" = πŸ‘

At cinch, I work on the inventory team and we manage all of the vehicle inventory, tracking the status, location and all kinds of other data for thousands of cars. We have an event driven architecture which means parts of our code respond to certain events which we subscribe to. We have a state machine/model which contains a LOT of logic to determine moving cars from one status to another. I came up with the following pattern when I noticed some hefty if conditions in the codebase.

In this example I'm going to use robots as the subject as I write code to do with vehicles every day! πŸš—

Let's imagine we want a function which disposes of a robot but we can only dispose of the robot if it's status is faulty or damaged. Below we setup our enum RobotStatus to list our possible robot status and a Robot interface to build the shape of our robot.

enum RobotStatus {
    ready,
    damaged,
    faulty
}

interface Robot {
    name: string
    status: RobotStatus
}

function disposeRobot(robot: Robot): void {
    if (robot.status === RobotStatus.damaged || 
        robot.status === RobotStatus.faulty
    ) {
        console.log('Disposing of robot...')
    }

    console.log('Robot in incorrect state to dispose...')
}
Enter fullscreen mode Exit fullscreen mode

This is fine for now. But imagine if we had to start adding more checks for other status. Let's add some more for discontinued, dead, old, rusty, and dangerous.

enum RobotStatus {
    ready,
    damaged,
    faulty,
    discontinued,
    dead,
    old,
    rusty,
    dangerous
}

interface Robot {
    name: string
    status: RobotStatus
}

function disposeRobot(robot: Robot): void {
    if (robot.status === RobotStatus.damaged || 
        robot.status === RobotStatus.faulty ||
        robot.status === RobotStatus.discontinued ||
        robot.status === RobotStatus.dead ||
        robot.status === RobotStatus.old ||
        robot.status === RobotStatus.rusty ||
        robot.status === RobotStatus.dangerous ||
    ) {
        console.log('Disposing of robot...')
    }

    console.log('Robot in incorrect state to dispose...')
}
Enter fullscreen mode Exit fullscreen mode

Now that if block is getting chunky and it stinks πŸ‘ƒ.
Let's create an enum containing our allowed disposable statuses.

enum DisposableStatus {
    damaged,
    faulty,
    discontinued,
    dead,
    old,
    rusty,
    dangerous
}
Enter fullscreen mode Exit fullscreen mode

JavaScript has an in operator which will return true if the specified property exists in the specified object.

prop in object
Enter fullscreen mode Exit fullscreen mode

This can clean up our if block from above. Let's use it...

function disposeRobot(robot: Robot): void {
    if (robot.status in DisposableStatus) {
        console.log('Disposing of robot...')
    }

    console.log('Robot in incorrect state to dispose...')
}
Enter fullscreen mode Exit fullscreen mode

TypeScript will compile the enum into a regular JavaScript object and these properties will exist at runtime πŸ‘.
This is much more readable and easier to digest for your future self and other developers.

πŸ’– πŸ’ͺ πŸ™… 🚩
andrewmcoupe
Andy Coupe

Posted on November 8, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related