<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Wildan Zulfikar</title>
    <description>The latest articles on Forem by Wildan Zulfikar (@wzulfikar).</description>
    <link>https://forem.com/wzulfikar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53004%2F23b8ad40-d94e-40e4-bc93-5891825652fd.jpeg</url>
      <title>Forem: Wildan Zulfikar</title>
      <link>https://forem.com/wzulfikar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/wzulfikar"/>
    <language>en</language>
    <item>
      <title>End-to-end Typing for Next.js API</title>
      <dc:creator>Wildan Zulfikar</dc:creator>
      <pubDate>Sat, 20 Aug 2022 23:41:00 +0000</pubDate>
      <link>https://forem.com/wzulfikar/end-to-end-typing-for-nextjs-api-50kn</link>
      <guid>https://forem.com/wzulfikar/end-to-end-typing-for-nextjs-api-50kn</guid>
      <description>&lt;p&gt;One thing I realized after writing TypeScript (TS) for some while is "we write TS so we can keep writing JS". I used to sprinkle type annotations for the sake of typings but that's not how it works. What I should do is, write TS in one place, and put a structure so I can infer the type from where I need it without having to manage more types.&lt;/p&gt;

&lt;p&gt;To see the difference, here's how I would write an API handler before and after applying the new structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qxzkrs7mmur8yjuw5h8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qxzkrs7mmur8yjuw5h8.png" alt="greeting.old.ts vs greeting.ts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post is my attempt to extract what I wish I knew when I started. The TS knowledge is applicable anywhere you use TS, but I'll use Next.js to present the idea.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before going further, step 1 to 2 are pretty basic if you're familiar with TS – so feel free to skim. The typing progress starts from step 3.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Setting up the stage
&lt;/h2&gt;

&lt;p&gt;Let's set up the stage by creating a Next.js repo that uses TS out of the box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest &lt;span class="nt"&gt;--ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once done, you'll have these files:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9wb6e39dp6onbacz6qk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9wb6e39dp6onbacz6qk.png" alt="List of Next.js files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At the time of this writing, I'm using Next.js 12&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To ensure Next.js is ready, run &lt;code&gt;yarn dev&lt;/code&gt; and &lt;code&gt;curl&lt;/code&gt; the &lt;code&gt;api/hello&lt;/code&gt; endpoint to see its response. When you stop your &lt;code&gt;yarn dev&lt;/code&gt; terminal session (use &lt;code&gt;ctrl+c&lt;/code&gt;), the &lt;code&gt;curl&lt;/code&gt; should no longer work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnusb6o94ii2dabz0ab0k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnusb6o94ii2dabz0ab0k.gif" alt="GIF for yarn dev"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, let's install more packages (we'll explains their uses as we go):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add zod http-status-code @sentry/nextjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Use Absolute Import
&lt;/h2&gt;

&lt;p&gt;Open the &lt;code&gt;pages/api/hello.ts&lt;/code&gt; file in vscode and add this import statement, you'll see the red squiggle:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18rgwmsnf5ph5efry7mx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18rgwmsnf5ph5efry7mx.png" alt="Red squiggle in import "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TS tried to find &lt;code&gt;@backend&lt;/code&gt; package in node_modules but it couldn't find, hence the error. We don't need to install the package because it'll be a folder that we refer to using absolute import. Let's set it up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your &lt;code&gt;tsconfig.json&lt;/code&gt; and add these lines below &lt;code&gt;compilerOptions&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;baseUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;paths&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@api/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pages/api/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;backend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@backend/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;backend/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9vq7mxsd8lagq3mda1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9vq7mxsd8lagq3mda1k.png" alt="Content of tsconfig.json"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Next, let's create a new folder &lt;code&gt;backend&lt;/code&gt; and create &lt;code&gt;index.ts&lt;/code&gt; file in it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbjnbmd56y9fucbpao0ag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbjnbmd56y9fucbpao0ag.png" alt="Content of backend/index.ts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;pages/api/hello.ts&lt;/code&gt; file again and the red squiggle is now gone!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funkqlke7odjkckzj0yon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funkqlke7odjkckzj0yon.png" alt="Red squiggle removed from api/hello.ts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on the newly added &lt;code&gt;baseUrl&lt;/code&gt; and &lt;code&gt;paths&lt;/code&gt; in our &lt;code&gt;tsconfig.json&lt;/code&gt;, TS knows which folder to find when it sees &lt;code&gt;"@backend"&lt;/code&gt;. We call this set up "absolute import". Using absolute import is easier compared to relative import where we have to use &lt;code&gt;../&lt;/code&gt; or &lt;code&gt;../../&lt;/code&gt; to access files in parent folders.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1) Since we've added &lt;code&gt;"baseUrl":"."&lt;/code&gt; and the &lt;code&gt;backend&lt;/code&gt; folder is actually in the root directory of the project, we can do &lt;code&gt;import {} "backend"&lt;/code&gt; and it'll still work. We'll stick with the &lt;code&gt;"@backend"&lt;/code&gt; because (in my opinion) the &lt;code&gt;@&lt;/code&gt; prefix is helpful to hint that it's an absolute import.&lt;/p&gt;

&lt;p&gt;2) We also added absolute path for &lt;code&gt;"@api/*"&lt;/code&gt; which we'll get to it later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Add files to backend folder
&lt;/h2&gt;

