Skip to main content
DocsHow-To GuidesGenerate types with GraphQL Codegen

Generate types with GraphQL Codegen

Faust.js provides built-in TypeScript support, including types for Templates, Blocks, and more. This guide will show you how to generate fully typed definitions for your custom GraphQL queries and fragments using GraphQL Code Generator.

Tip

If you're looking to generate Apollo-specific fragment matching metadata (i.e. possibleTypes), see the faust generatePossibleTypes command. However, that command does not produce TypeScript definitions for your queries. For typing your queries in Faust, continue reading below.

0. Prerequisites

If you haven't already, follow the Basic Setup steps to get Faust.js configured. Once your project is set up, add @graphql-codegen/cli to your project:

npm install -D typescript @graphql-codegen/cli

1. Add Codegen Configuration

In the root of your project, create a configuration file named codegen.ts

codegen.ts
import { CodegenConfig } from "@graphql-codegen/cli";
 
const config: CodegenConfig = {
	schema: "https://faustexample.wpengine.com/graphql",
	documents: ["src/**/*.{tsx,ts}"],
	generates: {
		"./src/__generated__/": {
			preset: "client",
			plugins: [],
			presetConfig: {
				gqlTagName: "gql",
			},
		},
	},
	ignoreNoDocuments: true,
};
 
export default config;

2. Add Codegen Script

Next, update your package.json to add a script for running the code generator:

package.json
{
	"scripts": {
		"generate:types": "graphql-codegen"
	}
}

Now you can run:

npm run generate:types

This command will scan your src/ folder for any GraphQL queries or fragments, then generate TypeScript types in src/__generated__/graphql.ts.

Important

Be sure to enable WPGraphQL introspection before running the npm run generate command since it is disabled by default.

3. Using Generated Types

A. Typing Templates

After Codegen runs, you'll see auto-generated types in graphql.ts. For example:

src/__generated__/graphql.ts
export type GetPostQueryVariables = Exact<{
	databaseId: Scalars["ID"];
	asPreview?: InputMaybe<Scalars["Boolean"]>;
}>;
 
export type GetPostQuery = {
	// ...
};

You can use these types with the FaustTemplate helper in your WordPress templates:

wp-templates/single.tsx
import { gql } from "../__generated__";
import { GetPostQuery } from "../__generated__/graphql";
import { FaustTemplate } from "@faustwp/core";
 
const Component: FaustTemplate<GetPostQuery> = (props) => {
	// `props.data` and other fields are now typed!
	return <div>{props?.data?.post?.title}</div>;
};
 
export const pageQuery = gql(/* GraphQL */ `
  query GetPost($databaseId: ID!, $asPreview: Boolean) {
    ...
  }
`);

Then you can inspect all the types in the props parameters as you type:

TypeScript auto-complete suggestion in Faust.js, showing the available fields for a GraphQL query's response. The code completion suggests properties like __SEED_NODE__, data, and loading, indicating TypeScript's type inference for the props object.

All the data from the query results will be properly typed based on the introspected schema:

TypeScript type definition for an author field in a Faust.js GraphQL query. The type structure shows NodeWithAuthorToUserConnectionEdge, defining the User type with an optional name property, demonstrating TypeScript's type safety for GraphQL responses.

B. Typing Block Components

If you create blocks with @faustwp/blocks, you can use the WordPressBlock type to add strong typing to those components:

wp-blocks/CoreParagraph.tsx
import { gql } from "../__generated__";
import { WordPressBlock } from "@faustwp/blocks";
import { CoreParagraphFragmentFragment } from "../__generated__/graphql";
 
const CoreParagraph: WordPressBlock<CoreParagraphFragmentFragment> = (
	props,
) => {
	return <p>{props.attributes?.content}</p>;
};
 
export const fragments = {
	entry: gql(`
    fragment CoreParagraphFragment on CoreParagraph {
      attributes {
        content
      }
    }
  `),
	key: "CoreParagraphFragment",
};

By passing in CoreParagraphFragmentFragment to WordPressBlock, TypeScript enforces that props only contains fields you've declared in the GraphQL fragment.

Further Reading