Converting a Gatsby Site to Use TypeScript
Tags: gatsby, typescript, graphql, react
Published: 2023-08-13 20:19:30

When I was learning web development I built my portfolio site using the [Gatsby-starter-hello-world](https://github.com/gatsbyjs/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 professionally. 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:

```bash
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:

```bash
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:

```bash
npx tsc --init
```

Alternatively, you can use the tsconfig.json file from the official [Gatsby minimal starter](https://github.com/gatsbyjs/gatsby/blob/master/starters/gatsby-starter-minimal-ts/tsconfig.json) TypeScript repository:

```javascript
// 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:

```javascript
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:

```javascript
// 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:

```graphql
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`:

```javascript
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:

```javascript
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.