&lt;p&gt;Open this &lt;a href="https://gist.github.com/wzulfikar/9894181bb3463128bcba2d5cc91ef94b" rel="noopener noreferrer"&gt;Github gist&lt;/a&gt; and copy the content to its corresponding file in your &lt;code&gt;backend&lt;/code&gt; folder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtgrsdnhcbwpyjpnphgd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtgrsdnhcbwpyjpnphgd.png" alt="Github gist for backend content"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your backend folder should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvsahdu9hcracvdy0byv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvsahdu9hcracvdy0byv.png" alt="Content of backend folder after adding gist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once all in place, let's run a type check to ensure there's no error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn tsc &lt;span class="nt"&gt;--noEmit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyly53fl7wahyjcn2vic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyly53fl7wahyjcn2vic.png" alt="Run typescript check"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We use &lt;code&gt;--noEmit&lt;/code&gt; to tell TS to run typechecking without actually compiling the files to JS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Let's see the types!
&lt;/h2&gt;

&lt;p&gt;Open the &lt;code&gt;pages/api/hello.ts&lt;/code&gt; file and notice that Next.js has added a type &lt;code&gt;Data&lt;/code&gt; for the JSON response. If you pass a wrong shape for the parameter, TS will complain:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jtciq3m65fje3fw6gqq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jtciq3m65fje3fw6gqq.png" alt="Type error in hello.ts"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Try save the file while having the red squiggly line and run a type check (&lt;code&gt;yarn tsc --noEmit&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xt7ds66pi2i9a54s5o7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xt7ds66pi2i9a54s5o7.png" alt="tsc with error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You see that the type check didn't pass because there's an error. This is one way of using TS to prevent accidental bug to creep in to production. For example, we can run the type check automatically (eg. using Github Action) for each commit and prevent the commit to get merged to &lt;code&gt;main&lt;/code&gt; if the check is not passing.&lt;/p&gt;

&lt;p&gt;Now we know that Next.js has added the type for the response data. But what if we want to type the request too? Open &lt;a href="https://gist.github.com/wzulfikar/9fbe4ef13429e0f29581e611bdc30251" rel="noopener noreferrer"&gt;this gist&lt;/a&gt; and copy the content to &lt;code&gt;pages/api/greeting.ts&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l36w52wf6tna3mto4ud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l36w52wf6tna3mto4ud.png" alt="pages/api/greeting.ts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how we read above codes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Line 1&lt;/code&gt;: we import the type &lt;code&gt;ApiHandler&lt;/code&gt; and the functions (&lt;code&gt;handle&lt;/code&gt;, &lt;code&gt;z&lt;/code&gt;) from backend folder (see &lt;code&gt;backend/index.ts&lt;/code&gt; file from step 3). The &lt;code&gt;z&lt;/code&gt; actually comes from &lt;code&gt;zod&lt;/code&gt; package but we re-export it thru backend so we don't have to add multiple imports. This is just a convenient approach because for our purpose, &lt;code&gt;z&lt;/code&gt; will almost always get imported when &lt;code&gt;handle&lt;/code&gt; is.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Line 3-7&lt;/code&gt;: define &lt;code&gt;schema&lt;/code&gt; variable that we'll use to validate the request and add the typing to our request object (&lt;code&gt;req&lt;/code&gt;). It tells us which properties (in query or body) are available for this endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Line 9-11&lt;/code&gt;: define &lt;code&gt;response&lt;/code&gt; to type the shape of our response object (&lt;code&gt;res&lt;/code&gt;). In this case, it has single property called &lt;code&gt;greeting&lt;/code&gt; (a string). Unlike &lt;code&gt;schema&lt;/code&gt;, &lt;code&gt;response&lt;/code&gt; is exported because we want to reuse it in our React component later.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Line 13-16&lt;/code&gt;: define &lt;code&gt;handler&lt;/code&gt; function which is the meat of our API code. We use &lt;code&gt;ApiHandler&lt;/code&gt;, a generic we defined in &lt;code&gt;backend/types.ts:25&lt;/code&gt;, to add types to our request and response objects based on the type of &lt;code&gt;schema&lt;/code&gt; and &lt;code&gt;response&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzrj0jdzc8142xmrsp44.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzrj0jdzc8142xmrsp44.gif" alt="type inference"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Line 18&lt;/code&gt;: pass the &lt;code&gt;handler&lt;/code&gt; to our &lt;code&gt;handle&lt;/code&gt; function which will automatically validate the request against the schema. It guarantees that all properties defined in &lt;code&gt;schema&lt;/code&gt;  will be available in &lt;code&gt;handler&lt;/code&gt;. For example, it'll drop the request and return an error response if user doesn't provide &lt;code&gt;name&lt;/code&gt; in query param. This way, our &lt;code&gt;handler&lt;/code&gt; doesn't have to deal with manual validation (eg. checking if &lt;code&gt;name&lt;/code&gt; is not empty).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqlwivmet0vnpljhrzhf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqlwivmet0vnpljhrzhf.gif" alt="curl with query"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;There we go!&lt;/strong&gt; We now have a structure to type our API. I like the way it starts with declarative style (declare the shape of schema and response) and continues with imperative style (the handler). &lt;/p&gt;

&lt;p&gt;When we have multiple files of similar structure, it'll be easy to skim because there's a pattern: shape of schema, shape of response, the handler. The handler is pretty slim too because it doesn't need to care about data validation.&lt;/p&gt;

&lt;p&gt;For the next part, we'll see how we reuse the &lt;code&gt;response&lt;/code&gt; to add typing in our React component. We'll also add a structure to test both the backend and frontend using &lt;code&gt;jest&lt;/code&gt;. Here's a sneak peek:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w11q84m5jxkpf6m4n49.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w11q84m5jxkpf6m4n49.gif" alt="yarn test backend frontend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>react</category>
      <category>structure</category>
    </item>
  </channel>
</rss>
