Home

Blog

Type Guards in TypeScript with React

Using types for dynamic code

by Alex Fenwood Hughes

September 07, 2019

TypeScript is a powerful language for insuring type safety in React applications. There are often cases where it is useful to check the type of a prop. You can check to confirm that a prop is the primitive type that you expect (e.g. string, number) using the typeof operator. If you are unfamiliar with typeof, check out this Mozilla article before continuing on.

In this article, we will look at how to check for more complex types that you can create in TypeScript. For our example, we will reference a MediaSlider React component that can render either an array of photo slides or video slides. Because the photos and videos will be rendered differently, in this example it will be useful to use a type-guard to determine whether the slides are photos or videos.

This will be the shape of our Photo and Video objects:

type Photo = {
    caption: string;
    url: string;
    altText: string;
};

type Video = {
    url: string;
};

Our MediaSlider component will take an array of slides as a prop. Here is how it would look as a component being used in a React application.

const PhotoSlides: Array<Photo> = [
    {
        caption: "Luke Skywalker",
        url: "https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwii-rq-rsHkAhUhc98KHd7RBgMQjRx6BAgBEAQ&url=https%3A%2F%2Fwww.starwars.com%2Fdatabank%2Fluke-skywalker&psig=AOvVaw0P_5XRq_zyK0uxkEz6wE9k&ust=1568036817844184",
        altText: "Luke Skywalker looking forward"
    },
    {
        caption: "Princess Leia",
        url: "https://www.google.com/url?sa=i&source=images&cd=&ved=2ahUKEwinx6nXrsHkAhVjk-AKHVYtDn8QjRx6BAgBEAQ&url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FPrincess_Leia&psig=AOvVaw2MeNl16x5ejFd4YfpjM1Lc&ust=1568036871194707",
        altText: "Princess Leia with a blaster"
    },
];

const VideoSlides: Array<Video> = [
    {
        url: "https://www.youtube.com/watch?v=g6PDcBhODqo&t=204s",
    },
    {
        url: "https://www.youtube.com/watch?v=hh-zGP-LcQQ",
    },
];

export const App: React.FC = () => (
    <>
        <MediaSlider slides={PhotoSlides} />
        <MediaSlider slides={VideoSlides} />
    </>
);

We want the MediaSlider to handle Photo slides differently from Video slides. Type guards are exactly what we need. Let's create a function using the TypeScript is keyword to check the slide type.

const isPhotoArray = (slides: any): slides is Photo[] => {
    return typeof slides?.[0]?.caption === "string";
};

How is this function working? isPhotoArray takes in an array of any which we will use exclusively for arrays of Photo or Video. Our return type of slides is Photo[] tells TypeScript that the boolean value that we return from this function will determine whether the argument provided is an array of Photo.

We know that the Photo type has a caption while Video does not, so we can use this function to determine whether the type of array passed to MediaSlider is a Photo array or a Video array. This is a pretty cool trick!

What would this look like within the MediaSlider component?

type Props = {
    slides: Photo[] | Video[];
};
export const MediaSlider: React.FC = ({ slides }) => {
    if (!slides) {
        return null;
    }
    if (isPhotoArray(slides)) {
        return (
            /* photo array stuff here */
        )
    }
    return /* video array stuff here */
}

Hope this is helpful to anyone who gets this far!