Recently I was doing redesign of my blog. As you may know, I'm using Gatsby.js. All in all, it is a very good static sitegenerator but I had one problem with it. Or to be more precise the issue waswith Gatsby and the TypeScript.
Problem
I try to help myself when writing frontend code so I decided that I will try toautomatically generate TypeScript interfaces from GraphQL schema that Gatsby.jsis using. Everything was fine until I found out that by design many fields areundefined. Take for example siteMetadata
object:
{
siteMetadata: {
siteName: 'Krzysztof Żuraw',
author: 'Krzysztof Żuraw',
description: 'Krzysztof Żuraw personal site & blog',
siteUrl: 'https://krzysztofzuraw.com',
social: {
linkedin: 'https://pl.linkedin.com/in/krzysztofzuraw',
github: 'https://github.com/krzysztofzuraw',
email: 'mailto:blog@kzuraw.com',
pinboard: 'https://pinboard.in/u:KZuraw',
newsletter: 'https://buttondown.email/krzysztof_zuraw',
},
}
}
You can see this file here.
I tried to generate TypeScript types for this structure using GraphQL Code Generator to get:
export type SiteSiteMetadata = {
__typename?: 'SiteSiteMetadata';
siteName?: Maybe<Scalars['String']>;
author?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
siteUrl?: Maybe<Scalars['String']>;
social?: Maybe<SiteSiteMetadataSocial>;
};
What? All of them are undefined
or null
? No way - I know they will be defined in the timewhen I generate a static site. I asked around and Hasparus give me a hint - youcan customize your GraphQL schema 🎉.
To do that I had to use createSchemaCustomization(you have to place it inside gatsby-node.js
):
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
type MarkdownRemark implements Node {
frontmatter: Frontmatter!
}
type Frontmatter {
tags: [String!]!
title: String!
slug: String!
date(
difference: String
formatString: String
fromNow: Boolean
locale: String
): Date!
}
type Site implements Node {
siteMetadata: SiteSiteMetadata!
}
type SiteSiteMetadata {
siteName: String!
author: String!
description: String!
siteUrl: String!
social: SiteSiteMetadataSocial!
}
type SiteSiteMetadataSocial {
linkedin: String!
github: String!
email: String!
pinboard: String!
newsletter: String!
}
`;
createTypes(typeDefs);
};
What is happening here? I added my own GraphQL types where all the fields are not nullable.Thanks to that it generated types look like follows:
export type SiteSiteMetadata = {
__typename?: 'SiteSiteMetadata';
siteName: Scalars['String'];
author: Scalars['String'];
description: Scalars['String'];
siteUrl: Scalars['String'];
social: SiteSiteMetadataSocial;
};
One drawback of it - right now it is on me as a developer, to make sure that all thedata from e.g frontmatter
will be there.
Summary
I wanted to fix autogenerated GraphQL types in Gatsby. Thanks to Hasparus suggestion I’veused createSchemaCustomization to overrideguested Gatsby types.
Thank you Hasparus once again 🙇🏻♂️.
Top comments (1)
Krzysztof Thanks for this article. I have one doubt here, say if you have Post and post has array of Tag, using
createSchemaCustomization
how would you solve this i.e in Post instead of string tag, populating post with all tag data.I tried couple of things but still no luck.
Thanks buddy.