Create an Avatar Component in Gatsby with TypeScript Part 3: Adding Types
Tags: react, gatsby, typescript, graphql
Published: 2020-01-08 00:00:00

---
title: Create an Avatar Component in Gatsby with TypeScript Part 3: Adding Types
published: true
date: 2020-01-08 00:00:00 UTC
tags: react, gatsby, typescript, graphql
canonical_url: https://joelmturner.com/blog/avatar-component-gatsby-3
cover_image: https://joelmturner.com/static/6ff52c584152ea8bd37d3faec098d43b/cefe4/gatsby-avatar-03.webp
series: Create an Avatar Component in Gatsby with TypeScript
---

We left off with our avatar component working using Gatsby Image and still able to receive an image URL. Now, let's look at what it would take to type this component. I like to use `type` instead of `interface` for the props. You can read more about [the difference between type and interface](https://medium.com/@martin_hotell/interface-vs-type-alias-in-typescript-2-7-2a8f1777af4c) if you'd like.

The props type will look something like this:

```typescript
{...}
type AvatarProps = {
  url?: string;
  altText?: string;
  title?: string;
  user?: "monster1" | "monster2";
}

function Avatar(props: AvatarProps) {
{...}
```

The cool part here is that the `user` prop can be typed to match the graphql alias names. This helps anyone consuming this component know the values they can pass.

Let's take a look at typing our data variable. We know the shape of what we expect because of our graphql. We just need to provide the correct typing at the childImageSharp level. Luckily Gatsby Image has a type of `FixedObject` that can help us out here. We pass the type to the static query hook `useStaticQuery<Data>(graphql` to signify that we expect the return to be `Data`.

```typescript
{...}
import Img, { FixedObject } from "gatsby-image"
{...}

type Data = {
  monster1: {
    childImageSharp: {
      fixed: FixedObject;
    };
  };
  monster2: {
    childImageSharp: {
      fixed: FixedObject;
    };
  };
}

function Avatar(props: AvatarProps) {
  const data = useStaticQuery<Data>(graphql`
{...}
```

Let's refactor the redundancy in the `Data` type. 

```typescript
type ChildImage = {
  childImageSharp: {
    fixed: FixedObject;
  };
}

type Data = {
  monster1: ChildImage;
  monster2: ChildImage;
}
```

Cool, now we should have something like this:

```typescript
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img, { FixedObject } from "gatsby-image"

type AvatarProps = {
  url?: string;
  altText?: string;
  title?: string;
  user?: "monster1" | "monster2";
}

type ChildImage = {
  childImageSharp: {
    fixed: FixedObject;
  };
}

type Data = {
  monster1: ChildImage;
  monster2: ChildImage;
}

function Avatar(props: AvatarProps) {
  const data = useStaticQuery<Data>(graphql`
    query {
      monster1: file(relativePath: { eq: "monster-01-headshot.png" }) {
        childImageSharp {
          fixed(width: 75, height: 75) {
            ...GatsbyImageSharpFixed
          }
        }
      }
      monster2: file(relativePath: { eq: "monster-02-headshot.png" }) {
        childImageSharp {
          fixed(width: 75, height: 75) {
            ...GatsbyImageSharpFixed
          }
        }
      }
    }
  `)

  const { url, altText, title, user } = props
  const styles = {
    width: "75px",
    height: "75px",
    borderRadius: "50%",
  }

  if (url) {
    return <img style={styles} src={url} alt={altText} title={title} />
  }

  return <Img style={styles} fixed={user && data[user].childImageSharp.fixed} alt={altText} title={title} />
}

export default Avatar
```

There we go! Now our avatar component is ready for prime time. Please let me know if you have any questions or would like to share other ways to solve the same requirements. Thanks for following along!