Using ENUMs to Make JSX Select Inputs More Type-safe

Jay @ Designly - Jul 20 - - Dev Community

TypeScript has changed my life as a free-lance React/Next.js developer. Since I've made it an essential part of my development tooling, I continue to learn new ways to make my apps more type-safe and provide better hinting.

One tip that I've been using for quite some time now is using ENUMs to create type-safe lists of key/value pairs. A great use-case example would be a simple HTML select element. We can use the ENUM to derive our type as well as generate our select options.

Example:

'use client';

import React, { useState } from 'react';

enum E_PreciousStones {
    diamond = 'Diamond',
    ruby = 'Ruby',
    sapphire = 'Sapphire',
    emerald = 'Emerald',
    amethyst = 'Amethyst',
    opal = 'Opal',
    topaz = 'Topaz',
    aquamarine = 'Aquamarine',
    garnet = 'Garnet',
    peridot = 'Peridot',
    turquoise = 'Turquoise',
    tanzanite = 'Tanzanite',
    citrine = 'Citrine',
    alexandrite = 'Alexandrite',
    spinel = 'Spinel',
    tourmaline = 'Tourmaline',
}

type T_PreciousStones = keyof typeof E_PreciousStones;

export default function Select() {
    const [selectedStone, setSelectedStone] = useState<T_PreciousStones | undefined>(undefined);

    const stones: T_PreciousStones[] = Object.keys(E_PreciousStones) as T_PreciousStones[];

    return (
        <div className="flex flex-col gap-6">
            <label htmlFor="stone" className="label">
                Select a precious stone:
            </label>
            <select
                id="stone"
                className="select select-bordered"
                value={selectedStone}
                onChange={e => setSelectedStone(e.target.value as T_PreciousStones)}
            >
                <option value="">Select a stone</option>
                {stones.map(stone => (
                    <option key={stone} value={stone}>
                        {E_PreciousStones[stone]}
                    </option>
                ))}
            </select>
            {selectedStone && (
                <div className="alert alert-info">
                    You have selected <strong>{E_PreciousStones[selectedStone]}</strong>.
                </div>
            )}
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

In this example, I've defined an ENUM of precious stones. Each item is a key with the friendly-print label as it's value. We then can derive our type for our selectedStone state by using keyof typeof. Next, we create an array of keys and type-cast it as T_PreciousStones. Lastly, we map the stones array out as our select options.

That's it! The great thing about this is if you want to add or remove any options in the future, you only have to modify your code in one place. Just edit the ENUM and everything else will follow.

Resources


Thank you for taking the time to read my article and I hope you found it useful (or at the very least, mildly entertaining). For more great information about web dev, systems administration and cloud computing, please read the Designly Blog. Also, please leave your comments! I love to hear thoughts from my readers.

If you want to support me, please follow me on Spotify!

Also, be sure to check out my new app called Snoozle! It's an app that generates bedtime stories for kids using AI and it's completely free to use!

Looking for a web developer? I'm available for hire! To inquire, please fill out a contact form.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .