avatr of Ibrahim

Published 3rd Aug 2023

Converting a Gatsby Site to Use TypeScript

3 min read

When I was learning web development I built this site with Gatsby using the Gatsby-starter-hello-world template without using Typescript. Typescript was on my things-to-learn bucket list but never got to it until I started working professionaly. After learning Typescript I cannot imagine building anything without it!

In case you don't know the benefits of Typescript, here's a list to why you should start using it:

  • Early Error Detection: TypeScript's static type checking can catch errors early in the development process, reducing the likelihood of runtime issues.
  • Improved Code Quality: With TypeScript, you get better tooling support, allowing for more reliable refactoring and improved code readability.
  • Enhanced Code Navigation: TypeScript's type annotations provide rich information for code navigation and auto-completion in your IDE.
  • Type-Safe GraphQL Queries: If you use GraphQL for fetching data TypeScript allows you to have type-safety for your GraphQL results, reducing the chance of data-related bugs.
  • Better Collaboration: The added type information makes it easier for team members to understand code written by others.

Here's how to migrate a Gatsby site to Typescript.

Step 1: Clean Up

Before integrating typescript, clean your cache:

gatsby clean

Step 2: Convert Files to TypeScript

The first step in the conversion process is to rename your existing .js and .jsx files to .ts and .tsx, respectively. This tells Gatsby that these files are now written in TypeScript.

Step 3: Install Dependencies

Next, we need to install the required TypeScript and type declaration dependencies. In your project directory, run the following command:

npm install --save-dev @types/node @types/react @types/react-dom typescript

Step 4: Create tsconfig.json

A tsconfig.json file is essential for configuring TypeScript in your project. You can generate one using the TypeScript compiler by running:

npx tsc --init

Alternatively, you can use the tsconfig.json file from the official Gatsby minimal starter TypeScript repository:

// tsconfig.json
// Replace your existing tsconfig.json with the one from the repository

You might find yourself editing some of the tsconfig.json properties to reflect the setup/configs of your project.

Step 5: Rename Gatsby Files

Rename these Gatsby filenames to match the new file extensions. Rename the following files accordingly:

  • gatsby-node.js to gatsby-node.ts
  • gatsby-config.js to gatsby-config.ts
  • gatsby-browser.js to gatsby-browser.tsx
  • gatsby-ssr.js to gatsby-ssr.tsx

Step 6: Replace require.resolve with path.resolve

TypeScript does not support require.resolve, so you'll need to replace these instances with path.resolve calls. Here's an example of how to do this in a gatsby-node.ts file:

import path from "path";

const template = path.resolve(`./src/templates/template.tsx`);

Note the file extension in ./src/templates/template.tsx. You will need to change all .js and .jsx extensions in gatsby.node to .tsx or gatsby develop will throw an error.

Step 7: Handling Hot-reloading

Be aware that when changing the siteMetadata in gatsby-config, hot-reloading won't occur during development. A restart of the development server will be necessary in this case.

Step 8: GraphQL Typegen

To have type-safety for your GraphQL results and autocompletion in your IDE, you can use Gatsby's GraphQL Typegen feature. Set the graphqlTypegen option to true in your gatsby-config.ts file:

// gatsby-config.ts
module.exports = {
  graphqlTypegen: true,
};

Make sure your tsconfig.json includes "include": ["./src/**/*"].

Step 9: Working with GraphQL Queries

When using TypeScript with GraphQL queries, ensure that your query has a name:

export const query = graphql`
  query blogsPage {
    # ... your query here ...
  }
`;

In order to get the graphQL query types you will need to restart your development server so Gatsby picks it up.

Now, you can access the query type using the global namespace Queries:

import { PageProps } from "gatsby"

const Blogs = ({ data }: PageProps<Queries.blogsPageQuery>) => {
  // ...
};

Step 10: Dealing with Read-only Types

When using data from GraphQL queries in your state, you might encounter read-only types that don't allow mutability. To address this, explicitly cast the data to the desired type, like this:

import { PageProps } from "gatsby"

const Blogs = ({ data }: PageProps<Queries.blogsPageQuery>) => {

  const [blogs, setBlogs] = useState<Queries.ContentfulBlog[]>(data.allContentfulBlog.nodes as Queries.ContentfulBlog[]);
  .
  .
  .
  setBlogs(data.allContentfulBlog.nodes as Queries.ContentfulBlog[]);
  .
  .
  .

}

By doing this, TypeScript won't complain about mutability issues.

TypeScript may complain about potentially undefined values in your code. Use optional chaining .? to handle such cases gracefully. If you are converting a larger, existing codebase to TypeScript, consider doing it in manageable steps. Focus on critical components and gradually migrate other parts of the project.

And this is how to convert a Gatsby site to using Typescript.

Thank you for reading. Let's connect!

Feel free to connect on Twitter or LinkedIn

© Ibrahim Al-Quraishi 2024