We will use GraphQL code generator to generate types for the queries used in the app. You'll see how we will get the benefit of TypeScript while not having to do much typing at all ourselves.
This way we know what data is being passed around our application through TypeScript.
Resources:
Checkpoint: Generate types with graphql codegen
Instructor: [0:00] GraphQL Code Generator is a CLI tool that allows you to generate code from your GraphQL schema. For example, you could use it to generate the TypeScript types based on your schema for the exact queries that you use in your app.
[0:13] Let's go to the API documentation, and under Installation Instructions, let's copy the installation command and paste it into our terminal. Next, let's head over to Plugins > Utilities, and Introspection. This plugin will generate the GraphQL introspection file based on your GraphQL schema. Let's copy the installation command and install the library.
[0:35] Now, in our root directory, let's create a new file called codegen.schema.yml. This will be our configuration file for generating the GraphQL schema. We'll need to add the schema. This will be the URL we fetch from, in our case, localhost:3000/graphql. Let's set ovewrite to true. This will overwrite the schema if you've already created one previously.
[0:58] Let's do generate and the pass for our schema. Let's do source GraphQL and GraphQLschema.JSON. This will take a list of plugins. In our case, we just want to use the introspection plugin. Let's open the package JSON. In the script section, let's add another script, and let's call it generate GraphQL schema.
[1:21] This will do yarn GraphQL Codegen. We'll need to pass in the config file that we just created. This will be codegenschema.yaml. When we open the terminal, we can do yarn generate GraphQL schema.
[1:35] This will generate our GraphQL schema in our source GraphQL, GraphQl schema directory. We'll need to use this GraphQL schema in order to generate our types. This is something you should check into source control and manually update when the API changes.
[1:49] Next, let's scroll up to Typescript and Typescript operations. This plugin generates Typescript types based on your GraphQL schema and the GraphQL operations or fragments used in your codebase. Let's copy this installation command and install the library.
[2:05] As the documentation says, we'll also need the Typescript plugin. Let's head over to Typescript and also install GraphQL Codegen Typescript. Let's now add another file to our root directory and we'll call it codegentypes.yaml.
[2:20] For the schema, let's pass in the schema we just generated. This will be in source GraphQL and GraphQLschema.JSON. Let's set overwrite to true to overwrite any previous versions.
[2:32] For the documents, we want to pass in the path for which files the GraphQL Code generator is going to generate types for. In our case, our GraphQL queries are inside our components, so in our home component and in our story details Moodle.
[2:47] In our config file, let's pass all files in the source directory, which aren't the Typescript definition files, but end with either TS or TSX. Let's do generates. Here we want to create a file in source, GraphQL.
[3:01] I usually used the double underscore generated folder, because this file shouldn't be checked into Git and this just makes it explicit. Let's call it operationtypes.ts. For the plugins, we're going to use the Typescript plugin and a Typescript operations plugin.
[3:18] Let's open the package JSON again and add another script for generating the GraphQL types. This will take the codegentypes.yaml. When we open our terminal and run yarn GraphQL generate types, this will generate a operation types file in our source, GraphQL generated folder.
[3:39] If we look into this file, we can see that it's generated types for all the mutations our API provides, all the queries, but also the particular queries that we have used in our app. If you're using ESLint, you'll probably see some linting errors in this file.
[3:54] The way I get around this, in the script section, let's generate another script and let's call it lint fix. This will do yarn lint--fix, which also fixes all the auto-fixable problems. Here after we generate the types, let's add the word a stand and yarn lint fix.
[4:14] Now we open our terminal and run generate types again. We can see that this generates the types and then also lints our code base. When we go to the operation types, they are now much easier to read. This operation types file shouldn't be checked in to Git, but should be generated post-install.
[4:33] Let's add a Git keep file into our generated folder. This ensures that this folder gets checked into Git, even though it will have nothing in it. Now let's open the Git ignore file. Let's ignore the generated files. We'll want to ignore the whole generated folder, but we don't want to ignore the Git keep file.
[4:53] To make sure that these operation types are always generated, the best thing to do is open package JSON and add a post-install script, which will run yarn generate GraphQL types.
[5:04] This ensures that whether you, any of your colleagues, or the CI runs yarn install, the types will be generated as a post install step. Let's open the home screen and see how we can use the types to type our query. GraphQL Codegen uses the name of the query to generate the types.
[5:23] The name of this query is all stories. If we go to operation types, we can see that it has auto-generated all stories query variables and all stories query.
[5:33] In our home screen, let's import all stories query and all stories query variables. Let's scroll down to our useQuery hook and let's pass in these types. We'll pass in all stories query, all stories query variables.
[5:49] When we hover over our data, we can see that Typescript knows what type the data is going to be in. Furthermore, it's already exposed in oversight on our part. Namely, that data.stories is not guaranteed to exist even if the API does an error. Let's add a question mark here.
[6:07] This will return undefined if data is undefined or null. Let's open our story details Moodle, and do the same with the story by ID query. If we open our operation types, we can see that we already have a story by ID query and story by ID query variables.
[6:23] In our story details Moodle, let's import story by ID query and story by ID query variables. In our useQuery hook, let's pass them in. Story by ID query and story by ID query variables. Now because we've tied both the query and the variables, even these variables here are type.
[6:43] For example, if we didn't pass in an ID, we would immediately get a Typescript error. Similarly, if we try to pass in any additional types that don't exist in the query, we would also get a Typescript error.
[6:54] If we scroll down, we have a similar problem as we did with our home page in that data.story might not exist. Let's add another case here under the error page. If not data.story, then let's return a view that says story not found.
[7:10] Let's say you wanted to update this all stories query from the home page and also return the author. In our current operation types, the all story query only has the ID, title, and summary. To update this in our terminal, we'll run yarn generate GraphQL types.
[7:27] If we open the operation types again, we'll see that we now have an author field here. If we change our mind and remove it, all you need to do is run generate types again, and the field gets removed from the types.