Generating TypeScript Types for GraphQL Schema, Queries and Mutations Using GraphQL Code Generator

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi my name is dmitro and in this video i would like to show how to set up and use graphql code generator it's a tool that helps you generate the typescript types for your graphql schema resolvers queries and mutations in this video i'm going to set up the types for typescript but graphql code generator supports other languages as well for example java and kotlin we can use this tool to generate the types for both the backend and the front end basically we can create types for our queries and mutations manually especially if the app we are working on is very simple and that's what i did in this example app this is a next.js project and it includes both the front end and the back end the back end is powered by the next js api routes feature it's a very simple nodes app basically you can add a node here and it appears in this list that's it now i would like to explain briefly how i set up the back end of this app i will open the editor the graphql api is served from the route api graphql here i'm importing the poly server from apollo server micro package this is the apollo server integration that is most suitable for serving graphql api over the next.js api routes feature at the moment so in this file i instantiate the apollo server providing it with the schema and the context object we can use the context object to pass different functionality to the resolver functions in here i pass the notes object that is used to read and write notes and finally i export the function created by the create handler method and this function is used by next.js to handle a request i imported the schema from this file and what this file does is the following it combines the graphql type definitions and the resolvers object into a single data structure that can be used by the polyserver or if necessary apollo client the actual graphql schema is in this file typeddefs.ts here it is here we have a single query called nodes it returns an array of node objects the node object is described here and we've got one mutation called add node which accepts one variable called input of type at node input here it is then we've got the resolvers file this is where i implemented the query and mutation which i described in the graphql type definitions here they are we've got the nodes query and the add node mutation i use the nodes object from the context to get and add nodes for simplicity this object stores nodes in memory so there is no database the important thing for me to note here is that i have created the types for these resolvers manually i created this type manually to describe the return type of the notes function i have created the type for the add node mutation arguments here's the type of the input object i'm describing the return type of this function as well here and i'm using a generic iresolvers type from apollo server micro package this type describes the structure of the resolver's object in general and it can't make sure that the actual resolvers we need are typed properly we have to do it manually here so what i would like to do now is to set up the graphql code generator to be able to generate the types for the backend automatically so i won't have to spend much time typing the resolvers manually to get started let's open the graphql code generators website here it is i will go to the documentation page and look for the installation instructions here they are and the first thing we need to do is to install the graphql package this package is used by the code generator to process the graphql schema queries and mutations so i will go ahead and edit i have stopped the next dev server okay meanwhile let's continue what else do we need and we need the graphql called gen cli package this is the command line interface for graphql code gen tool so i will copy it and install it as well it's installed as a dev dependency let's go back to the documentation to see other instructions so once we have installed the dependencies we should run this command to configure the code generator for our project so i'll copy it and paste here let's run it i'll extend the terminal window here we go so the first thing this initialization wizard asks us is what type of the application we are building and it looks like it's detected that we are building a react app and this is true but at the moment i would like to generate the types for the backend so i will uncheck this option by pressing the spacebar and check back end hit enter now we should specify the path to our schema and you can use either the file system path or a url i could have used the file system path if i stored the schema as a string in here in a simple graphql file but i'm storing it in a typescript file instead so i'll just go ahead and use the url so our schema is available at http localhost 3000 slash api slash graphql now it tells us to pick the plugins that we would like to use to generate the types graphql code generator can generate types not only for typescript but also other languages such as reason java kotlin etc that's why it has a flexible plugin system that allows us to specify what we would like to generate and we already have two plugins selected for us by default the first one typescript it generates the types for our schema only and the plugin typescript resolvers generates the types for our resolver functions so i will just keep these two plugins and hit enter then we should specify where we would like to store the types file and i would like to store it in the generated folder and in the file called graphql backend because these are the backend types okay introspection file this option tells the generator to generate a file that includes the schema and various data that was used to generate the types i would like to meet this file because i don't have a use for it at the moment this script is going to create a config file for the generator and here we should pick the name for that file let's skip the default it also adds a script to our package.json to run the generator let's call this script called gen okay we've got the code generators config here this file contains the options we have picked in the wizard here is our schema path and the generates option here we use this option to list the files the type files we would like to generate and for each file we pick the plugins that we would like to use to generate the types together with the plugins option we can also use the config option here to set the options for the plugins we will use the config option later if i open the package.json we will see that the wizard added to dev dependencies these are the plugins we have chosen and the script here even though it added the plugins as dev dependencies to this file it did not install these plugins so we have to run the installation script i use yarn so i will run yarn if you use npm you run npm install ok installation completed let's run the code gen script to generate the types and we've got an error failed to load schema from our url and this happened because we didn't run the next server that serves this url here so i'm going to run the server using yarn dev command this starts the next js dev server okay now our api route is up so let's open another terminal window and generate the types here okay the types were generated successfully we've got a new folder generated and a new file i'm going to open it and in here we've got the types based on our schema and the types for the resolvers like it's they start here and there are a lot of helper types and basically what we need is this type okay let's describe the resolvers here using these types so instead of this generic interface i'm going to use the resolvers type from the generated file and from the start we've got a few problems here let's hover over the nodes to check the error types of property id are uncomfortable type number is not assignable to type string and this happens because in the graphql schema the id is defined like this using the id type and graphql code generator uses a string to describe this id type in typescript we can check it like this i'll open the graphql backend yes look for the node type here it is and the id is described using scalar's id here is the scalars type and the id is here so it's a string but in our code we use numbers to describe id here in the notes object we've got id stored as a number so there is a mismatch between this graphql schema and what we expect in the code so let's fix it by changing the id type in graphql schema from id to an integer this will turn into a number in the types so let's regenerate the types ok let's check the resolvers and this error is fixed before continuing i would like to do one thing that i forgot to do with the resolver's type the resolver's type takes as generic type parameter the type of the context object so i will pass the context object type here so typescript knows what the context object is here okay let's continue add note types of property input are incompatible type at node input or null or undefined is not assignable to type add node input undefined is not assignable to type at node input so let's check why this happens i will hover over the input here itself type at node input okay we've got args here what if i so now that we use the resolvers type that was generated specifically for our queries and mutations i can avoid describing the arcs argument manually so i'll remove this type from here and it's described for us by the code generator now and we've got a problem here if i hover over it there is type undefined is not assignable to type add node input so the input type from the graphql schema can be null or undefined but addnode method expects this argument so it doesn't allow for undefined for node input and this is where the mismatch occurs let's fix this in our graphql schema here where we define the add node mutation let's make the add node input variable required by adding the exclamation mark here and regenerate the types okay let's check the resolvers and the error is fixed because input is now required it cannot be undefined anymore okay also we can remove this return types here and here because the code generator described the return types for us so the code generators type definitions make sure that we return the right type here and here also let's remove some things that became unnecessary i'll remove the types i added manually here i'll remove this import and this one so our code became much less variables and this feels good so let's continue i would like to commit the changes okay i've just remembered that i forgot to handle one more issue if we open the schema file here we will get an error that the resolver's object from our resolvers file is not compatible with the resolver's object expected by this function and the same would happen if we tried to pass resolvers directly to the apollo server and this happens because the code generator generates the types for the resolvers that are not compatible with the types expected by this function and the apollo server and the call generators team has fixed this problem so in order to fix it in our project we should add an option to the coach and yaml an option specifically for the typescript resolvers plugin so to add an option for the plugins we use the config object on the same level with the plugins and let's look for the name of this option i will open the website okay let's look for the docs for our plugin so it's plugins typescript and then tag script resolvers and here's this option so i'll copy it paste it here and enable it okay let's regenerate the types ok let's open the schema and we can see that our resolvers type is compatible with the type expected by this function and it will be also compatible with the poly server okay let's add this to the previous commit i will use the amend option here we are okay now let's set up the code generator for the front end but first i would like to talk briefly about how our front end looks like we have a single page the home page here in the index file on this page we run a query to fetch the nodes here they are and we render them in a list i created the types to describe the query manually i created the nodes query type this type describes the result of the nodes query it's the nodes array and the type for the node we pass the nodes query as a generic type parameter to use query so typescript knows how the data property looks like and its nodes query here further we extract the nodes from data and render them so it's quite a lot of manual work also we have the add node form here it's stored in the components folder here in the form we generate the add node mutation function using the use mutation hook and we use this mutation function when the user submits the form to create a node with the user's content i didn't create the types for this query so the type of the add node mutation is quite generic and this means for example that the variables are not typed and we can pass anything we want here so instead of expected input object we could pass something like this for example hello world and this would work without an error on the compiler side of course in the runtime we'll have a big problem so let's get it back to the original variables and let's go ahead and generate the types for our frontend to make our code more type safe first of all i would like to store all the queries and mutations for the front-end in the file in the folder sorry called graphql i'll create this folder in the project's root and inside this folder let's store all the queries and mutations in files with the graphql extension for example for the nodes query we can create a file called nodes dot graphql let's move the notes querying it here i'll copy it from the home page all right now we should configure the code generator such that it looks into this folder finds all the queries and mutations here and generates the types for them so i'll open the call gen yaml and this time i will configure the code generator manually under the generates option let's add another types file that we would like to get generated let's call it this time graphql frontend here we should specify the plugins we would like to use for type generation and the first plugin is typescript to generate the basic types based on our schema then the other two plugins are different the first one is called typescript operations this plugin generates the types for our queries and mutations basically it generates the types for the query and mutation results the query mutation variables etc and we need another plugin that generates custom react hooks for our queries invitations it's called typescript react apollo now we should install these plugins to be able to install them we should figure out their names the names of their packages and there is a table with the names in the documentation here if i click all plugins in the menu there is a table let's look for the type suit operations and here is the corresponding package name i will copy and paste it we should install these plugins as dev dependencies and let's get the second package name and here it is typescript react apollo all right i'll hit enter okay the plugins have been installed now let's finish configuring the code generator we need to tell it where to look for the queries and mutations and for this we can use the documents option here let's specify the path to our graphql files relative to the project root we would like to look for the files in any subfolder any file name with graphql extension okay let's generate the types ok the types have been generated let's check them out here we've got some basic types generated from our graphql schema then we've got the types for our notes query here is the type for the note query result data we've got the notes query document that we can use to run this query and we've got the types generated by typescript react apollo plugin also here are some types and here are our custom react hooks so basically these are just functions that wrap the original apollo use query react hooks with the necessary types set up for us so let's use this hook to fetch notes on the home page instead of this query okay and that's it that's all we need to run the notes query now we don't need the document anymore we don't need these types anymore as well no this import is not needed all as well okay so our homepage code became much more simple now let's generate the types for the add node mutation here in the form at node form i'll copy the mutation here and paste it into a file in the graphql folder let's call this file add note okay here it is let's generate the types all right now i'll go back to the form and we don't need this query document anymore because it's generated for us okay instead of using the use mutation we can use our custom hook use add node mutation okay and now our add node mutation function is properly typed if we for example try to change the variables here to something that is not expected like for example hello world we will get an error so the variables should match the right structure like the input object is the content property okay let's test if our app still works i'll reload the page and try to add something okay looks like it's working so that's it we have used graphql code generator to generate the types for our back end and front end i hope you found this video useful if you liked it please hit the like button thanks for watching this video and see you next time
Info
Channel: Dmytro Danylov
Views: 19,045
Rating: undefined out of 5
Keywords:
Id: DFTVPZvgnaQ
Channel Id: undefined
Length: 24min 23sec (1463 seconds)
Published: Sun Sep 06 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.