<?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: Resi Respati</title>
    <description>The latest articles on Forem by Resi Respati (@resir014).</description>
    <link>https://forem.com/resir014</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%2F10817%2F12f1e1ed-f362-4481-b047-be4a19e36be1.png</url>
      <title>Forem: Resi Respati</title>
      <link>https://forem.com/resir014</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/resir014"/>
    <language>en</language>
    <item>
      <title>How I accidentally built a popular tool for Trackmania streamers: the story of TMViz</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Wed, 02 Jun 2021 05:07:19 +0000</pubDate>
      <link>https://forem.com/resir014/how-i-accidentally-built-a-popular-tool-for-trackmania-streamers-the-story-of-tmviz-3684</link>
      <guid>https://forem.com/resir014/how-i-accidentally-built-a-popular-tool-for-trackmania-streamers-the-story-of-tmviz-3684</guid>
      <description>&lt;p&gt;For developers, side projects often feel like a nuisance.&lt;/p&gt;

&lt;p&gt;There seems to be all sorts of ideas floating around the head of a developer, but figuring out which idea to put the work in is a lot harder. And once we find the time to work on a side project, we get sidetracked by any other side project idea we came up with during our morning coffee. But sometimes, the perfect formula for a side project can arrive out of the most mundane situations.&lt;/p&gt;

&lt;p&gt;This is the story of how I accidentally built &lt;a href="https://tmviz.vercel.app/"&gt;TMViz&lt;/a&gt;, a tool that became popular among Trackmania streamers. This post will contain a lot of technical details. But with it, I do hope to tell a story about how I developed and still actively maintain a side project which has a decently-sized userbase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;I've been livestreaming consistently for about 1.5 years under my own &lt;a href="https://www.twitch.tv/resir014"&gt;Twitch channel&lt;/a&gt;. I've been playing a lot of racing games on stream, and as of late I've also been streaming &lt;a href="https://trackmania.com/"&gt;Trackmania&lt;/a&gt; almost consistently. I've played Trackmania casually ever since the Trackmania Nations Forever (TMNF) days in 2009, and with the new release of Trackmania, I want to take it a little more seriously.&lt;/p&gt;

&lt;p&gt;As I started watching some popular Trackmania streamers on Twitch for inspiration, I've noticed that some streamers have a custom overlay which shows the current inputs on their controller/keyboard, one of them being &lt;a href="https://github.com/piatf/padviz"&gt;padviz&lt;/a&gt;. But sadly, back then I could never find out what it's called. And I was the kind of guy who was very shy in chat, because I'm fairly new to the Trackmania community on Twitch.&lt;/p&gt;

&lt;p&gt;I was getting frustrated that I couldn't find it. So I decided to make my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  First iteration
&lt;/h2&gt;

&lt;p&gt;To make the first iteration of my overlay, I used a technology which 1) I'm familiar with; and 2) has been tried and tested by many different apps for ages: the web. In JavaScript, we can use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API"&gt;Gamepad API&lt;/a&gt; to receive inputs from game controllers and react to it. Remember this API - it will become important later.&lt;/p&gt;

&lt;p&gt;I'm a fan of tools that you can set up quickly and then forget about it. In padviz, you need to run a separate app in the background to provide the overlay, and you will have to do that every time you start your stream. By providing an overlay that can be included in OBS as a browser source, it's a truly set-and-forget solution.&lt;/p&gt;

&lt;p&gt;The initial iteration of the overlay was implemented within a week. It was initially created as a module within my &lt;a href="https://github.com/resir014/stream-overlays"&gt;web-based stream overlays set&lt;/a&gt;, and remained that way for the first few weeks/months.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fptfoCbX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etqxbkp28tcsdd2kz8gn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fptfoCbX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etqxbkp28tcsdd2kz8gn.jpg" alt="Screenshot of the first iteration of TMViz."&gt;&lt;/a&gt;&lt;/p&gt;
Screencap of my Twitch stream with the first iteration of TMViz on the right panel.



&lt;h2&gt;
  
  
  Second iteration
&lt;/h2&gt;

&lt;p&gt;I used the first iteration of this tool on my own stream for a couple weeks. At some point during my stream, someone in the chat noticed my tool and that it's different compared to padviz. He asked whether or not it might work for another streamer's controller, since padviz won't work for this one streamer.&lt;/p&gt;

&lt;p&gt;Turns out, since padviz was a desktop app written in Python, support for lesser-known controllers was quite flaky. The streamer in question uses a Stadia controller, which was not supported in padviz. Since the web-based Gamepad API is supported by all major browsers - including the OBS browser source - and supports any controller that you could plug into your computer, I immediately saw the need for a standalone version.&lt;/p&gt;

&lt;p&gt;I recently read &lt;a href="https://twitter.com/Kavaeric/status/1391933781901197319"&gt;a thread by Kavaeric&lt;/a&gt; about the inner workings of UI/UX design, and I realised I already have a mental model of what my target users are going to be like while coming up with the standalone version of TMViz:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they're streamers&lt;/li&gt;
&lt;li&gt;they need a set-and-forget solution that can be easily plugged into any streaming software&lt;/li&gt;
&lt;li&gt;they use a multitude of controllers; even keyboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So immediately, I saw the need for a usable overlay customizer. I put together a customiser UI with &lt;a href="https://nextjs.org/"&gt;NextJS&lt;/a&gt; and &lt;a href="https://chakra-ui.com/"&gt;Chakra UI&lt;/a&gt;, which generates an overlay URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q3GSY_G---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qs3yynqwi368baj1u4yd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q3GSY_G---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qs3yynqwi368baj1u4yd.png" alt="Screenshot of the TMViz customizer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The overlay and game logic itself is easy enough to move, although I redesigned the overlay to match the look of padviz.&lt;/p&gt;

&lt;p&gt;The Overlay URL scheme takes some imspiration from &lt;a href="https://streamkit.discord.com/overlay"&gt;Discord StreamKit&lt;/a&gt;. This way, I could build a system to create a personalised URL based on the settings saved in the customizer. None of the settings is stored in any external server, since everything is saved in the browser's local storage.&lt;/p&gt;

&lt;p&gt;The final step was to tweak the design of the overlay to match the design of padviz's overlay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ggjhCfGQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bcwkmkd8mohqg768d6d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ggjhCfGQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bcwkmkd8mohqg768d6d1.png" alt="Screenshot of the second iteration of TMViz"&gt;&lt;/a&gt;&lt;/p&gt;
Screenshot of the second iteration of TMViz.



&lt;p&gt;Once everything is done, I worked on branding. I named it TMViz, designed a simple logo for it, and made it public.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship, then bite your fingernails
&lt;/h2&gt;

&lt;p&gt;The second iteration of TMViz was piloted by the same streamer who used the Stadia controller. After a day, he came back to me with the word I had initially feared: the overlay is broken.&lt;/p&gt;

&lt;p&gt;The streamer reported the overlay would be frozen after a while. When this happens, he had to hide and then show the overlay to make it work again.&lt;/p&gt;

&lt;p&gt;At this point, I was still using the first iteration of my overlay, so I wasn't able to eat my own dogfood. I decided to transition to TMViz so that I could test this issue, and I ran into the same issue. I also realised that when I opened Task Manager, the OBS process which houses the browser source would have an unusually high memory usage.&lt;/p&gt;

&lt;p&gt;I decided to run a memory profiler while the overlay was being used, and soon enough, I found the problem. It turns out that implementing the UI of the controller overlay in Chakra UI &lt;a href="https://github.com/resir014/TMViz/issues/5#issuecomment-724651067"&gt;caused a memory leak&lt;/a&gt;. This will cause the overlay to freeze when the OBS browser source can't handle the memory. So I immediately rushed to rewrite the overlay part of TMViz to use &lt;a href="https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css"&gt;CSS Modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So that's one issue fixed. I could also relax for a bit, knowing that I could now eat my own dogfood by using TMViz on my own channel.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a side gig becomes a full-time job
&lt;/h2&gt;

&lt;p&gt;Around this time, TMViz was also picked up by a popular streamer. He requested me to tweak the overlay so that he can also visualise his use of the D-pad at the same time. It turns out, some players sometimes switch between analog sticks and D-pads when driving on different surfaces (for example, ice).&lt;/p&gt;

&lt;p&gt;I spent a few hours refactoring the control schemes to support multiple input methods. I also tweaked the design of the customiser to make setting up keybinds easier. I pushed the update and notified the streamer that the feature is implemented.&lt;/p&gt;

&lt;p&gt;The next day, the same streamer reports some issues. After asking some questions, I learned that sometimes he has two controllers plugged in. It turns out, the order of when the controller is plugged in takes precedence in the overlay, and TMViz would. And through computer restarts, the order might change, because of how Windows detects USB devices during bootup. I tweaked the customiser so that users can pick which controller gets picked up by the overlay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jd4Tu-yU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ej17bgre3zpgeszhqja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jd4Tu-yU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ej17bgre3zpgeszhqja.png" alt="Screenshot of the controller selection screen."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I pushed the fix. The next bug report that came from him completely baffled me. The overlay would crash seemingly at random. Throughout my streams and debugging sessions, I could never replicate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KOSEX37b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rlrgswqxrnhgudrzb1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KOSEX37b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rlrgswqxrnhgudrzb1a.png" alt="Screencap of a Discord message of a streamer reporting the random crash bug."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then something dawned on me. At work, we've been using &lt;a href="https://sentry.io/"&gt;Sentry&lt;/a&gt; to log any errors from our users. Sentry collects detailed stack trace from any user whenever an exception is handled within the code, and it has been instrumental to us at work. So I thought it would be a great time to finally give it a spin on my side projects.&lt;/p&gt;

&lt;p&gt;So I implemented Sentry and waited for more errors to come in. Based on the stack trace I collected, it turns out I didn't handle the case where a pressed button doesn't exist in the controller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Id3XZ_2R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tq8g4v08tbf8ecexbcr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Id3XZ_2R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tq8g4v08tbf8ecexbcr9.png" alt="Screenshot of the Sentry log showing the unhandled input."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oops. Rookie mistake, I know.&lt;/p&gt;

&lt;p&gt;Fixing this issue didn't take that long. But of course, debugging and triaging this issue did take a while. I'm glad that tools like Sentry exist. Otherwise the best way of debugging this issue would be individually contacting whoever reported the issue, and asking them about technical stuff they wouldn't understand.&lt;/p&gt;

&lt;p&gt;After this final fix, the overlay has grown more stable over time. It's still being picked up by more streamers as time goes, and it's becoming more commonly shared around amongst the Trackmania communities on Discord.&lt;/p&gt;

&lt;h2&gt;
  
  
  Epilogue, and what's next
&lt;/h2&gt;

&lt;p&gt;So what did I learn while building this? Sometimes, the best ideas for a side project are the ones that are already in front of your eyes. Solve real problems &lt;em&gt;you&lt;/em&gt; are having. As the best React instructor on Earth, &lt;a href="https://twitter.com/kentcdodds"&gt;Kent C. Dodds&lt;/a&gt;, would tell us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[Don't] invent problems just so you can create solutions to them. Nobody will care. Contribute to existing solutions, and solve problems where there are no solutions or the existing solutions are lacking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;— Kent C. Dodds, in &lt;a href="https://kentcdodds.com/blog/intentional-career-building"&gt;"Intentional Career Building"&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would like to personally thank all the streamers who use TMViz. It always brightens my day seeing that tiny little overlay every time I browse through &lt;a href="https://www.twitch.tv/directory/game/TrackMania"&gt;Trackmania streams&lt;/a&gt; on Twitch, regardless of viewer count. I have never felt any more invigorated to continue maintaining any side project than ever before.&lt;/p&gt;

&lt;p&gt;What's next for TMViz, then? The next item on the list would be keyboard support. This would be a technical feat in of itself, but I understand there's a lot of demand for this. So I'll be sure to make that a reality.&lt;/p&gt;

&lt;p&gt;Until then, I can assure everyone that I will keep maintaining TMViz as long as I remain in the Trackmania scene. I am also open for any questions regarding the technical side of the overlay, or just to ask for technical support. You can mention me on &lt;a href="https://twitter.com/resir014"&gt;Twitter&lt;/a&gt;, or you can head over to the &lt;code&gt;#tmviz-support&lt;/code&gt; channel on my &lt;a href="https://discord.gg/ws3P4wf"&gt;Discord server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those interested, the code for TMViz is also open source and is &lt;a href="https://github.com/resir014/TMViz"&gt;available on GitHub&lt;/a&gt;. If you would like to report a bug or help work on pull requests, any contribution is very much appreciated!&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Please, tell us how you solved the problem.</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Thu, 21 Jan 2021 11:47:02 +0000</pubDate>
      <link>https://forem.com/resir014/please-tell-us-how-you-solved-the-problem-5gg4</link>
      <guid>https://forem.com/resir014/please-tell-us-how-you-solved-the-problem-5gg4</guid>
      <description>&lt;p&gt;&lt;em&gt;Header image by &lt;a href="https://unsplash.com/@designbytholen"&gt;Regine Tholen&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/8s8p3jyoMlo"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's never been a better time to start programming. With the internet at our fingertips, there are tons of resources available to learn any language, library, or framework that you so wish.&lt;/p&gt;

&lt;p&gt;There are also online communities for the programming languages you enjoy. There you can meet like-minded people and discuss your favourite languages/libraries, share your knowledge with others, and ask for help if you're stuck.&lt;/p&gt;

&lt;p&gt;Previously if you came across errors while programming, you would have to consult a reference specific to the programming language you're writing in — which could be hundreds of pages long — and find the exact section for the error you're having. No &lt;a href="https://www.google.com/"&gt;Google&lt;/a&gt;, &lt;a href="https://stackoverflow.com/"&gt;Stack Overflow&lt;/a&gt;, or &lt;a href="https://www.freecodecamp.org/"&gt;freeCodeCamp&lt;/a&gt; to help you.&lt;/p&gt;

&lt;p&gt;Nowadays everything is available at our fingertips. If you know where to look, a quick web search would get you to your solution. Or you can jump into discussion boards of programming communities to ask for help, and get answers from people who are fluent in the languages that you use.&lt;/p&gt;

&lt;p&gt;But there are times where we take the convenience of modern programming too much for granted. And there are times where we forget the web is a huge knowledgebase that people will come across in the future.&lt;/p&gt;

&lt;p&gt;Too often I go on the help channels of developer communities seeing this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--irMkHXnp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qnir5m1zq9txx5uc98w7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--irMkHXnp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qnir5m1zq9txx5uc98w7.png" alt="The worst kind of message."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Someone asks a question on a help channel in a developer community, hoping for an answer. Then, through some epiphany or otherwise, they managed to solve it. But they just wrote "solved," all whilst leaving people hanging.&lt;/p&gt;

&lt;p&gt;This is not good etiquette for asking for help, especially for people in the future who will come across your posts. Let me explain why.&lt;/p&gt;




&lt;h2&gt;
  
  
  Have you experienced this?
&lt;/h2&gt;

&lt;p&gt;For those who lived long enough on the internet to experience the days of online forums and bulletin board systems (BBS), we all know too well the experiences that I'm about to tell you.&lt;/p&gt;

&lt;p&gt;You're stuck for hours on end on a certain tech problem, be it standard computer stuff, programming errors, or something similar. You decided to do a quick Google search. You carefully crafted your keywords hoping it clearly explains the problems you're having.&lt;/p&gt;

&lt;p&gt;Jackpot. You found a thread on some random tech forum you've barely heard about, and you decided to click said search result, hoping to find a solution.&lt;/p&gt;

&lt;p&gt;One post. Zero replies. The OP explained exactly the problem you're having, in amazing detail. But alas, nobody seem to have replied with a solution. Or even worse, nobody seemed to care.&lt;/p&gt;

&lt;p&gt;You felt frustrated. It was so close, yet so far. Did this random person solve their problem in the end? Did they jump around into other forums, and ask the same question hoping someone will answer? Or did they just give up, and continue to throw more solutions into the problem until something works? &lt;em&gt;What did they see?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Truth is, you'll never know. So you ended up finding the closest, but not-so-accurate solution for a slightly different problem, hoping it will work.&lt;/p&gt;

&lt;p&gt;There's even a relevant XKCD to this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZXR6UWOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/wisdom_of_the_ancients.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZXR6UWOh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://imgs.xkcd.com/comics/wisdom_of_the_ancients.png" alt="Relevant XKCD comic"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://xkcd.com/979/"&gt;"Wisdom of the Ancients"&lt;/a&gt; - xkcd.com



&lt;p&gt;In the next section, I ask everyone in the developer communities I participate in to practice good etiquette in asking help from the internet. All you need to do is simple.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tell us how you solved it.
&lt;/h2&gt;

&lt;p&gt;The easiest way to prevent the frustrating experience above is to just &lt;strong&gt;tell us how you solved the problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you asked for help in a community with a certain problem, and you manage to solve the problem before getting an answer, let us know you solved it, &lt;em&gt;and&lt;/em&gt; tell us how you did it.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OK, I solved it. I turns out that [...] so I tried doing [...] and it finally works!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even forums like Stack Overflow encourage you to do this. They encourage you to &lt;a href="https://stackoverflow.com/help/self-answer"&gt;answer your own question&lt;/a&gt; when you figure it out by yourself, and they will even &lt;a href="https://stackoverflow.com/help/badges/14/self-learner"&gt;give you a shiny badge&lt;/a&gt; when you do so.&lt;/p&gt;

&lt;p&gt;One recent example is &lt;a href="https://stackoverflow.com/questions/47444189/what-are-the-performance-implications-of-using-an-immediate-mode-gui-compared-to"&gt;this thread&lt;/a&gt;, where someone asked about the performance implications between retained-mode GUI and immediate-mode GUI. Years later, they used the exact same question for their &lt;a href="https://stackoverflow.com/a/59828450"&gt;master's thesis&lt;/a&gt;, and they went back to the thread years later to post an answer outlining the conclusions made in said thesis.&lt;/p&gt;

&lt;p&gt;Telling the world how you solved a problem will not just help you. More importantly, it will also help other people who might encounter the same problem as you in the future.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Web Monetization API and Coil, explained for Twitch streamers</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Mon, 13 Jul 2020 16:09:52 +0000</pubDate>
      <link>https://forem.com/resir014/web-monetization-api-and-coil-explained-for-twitch-streamers-b9c</link>
      <guid>https://forem.com/resir014/web-monetization-api-and-coil-explained-for-twitch-streamers-b9c</guid>
      <description>&lt;p&gt;If you’re a streamer and you looked into your Twitch Dashboard’s activity log lately, chances are you might have seen cheers of at least 100 bits from a user named &lt;code&gt;Coil_Twitch_Bot&lt;/code&gt;. And you’re probably wondering to yourself who it’s from, and why it’s doing it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--huxtxEtJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/09vdg6f4d136fvefwm7m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--huxtxEtJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/09vdg6f4d136fvefwm7m.png" alt="twitch-bit"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Short answer, it’s from &lt;a href="https://coil.com/"&gt;Coil&lt;/a&gt;. Long answer, we need to talk about the Web Monetization API.&lt;/p&gt;




&lt;p&gt;The bot, and its donation you’re seeing is the result of an upcoming web spec called the Web Monetization API, and one of the services which have been adopting it, Coil.&lt;/p&gt;

&lt;p&gt;In a nutshell, &lt;a href="https://webmonetization.org/"&gt;Web Monetization API&lt;/a&gt; is a new spec for the web which allows your website/app to receive a stream of small payments from the user, based on the &lt;a href="https://interledger.org/"&gt;Interledger&lt;/a&gt; protocol. If you connect to a Web Monetization-enabled content on the internet, through a supported browser/platform, you will support the content you’re reading by making micropayments to the content creator in the background.&lt;/p&gt;

&lt;p&gt;This is a brand-new web API, and is still being proposed as a W3C standard at the Web Platform Incubator Community Group. However, services like Coil and a number of payment providers as well as browsers have included built-in support for this API.&lt;/p&gt;

&lt;p&gt;To make your website/app support Web Monetization, simply add the following meta tag to your website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"monetization"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"$YOUR_WALLET_URL"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;a href="https://webmonetization.org/docs/api"&gt;JavaScript API&lt;/a&gt;, you can then make your website behave differently for users who have Web Monetization enabled on their client. For example, removing ads, or even unlocking paywalled content for them.&lt;/p&gt;

&lt;p&gt;Or, you don’t even have to do anything! You can set up Web Monetization to provide passive monetisation for your website/app as well.&lt;/p&gt;




&lt;p&gt;But what does this have to do with Coil though?&lt;/p&gt;

&lt;p&gt;Well, Coil provides a way to support the content you enjoy by allowing you to make micropayments to sites which support them. And it all happens through the power of Web Monetization API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zy8BqXQX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3c4oukisnhewj066ok7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zy8BqXQX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3c4oukisnhewj066ok7r.png" alt="coil-screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You become a Coil member by paying a flat $5/month fee. Once a member, you can download their extension to enable the power of Web Monetization through Coil on your browser.&lt;/p&gt;

&lt;p&gt;When a website has Web Monetization enabled, your extension will start making micropayments every second to the website owner’s wallet. Currently, the wallets that support Web Monetization are &lt;a href="https://uphold.com/"&gt;Uphold&lt;/a&gt;, &lt;a href="https://gatehub.net/"&gt;Gatehub&lt;/a&gt;, &lt;a href="https://stronghold.co/real-time-payments#coil"&gt;Stronghold&lt;/a&gt;, and &lt;a href="https://www.xrptipbot.com/"&gt;XRP Tipbot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But what about Twitch streams then? How are you receiving that bits donation from Coil’s bot?&lt;/p&gt;

&lt;p&gt;Coil &lt;a href="https://help.coil.com/for-creators/twitch-stream"&gt;works natively on Twitch&lt;/a&gt;, too! If you are an affiliated or partnered Twitch streamers, you don’t need to set anything up, since payouts from Coil members are provided through &lt;a href="https://www.twitch.tv/bits"&gt;Twitch Bits&lt;/a&gt;. If you have Coil members watching your stream and they have the extension installed, it’ll collect micropayments the same way over time, and pays it out via bits periodically.&lt;/p&gt;




&lt;p&gt;Let’s face it, monetising content on the web is broken, and the current solution available leaves the entire user experience on the web worse off. The only way you support content creators and journalists for their work nowadays is broken. They make you go into one of the web’s many walled gardens, and force you to make separate payments over many different walled gardens you go into.&lt;/p&gt;

&lt;p&gt;But that shouldn’t be how monetisation works on the internet. It should work the same, every time, everywhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aux5u1Z8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vnn8tq57jncf2ghccjnc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aux5u1Z8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vnn8tq57jncf2ghccjnc.png" alt="paywall"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Web Monetization API makes monetising content on the Internet open, global, and respects your privacy. I really want this to be the future of the internet, and Coil is taking steps towards it.&lt;/p&gt;

&lt;p&gt;I don’t want to make this seem like a sponsored post, but I really believe in Web Monetization API and I really want to see Coil succeed. If you want to support your favourite Twitch streamers as well as many other content on the internet, consider subscribing to &lt;a href="https://coil.com/"&gt;Coil&lt;/a&gt;. It’s only $5 per month, which is a great deal.&lt;/p&gt;

</description>
      <category>webmonetization</category>
      <category>javascript</category>
      <category>streaming</category>
      <category>twitch</category>
    </item>
    <item>
      <title>Why can't we just get along?</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Sat, 20 Jun 2020 05:55:00 +0000</pubDate>
      <link>https://forem.com/resir014/why-can-t-we-just-get-along-4lc3</link>
      <guid>https://forem.com/resir014/why-can-t-we-just-get-along-4lc3</guid>
      <description>&lt;p&gt;&lt;em&gt;Header image by &lt;a href="https://unsplash.com/photos/MAEbdaFe4ps"&gt;Olav Ahrens Røtne&lt;/a&gt; on Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There’s been a lot of Discourse™ in the frontend landscape after &lt;a href="https://twitter.com/sstephenson/status/1272608076433166336"&gt;this thread&lt;/a&gt;, announcing a new email client called &lt;a href="https://hey.com/"&gt;HEY&lt;/a&gt;, was published. In it, they dove deep into HEY’s tech stack, and further boasted about its capabilities. This started further debate on the unique path HEY has taken, and whether or not “better” tech stack is a feature.&lt;/p&gt;

&lt;p&gt;I’ve written &lt;a href="https://medium.com/@resir014/why-you-moved-from-angular-2-to-vue-js-and-why-you-didnt-understand-what-react-is-about-107ea9188912"&gt;a couple&lt;/a&gt; &lt;a href="https://dev.to/resir014/no-typescript-is-not-a-waste-of-time-2hpk"&gt;of times&lt;/a&gt; lamenting about the tendency of people starting framework/language wars time and time again. The reality is that your choice of frontend stack doesn’t matter that much anymore. It always frustrates me every time people write opinion thinkpieces disguised as “objective” “facts” about how one framework, or language, is better than the other.&lt;/p&gt;




&lt;p&gt;I’ve been on the web development landscape for 6-7 years now. I’ve seen frameworks, technologies, and libraries come and go. I’ve tried all 4 of the Big Frameworks, and understood what each of their benefits are.&lt;/p&gt;

&lt;p&gt;I’ve done a lot of framework-hopping before eventually settling on React. From &lt;a href="https://angular.io/"&gt;Angular&lt;/a&gt; I became addicted to &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;. From &lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt; I learned how better developer tools can significantly improve the developer experience. And from &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; I could get down and dirty with business logic more comfortably.&lt;/p&gt;

&lt;p&gt;I’ve recently tried learning Svelte, and have been doing so while livestreaming to my &lt;a href="https://www.twitch.tv/resir014"&gt;Twitch channel&lt;/a&gt;, which you can view the entire series &lt;a href="https://www.twitch.tv/collections/4SmikxhFFRZGXw"&gt;here&lt;/a&gt;. Over time, I’ve seen the advantages of it, as well as some neat features that literally made my jaw drop.&lt;/p&gt;

&lt;p&gt;As much as these frameworks benefits are useful, they’re &lt;em&gt;not&lt;/em&gt; mutually exclusive.&lt;/p&gt;

&lt;p&gt;Let me explain.&lt;/p&gt;




&lt;p&gt;I’ve been working on a static website as a side project lately. Since our deployment environment is very limited, I had to be creative and include a mix of old and new tools.&lt;/p&gt;

&lt;p&gt;For example, I’ve decided to get back to &lt;a href="https://gulpjs.com/"&gt;Gulp&lt;/a&gt; and improve the site’s build pipeline. Gulp has improved a lot since v4 came out, and this allows me to include the best of old and new in one build pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--20KZhY9h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resir014.xyz/static/3576b84f4ee7b2c0abaf20afd06629e8/33faa/Code_wM0hTn11vc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--20KZhY9h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resir014.xyz/static/3576b84f4ee7b2c0abaf20afd06629e8/33faa/Code_wM0hTn11vc.png" alt="Gulpfile!" title="Gulpfile!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allows me to rewrite most of the outdated ES5 code into mostly vanilla ES6. It’s not always vanilla though. Thanks to &lt;a href="http://browserify.org/"&gt;Browserify&lt;/a&gt; we can now include the best of the JavaScript ecosystem into our stack. For example, there’s an interactive widget that is written in &lt;a href="https://preactjs.com/"&gt;Preact&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Code-splitting is done entirely manually, with each top-level styles and scripts compiled to their separate files. This forces me to actually write proper modular code, where, I split the styles/scripts between core modules and page/feature-specific modules. I’ve devised a custom file naming scheme to figure out which one is which.&lt;/p&gt;

&lt;p&gt;This of course means that every part of the code can be included on-demand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j_k9EFgN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resir014.xyz/static/6ec4acb1cd697bdc39fc8e56e9a56dec/990f1/skM6hdHASh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j_k9EFgN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://resir014.xyz/static/6ec4acb1cd697bdc39fc8e56e9a56dec/990f1/skM6hdHASh.png" alt="Manual code splitting" title="Manual code splitting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I haven’t written pure SCSS for a while now, and ever since then, the CSS ecosystem has improved significantly. I’ve combined the best of SCSS (nesting, mixins, etc) with the best features that are already in CSS today (custom properties, grid, etc.). I then run everything through &lt;a href="https://postcss.org/"&gt;PostCSS&lt;/a&gt; to down-compile these features to something that’s supported by popular browsers.&lt;/p&gt;

&lt;p&gt;I kinda miss the old way of building websites. But I also have been spoiled by the developer experience of modern tools.&lt;/p&gt;

&lt;p&gt;So why can’t we have the best of both?&lt;/p&gt;




&lt;p&gt;We have been spoiled by Good Developer Experience™ with these modern frameworks, we tend to forget that in the real world, &lt;em&gt;user experience&lt;/em&gt; always wins over &lt;em&gt;developer experience&lt;/em&gt;. Just being able to run &lt;code&gt;yarn dev&lt;/code&gt; and getting your new app running in a day doesn’t solve user’s pain points like user experience, accessibility, etc. All of these require attention to detail and TLC.&lt;/p&gt;

&lt;p&gt;It’s what I’ve been realising when building that project as well. It’s that you &lt;em&gt;can&lt;/em&gt; combine the best of old and new if it further improves the user experience.&lt;/p&gt;

&lt;p&gt;But do take note that this does &lt;strong&gt;not&lt;/strong&gt; mean that we have to force everyone to party like it’s the 90s. Different companies have different solutions, different user needs, pain points, etc. Feel free to continue on using React, Vue, Angular, and any other modern framework you like. Feel free to stick to the Old Way™️ of doing things. Just remember that choosing a stack is half the battle.&lt;/p&gt;

&lt;p&gt;Because a tech stack is &lt;em&gt;not&lt;/em&gt; a feature. The way you solve your users’ needs is the &lt;em&gt;real&lt;/em&gt; feature.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>"How do you use a Next.js router in a class component?"</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Thu, 28 May 2020 05:16:23 +0000</pubDate>
      <link>https://forem.com/resir014/how-do-you-use-a-next-js-router-in-a-class-component-ajf</link>
      <guid>https://forem.com/resir014/how-do-you-use-a-next-js-router-in-a-class-component-ajf</guid>
      <description>&lt;p&gt;Recorded live on &lt;a href="https://www.twitch.tv/videos/633185925"&gt;Twitch&lt;/a&gt; on 26 May 2020.&lt;/p&gt;

&lt;p&gt;This video is a short clip from one of my Twitch-Driven Development sessions, when someone asked me how to use a Next.js router in a class component. Want more of these? I do live coding streams occasionally on my &lt;a href="https://www.twitch.tv/resir014"&gt;Twitch channel&lt;/a&gt;. Follow me to be notified!&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Supercharging your Next.js site with getStaticProps and getStaticPaths</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Sat, 07 Mar 2020 15:07:00 +0000</pubDate>
      <link>https://forem.com/resir014/supercharging-your-next-js-site-with-getstaticprops-and-getstaticpaths-424d</link>
      <guid>https://forem.com/resir014/supercharging-your-next-js-site-with-getstaticprops-and-getstaticpaths-424d</guid>
      <description>&lt;p&gt;I’ve been diving deep into &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; lately. It has grown from just merely a framework for server-rendered React apps, to a full-fledged framework for building &lt;em&gt;any&lt;/em&gt; React-based full-stack apps, be it server-rendered, statically-generated, or a combination of both. And with the upcoming changes, we will see some incredible new features to unlock the full potential of both server rendering and static generation.&lt;/p&gt;

&lt;p&gt;In this post, we’ll take a quick look at these new features, and see how well it compares to all previous versions of Next.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  The beginning: getInitialProps
&lt;/h2&gt;

&lt;p&gt;The power behind Next.js always lies behind the &lt;code&gt;getInitialProps&lt;/code&gt; API. Whilst other frameworks decide to go the extra mile by including complicated boilerplates inside of the framework itself just to pull content, Next.js provides a simple intuitive API that doesn’t care how you prerender content into your app.&lt;/p&gt;

&lt;p&gt;In summary, &lt;code&gt;getInitialProps&lt;/code&gt; is how you fetch content into a certain Next.js page before it is rendered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// render page content&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Gets props during prerendering (server-side or static)&lt;/span&gt;
&lt;span class="nx"&gt;IndexPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// fetch content (e.g. using a WordPress API helper&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wp/v2/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// return your desired props&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No posts found&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="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// fallback props if necessary&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s so freaking simple. You can always trust the good folks at ZEIT to design simple, but intuitive APIs on every library they build.&lt;/p&gt;

&lt;p&gt;The problem? It’s hybrid. This means that despite the initial load of a site being pre-rendered, any subsequent route changes in your app will run another client-side fetch in order to get the new content. For dynamic content this is fine, but for static sites pulling static content through a headless CMS API, this can be a bit wasteful on resources.&lt;/p&gt;

&lt;p&gt;And as a knock-on effect on how this API works, generating static pages also requires a bit of boilerplate using &lt;a href="https://nextjs.org/docs/api-reference/next.config.js/exportPathMap"&gt;the &lt;code&gt;exportPathMap&lt;/code&gt; option&lt;/a&gt; in your Next.js config file.&lt;/p&gt;

&lt;p&gt;But fortunately, with changes coming to Next.js, everything’s going to be much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improved static-site generation
&lt;/h2&gt;

&lt;p&gt;About a few months back, the team behind Next.js &lt;a href="https://github.com/zeit/next.js/issues/9524"&gt;published an RFC&lt;/a&gt; detailing how they’re trying to improve static-site generation (SSG) within Next.js. This introduces several new Next.js lifecyle methods, including &lt;code&gt;getStaticProps&lt;/code&gt; and &lt;code&gt;getStaticPaths&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First things first, &lt;code&gt;getStaticProps&lt;/code&gt; will render any content passed through it statically at build time. This fits well into the JAMstack workflow, since all content is generated at build time. You can do any types of content fetching in this lifecycle, just as you would with &lt;code&gt;getInitialProps&lt;/code&gt; and it will still work as it has been. The difference? Your content will now be pre-generated by Next.js as a static JSON, and any subsequent client-side routing will fetch from these files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.jsx&lt;/span&gt;

&lt;span class="c1"&gt;// getStaticProps is only called server-side&lt;/span&gt;
&lt;span class="c1"&gt;// In theory you could do direct database queries&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Unlike `getInitialProps` the props are returned under a props key&lt;/span&gt;
    &lt;span class="c1"&gt;// The reasoning behind this is that there's potentially more options&lt;/span&gt;
    &lt;span class="c1"&gt;// that will be introduced in the future.&lt;/span&gt;
    &lt;span class="c1"&gt;// For example to allow you to further control behavior per-page.&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&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;Note that we pass in all of the props inside a &lt;code&gt;props&lt;/code&gt; key. This is to make room for any additional configurations that may be added in the future.&lt;/p&gt;

&lt;p&gt;To alleviate the burden of &lt;code&gt;exportPathMap&lt;/code&gt;, the &lt;code&gt;getStaticPaths&lt;/code&gt; lifecycle is also introduced. This allows you to return a list of pages to render with certain parameters. This will then be used by Next.js to prerender any static pages from dynamic routes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/blog/[slug].jsx&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// render posts content here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// `getStaticPaths` allows the user to return a list of parameters to&lt;/span&gt;
&lt;span class="c1"&gt;// render to HTML at build time.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;// this renders /blog/hello-world to HTML at build time&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&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="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we return all the path parameters inside a &lt;code&gt;paths&lt;/code&gt; key. Just like in &lt;code&gt;getStaticProps&lt;/code&gt; this is to make room for any additional configurations that may be added in the future. For example, we can add in &lt;code&gt;fallback: false&lt;/code&gt; to disable the default fallback behaviour within Next.js, &lt;a href="https://github.com/zeit/next.js/issues/9524#issue-528348833"&gt;which were described in the RFC document&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This also works with &lt;a href="https://nextjs.org/blog/next-9-2#catch-all-dynamic-routes"&gt;catch-all dynamic routes&lt;/a&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/blog/[...slug].jsx&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// render posts content here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// `getStaticPaths` allows the user to return a list of parameters to&lt;/span&gt;
&lt;span class="c1"&gt;// render to HTML at build time.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="c1"&gt;// this renders /blog/2020/03/hello-world to HTML at build time&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&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="s1"&gt;2020&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="s1"&gt;03&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="s1"&gt;hello-world&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, how do we hook it up with, say, the WordPress API? Here’s a quick example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/blog/[slug].tsx&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// render posts content here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// fetch content (e.g. using a WordPress API helper...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wp/v2/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// then return all of the rendered paths here:&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// put the slugs in with /blog/[slug] format&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// fallback to empty path if no posts found&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BlogPage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you still want the full capabilities of dynamic content, you can also look into the &lt;code&gt;getServerSideProps&lt;/code&gt; lifecycle. This is beyond the scope of this post, though you can still look into the full RFC document for its implementation detail.&lt;/p&gt;

&lt;p&gt;These new features have been implemented in the canary version of Next.js for everyone to try. You can install the canary version of Next.js by running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# npm&lt;/span&gt;
npm i next@canary

&lt;span class="c"&gt;# yarn&lt;/span&gt;
yarn add next@canary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;Over the past week, I’ve been helping the team at Kawal COVID-19 to build &lt;a href="https://kawalcovid19.id/"&gt;their website&lt;/a&gt;. We’re a group of volunteers from many backgrounds (including, but not limited to, medical practicioners, technologists, and data scientists), helping to provide accurate and factual information regarding the recent outbreak of the coronavirus COVID-19, which has hit several countries, including Indonesia. Our channels so far include &lt;a href="https://www.facebook.com/KawalCOVID19"&gt;Facebook&lt;/a&gt;, &lt;a href="https://twitter.com/KawalCOVID19"&gt;Twitter&lt;/a&gt;, and as of recently, our website.&lt;/p&gt;

&lt;p&gt;We initiated the project the day before &lt;a href="https://twitter.com/KemenkesRI/status/1234494277457076227"&gt;the first confirmed case of COVID-19 hit Indonesia&lt;/a&gt;, so we had to move fast. Everything from the architectural decision, to development and deployment of our website took 3-4 days.&lt;/p&gt;

&lt;p&gt;The architecture we decided to go with is a statically-generated Next.js site which pulls content from a WordPress backend. If that sounded familiar to you, &lt;a href="https://medium.com/kata-engineering/headless-wordpress-next-js-what-we-learned-c10abdf80f6a"&gt;I tried a similar architecture where I work&lt;/a&gt;. The difference is we’re running a new version of Next.js, therefore we can utilise new features like dynamic routes.&lt;/p&gt;

&lt;p&gt;Going static helps us unlock the true possibilities of a JAMstack site, and improves the speed, stability, and security of our website from back to front. However, over the past couple days, we started to notice bottlenecks. As users start to roll in once we announced the website’s launch, we’re starting to see increased response time in our WordPress backend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AZRP7B23--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6p2304mfgihkfr0yz427.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AZRP7B23--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6p2304mfgihkfr0yz427.jpg" alt="before.jpg" title="before.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;getInitialProps&lt;/code&gt; is hybrid, and only the first load of the page is pre-rendered, every client-side fetching triggered by route changes includes additional roundtrip into our WordPress backend. This causes WordPress REST API response times to increase as more people from across the country access our site.&lt;/p&gt;

&lt;p&gt;So we had to figure out another way to keep API roundtrips to a minimum. Fortunately, I remembered about the upcoming SSG improvements in Next.js, so I made the call to switch to the canary version and implement these new features.&lt;/p&gt;

&lt;p&gt;It didn’t take a long time to migrate everything from &lt;code&gt;getInitialProps&lt;/code&gt; to &lt;code&gt;getStaticProps&lt;/code&gt;. However, converting from &lt;code&gt;exportPathMap&lt;/code&gt; to &lt;code&gt;getStaticPaths&lt;/code&gt; might have to depend on the complexity of your routes, and we’re lucky to have made the call to switch when there’s not much content yet.&lt;/p&gt;

&lt;p&gt;The result? I’ll let the following GIF speak for itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R2a-fvYG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s6ewkou1ubf3ex4gwlm6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R2a-fvYG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s6ewkou1ubf3ex4gwlm6.gif" alt="comparison.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first load remains as fast as it used to be, but every subsequent route changes now loads from pre-generated data from our local build, therefore reducing API roundtrip and making the content load much faster.&lt;/p&gt;

&lt;p&gt;This also helps us reduces dependency on our WordPress API to zero, therefore reducing its load resulting from any API calls.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SgKb8YGJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7tacyf9hmyvk0izqqpgf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SgKb8YGJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7tacyf9hmyvk0izqqpgf.jpg" alt="after.jpg" title="after.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Give it a try!
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, you can try these features before they are included by installing the Next.js canary build. You can install the canary build of Next.js here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# npm&lt;/span&gt;
npm i next@canary

&lt;span class="c"&gt;# yarn&lt;/span&gt;
yarn add next@canary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently, the docs for it resides only in the &lt;a href="https://github.com/zeit/next.js/issues/9524"&gt;RFC document&lt;/a&gt;, but the ZEIT team will publish the necessary docs for it once it’s ready.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>No, TypeScript is not a waste of time.</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Mon, 29 Jul 2019 17:27:00 +0000</pubDate>
      <link>https://forem.com/resir014/no-typescript-is-not-a-waste-of-time-2hpk</link>
      <guid>https://forem.com/resir014/no-typescript-is-not-a-waste-of-time-2hpk</guid>
      <description>&lt;p&gt;&lt;em&gt;Header image by &lt;a href="https://unsplash.com/photos/AoEEtI6onH4"&gt;Chris Leggat&lt;/a&gt; on Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Another day, another heated “discussion” about how static typing in JavaScript is both the single greatest thing since sliced bread &lt;em&gt;and&lt;/em&gt; the worst thing to have happened to humanity as a whole.&lt;/p&gt;

&lt;p&gt;Let’s look into a &lt;a href="https://dev.to/parkroolucas/typescript-is-a-waste-of-time-change-my-mind-pi8"&gt;recent dev.to post&lt;/a&gt; that has been stirring this debate back up again. I’ll try to clear out some misconceptions, and hopefully, take things in a level-headed manner.&lt;/p&gt;

&lt;p&gt;Before I start, I want to change up some terms I used, especially the one in the title. Instead of referring to &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; specifically, I’d like to use the term “typed JavaScript”. Because there’s also another tool in the typed JS land, &lt;a href="https://flow.org/"&gt;Flow&lt;/a&gt;, and I don’t want to leave Flow users out. After all, we have the same goal of enforcing type soundness/safety in our apps.&lt;/p&gt;

&lt;p&gt;Another term that I would like to throw into the glossary is “dynamically-typed” JS, or “dynamic” for short. Despite what the original post wanted to make you believe, writing JS code without type annotations doesn’t mean that your code doesn't have types. A string written in dynamic JS still has a type of &lt;code&gt;string&lt;/code&gt;. So is a &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, you get the point. You just don't have to explicitly express said types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yes, it’s longer to start writing statically-typed JS short-term…
&lt;/h2&gt;

&lt;p&gt;I’m going to level with you: writing dynamically-typed JS is faster in the short-term. You might be surprised hearing that from a TypeScript advocate, but I’m being serious here. Really!&lt;/p&gt;

&lt;p&gt;Let’s say you’re writing a Node.js library. If you’re writing it in dynamically-typed JS, you can write your library and publish it, all without going through any build tools. It’s that fast! For tiny libraries that do one thing, writing it like this is the most effective way because of the speed.&lt;/p&gt;

&lt;p&gt;But now, let’s say you’re writing an entire backend in Node.js. It’s just a tiny API service with a couple endpoints. You have written your authentication system, middleware, and controllers in JavaScript. And since it’s a small endpoint with minor functionalities, you went with plain ol’ JavaScript.&lt;/p&gt;

&lt;p&gt;Now, imagine that tiny API service balooned into a full-fledged platform API with thousands of code. Probably tens of thousands of lines of code. Then you realised that you found a bug in one of your endpoints. Oh dear! Unit testing didn’t catch it, so you had to spend hours to trace around your app, looking for the issue. Maybe even setting up breakpoints, or even doing the old-fashioned &lt;code&gt;console.log&lt;/code&gt;-driven debugging.&lt;/p&gt;

&lt;p&gt;Then, you found the issue. Remember that one time you refactored that one middleware? You also changed the name of the exported function along with it. Sure, you had that middleware unit-tested, but your unit tests were only isolated to that middleware.&lt;/p&gt;

&lt;p&gt;Then your eyes came across a file where you had that middleware imported. &lt;em&gt;Of course.&lt;/em&gt; You changed the exported function name, but you forgot to rename the imports.&lt;/p&gt;

&lt;p&gt;Hours of productivity lost just because of a typo or missing file!&lt;/p&gt;

&lt;h2&gt;
  
  
  …but the long-term effects are real!
&lt;/h2&gt;

&lt;p&gt;Sure, you can also check mismatched imports with linting tools. But you might also want to rename a function — as well as updating the function name on all the files that import said function — all in the click of a button. After all, humans make mistakes, and missing things like this is not uncommon. TypeScript’s support for &lt;a href="https://code.visualstudio.com/docs/editor/refactoring"&gt;quick refactoring&lt;/a&gt; and find-and-replace support helps you deal with this. Therefore you can focus more on writing code instead of doing pointless find-and-replace by hand.&lt;/p&gt;

&lt;p&gt;Static type checkers like TypeScript and Flow also help reduce the amount of bugs in your code by detecting errors like this during compile time. There’s some statistical proof to this, too. In general, using static typing in your JavaScript code &lt;a href="https://blog.acolyer.org/2017/09/19/to-type-or-not-to-type-quantifying-detectable-bugs-in-javascript/"&gt;can help prevent about 15%&lt;/a&gt; of the bugs that end up in committed code.&lt;/p&gt;

&lt;p&gt;Sure, this will make starting out a project with TypeScript much slower, because you’ll need to define types, interfaces, and the like, in the very early stages of your app. But I’d argue that having you write implementation models, in the form of types and/or interfaces, makes you think about your app’s data structure early in the day.&lt;/p&gt;

&lt;p&gt;This greatly improves confidence of your app in the long run. And when you use these types well, in many cases you don’t even need types, thanks to TypeScript’s &lt;a href="https://mariusschulz.com/blog/control-flow-based-type-analysis-in-typescript"&gt;control-flow based type analysis&lt;/a&gt;. The benefits of TypeScript on large-scale apps outweighs the trade-offs of the longer time to kickstart your TypeScript project.&lt;/p&gt;

&lt;p&gt;Is this an investment that you would take in the future? It sure is for me, but I wouldn’t make any prior judgement for your apps. It’s still up to you to decide whether that investment is worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  You can adopt TypeScript incrementally
&lt;/h2&gt;

&lt;p&gt;Maybe you’re already maintaining a medium to large-scale app that’s already written in plain ol’ JavaScript. And you want to migrate to TypeScript, but are afraid that the red squiggly lines will haunt you in your sleep. How would you go about migrating your code?&lt;/p&gt;

&lt;p&gt;There are various guides in migrating to TypeScript. There’s one in Basarat Ali Syed’s awesome &lt;a href="https://basarat.gitbooks.io/typescript/content/docs/types/migrating.html"&gt;TypeScript Deep Dive&lt;/a&gt; handbook. I have also written a comprehensive guide &lt;a href="https://dev.to/resir014/migrating-to-typescript-part-1-getting-started-n4l"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another neat part of TypeScript is being able to infer types of normal JS files through JSDoc annotations, so if you write valid JSDoc annotations, and have JS typechecking turned on, it’ll be easy for you to migrate down the road.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/fMzOUcjYX6k8GdC8a3/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/fMzOUcjYX6k8GdC8a3/giphy.gif" alt="infer-types-from-jsdoc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although admittedly, the migration experience is where TypeScript falls short. The reason I linked to third-party guides is — well — TypeScript &lt;em&gt;does&lt;/em&gt; have an &lt;a href="https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html"&gt;official migration guide&lt;/a&gt;, although it’s horribly outdated. The official documentation also makes hard assumptions that the user know &lt;em&gt;something&lt;/em&gt; about statically-typed languages, so I wouldn’t recommend them to newcomers.&lt;/p&gt;

&lt;p&gt;Though rest assured, the TypeScript team has been working on &lt;a href="https://github.com/microsoft/TypeScript/issues/31983"&gt;reworking the documentation&lt;/a&gt;, as well as &lt;a href="https://github.com/microsoft/TypeScript-New-Handbook"&gt;a new handbook&lt;/a&gt; that will hopefully teach TypeScript a lot more progressively.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what about dynamic, runtime values?
&lt;/h2&gt;

&lt;p&gt;Admittedly, the TypeScript team has explicitly stated that extending static type-checking to the runtime is a &lt;a href="https://github.com/Microsoft/TypeScript/issues/1573#issuecomment-68374376"&gt;non-goal&lt;/a&gt; for the TypeScript compiler itself. But in reality, we still have to handle these runtime boundaries. A common example to this would be reading a JSON output from an API, or consuming an HTTP request payload.&lt;/p&gt;

&lt;p&gt;Since there’s a strong community backing towards TypeScript, the community has developed elegant solutions to this issue. There are tools like &lt;a href="https://github.com/gcanti/io-ts"&gt;io-ts&lt;/a&gt; which you can use to determine runtime representations in TS. A suitable alternative to Flow would be &lt;a href="https://gajus.github.io/flow-runtime/"&gt;flow-runtime&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static typing and testing go hand-in-hand!
&lt;/h2&gt;

&lt;p&gt;So far we’ve done a lot in making sure the type safety of our app with static types. Despite that, there are certain bugs static typing cannot catch. For a quick example, testing whether that toggle button displays its opposite state the right way when clicked.&lt;/p&gt;

&lt;p&gt;I’m a fan of the &lt;a href="https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests"&gt;Testing Trophy&lt;/a&gt; model by Kent C. Dodds. In his model, both linting/static analysis/static type checking and unit testing are located in the “base” of the trophy. This means that they’re both integral parts into building a testing experience that evokes confidence in your code. Hence I’d like to argue that both static typing and unit testing go hand-in-hand in helping you write code with less bugs!&lt;/p&gt;

&lt;p&gt;Let’s put the toggle button example above into code. We’re using TypeScript as our static typing, and Jest + react-testing-library to test our code.&lt;/p&gt;

&lt;p&gt;Here’s an example of said component, implemented in React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ToggleButtonProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;enabledText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;disabledText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ToggleButton&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;enabledText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;disabledText&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ToggleButtonProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleToggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setToggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;enabledText&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;disabledText&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleToggle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Toggle&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ToggleButton&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the surface, it looks like static typing has done its job. However, if we take a look closer, we’re able to set a custom state text for our toggle button. Sure, TypeScript can check if the string we passed to the &lt;code&gt;enabledText&lt;/code&gt; and &lt;code&gt;disabledText&lt;/code&gt; props is a string. But that’s just half of the battle.&lt;/p&gt;

&lt;p&gt;After all, if we’ve set our button’s enabled and disabled state is set to &lt;code&gt;'On'&lt;/code&gt; and &lt;code&gt;'Off'&lt;/code&gt; respectively, we want it to correctly show &lt;code&gt;'Off'&lt;/code&gt; when it’s disabled, and &lt;code&gt;'On'&lt;/code&gt; when it’s enabled. Not the other way around.&lt;/p&gt;

&lt;p&gt;Since we already checked the types of our component and its props through TypeScript, we can focus on testing the behaviour of the button.&lt;/p&gt;

&lt;p&gt;The following example uses &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; as our test runner, and &lt;a href="https://testing-library.com/docs/react-testing-library/intro"&gt;react-testing-library&lt;/a&gt; as our React testing utility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fireEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ToggleButton&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ToggleButton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ToggleButton&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;correctly renders the state of button&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryByText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ToggleButton&lt;/span&gt; &lt;span class="na"&gt;enabledText&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"on"&lt;/span&gt; &lt;span class="na"&gt;disabledText&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Test the initial state of the button.&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;On&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeNull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// Fires a click event to the button.&lt;/span&gt;
    &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Toggle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;// Test if toggle state is correctly modified.&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;On&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeNull&lt;/span&gt;&lt;span class="p"&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;Two things are happening here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static typing provides soundness and improves the developer experience by detecting type errors and allowing developers to refactor confidently through great IDE tools.&lt;/li&gt;
&lt;li&gt;Unit testing provides confidence that our code behaves the way that it’s supposed to be used.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/react-ts-unit-test-example-2u85p"&gt;Try it out in CodeSandbox&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s clear our heads
&lt;/h2&gt;

&lt;p&gt;The original post contained a lot of subjective points, which was a shame because I’d love some objective reasoning as to why static types aren’t worth the time.&lt;/p&gt;

&lt;p&gt;My rebuttal to the original post… also contains a lot of subjective points. But that’s fine! Because my goal in writing this post isn’t about going off about how one technology is “objectively better” than the other. I was trying to outline how one technology might benefit the users more than the other, and vice versa. And also find a commonality shared between both of them. Or at least, &lt;a href="https://www.destroyallsoftware.com/talks/ideology"&gt;I tried to&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of building inflammatory, subjective opinions disguised as “objective” “fact”, let’s approach things in a level-headed manner and understand that certain tools exists for certain reasons. Constructive criticism is a great power to improve all of us, regardless of which side you’re in on this debate.&lt;/p&gt;

&lt;p&gt;Since I’m a front-end developer myself, a good example I’d like to pick would be the endless debates between the Big Three frameworks (&lt;a href="https://angular.io/"&gt;Angular&lt;/a&gt;, &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;, and &lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt;), and why one is better than the other.&lt;/p&gt;

&lt;p&gt;For example, Vue and React developers often went up in arms, writing senseless Medium thinkpieces about how one is better than the other. I’m a React guy myself, but I still understand that &lt;a href="https://www.youtube.com/watch?v=ANtSWq-zI0s"&gt;Evan You had his own issues to tackle&lt;/a&gt; with Vue, hence the issues that he solved being his framework’s key selling point. The most prominent ones being the learning curve and how easy it is to adopt.&lt;/p&gt;

&lt;p&gt;The people behind TypeScript and Flow are smart enough to tackle one of their pain points in writing JavaScript. They want to write JavaScript code that scales in large-scale projects. And the way they approach that is to provide a static typing superset that ensures type soundness and safety, as well as improving productivity through developer tools that are enabled thanks to the power of static types. And for some people, it worked well. TypeScript and Flow are both running many medium to large-scale projects out there (including where I work), and I could imagine all the ways they enabled engineers to write code with less bugs.&lt;/p&gt;

&lt;p&gt;TypeScript might be a waste of time &lt;strong&gt;for you&lt;/strong&gt;, but it certainly isn’t a waste of time for me.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, there’s nothing wrong in writing plain JS as well! Maybe you want to iterate faster on the early stages of the project, so you opted for plain JS instead of jumping into TS straight away. Maybe you want to get down and dirty with TypeScript right from the get-go. Both of these are fine. After all, it’s only &lt;em&gt;you&lt;/em&gt; knows how to best develop your app. It’s only &lt;em&gt;you&lt;/em&gt; who knows how to serve a better user/developer experience.&lt;/p&gt;

&lt;p&gt;Because regardless of our choices of tools, languages, and frameworks (or lack thereof), it all ends up with a working app.&lt;/p&gt;

&lt;p&gt;Right?&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Using TypeScript's absolute paths in Create React App 2.0 without ejecting</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Wed, 13 Mar 2019 02:37:00 +0000</pubDate>
      <link>https://forem.com/resir014/using-typescripts-absolute-paths-in-create-react-app-20-without-ejecting-4kd9</link>
      <guid>https://forem.com/resir014/using-typescripts-absolute-paths-in-create-react-app-20-without-ejecting-4kd9</guid>
      <description>&lt;p&gt;&lt;em&gt;Header image: &lt;a href="https://commons.wikimedia.org/wiki/File:Ejection_seat_test_at_China_Lake_with_F-4B_cockpit_1967.jpg"&gt;Ejection seat test at China Lake with F-4B cockpit (1967)&lt;/a&gt;, public domain (US).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update 2019-05-15:&lt;/strong&gt; Starting from &lt;a href="https://github.com/facebook/create-react-app/releases/tag/v3.0.0"&gt;version 3.0&lt;/a&gt;, Create React App will respect the &lt;code&gt;baseurl&lt;/code&gt; settings that you have in your &lt;code&gt;tsconfig.json&lt;/code&gt;. If you already use CRA 3.0 and above, this guide is no longer necessary.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://facebook.github.io/create-react-app/"&gt;Create React App (CRA) 2.0&lt;/a&gt; allows for drop-in support for TypeScript. This means we can finally use TypeScript from the core CRA package without having to rely on community-maintained forks like &lt;a href="https://github.com/wmonk/create-react-app-typescript"&gt;create-react-app-typescript&lt;/a&gt;. Thanks to Babel 7’s TypeScript support, the TypeScript integration to CRA 2.0 is seamless. Although this means that slight differences from &lt;code&gt;create-react-app-typescript&lt;/code&gt; apply.&lt;/p&gt;

&lt;p&gt;One TypeScript feature that lacks from &lt;code&gt;create-react-app&lt;/code&gt; and TypeScript is the ability to use absolute imports. This allows importing from an absolute path based on the project’s root source directory. It means you can import modules without having to resort to relative paths. Nothing wrong with them, but when your folders are deeply nested, they can sometimes go ugly. (&lt;code&gt;../../../../../../../&lt;/code&gt;, anyone?)&lt;/p&gt;

&lt;p&gt;Unfortunately, with CRA 2.0 making use of Babel for transpilation, this feature is rather limited. And they made it clear by forcing some defaults on this behaviour. For instance, CRA 2.0 automatically removes the &lt;code&gt;baseUrl&lt;/code&gt; and &lt;code&gt;paths&lt;/code&gt; options from the &lt;code&gt;tsconfig.json&lt;/code&gt; any time we run its scripts. This means for some people wanting to make use of this feature, ejecting is the only option.&lt;/p&gt;

&lt;p&gt;Not anymore. Thanks to some clever little hacks and using CRA rewiring tools, we can now set up CRA 2.0 to respect TypeScript’s absolute imports without ejecting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we start
&lt;/h2&gt;

&lt;p&gt;Please note that rewiring CRA scripts is a slightly-advanced technique. Proceed with caution!&lt;/p&gt;

&lt;p&gt;By rewiring your scripts, your’re breaking the &lt;a href="https://github.com/facebookincubator/create-react-app/issues/99#issuecomment-234657710"&gt;“guarantees”&lt;/a&gt; that React provides. You now accept that you “own” your configs, which means that the CRA team cannot give support for your rewired config.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Stuff can break” — &lt;a href="https://twitter.com/dan_abramov/status/1045809734069170176"&gt;Dan Abramov&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But fortunately, with tools like &lt;code&gt;craco&lt;/code&gt;, we can easily revert back to the default CRA config should things go wrong. It’s still a better option over ejecting CRA entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up &lt;code&gt;craco&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/sharegate/craco"&gt;craco&lt;/a&gt; is a wonderful tool which allows us to extend CRA 2.0 configs without ejecting. It’s the spiritual successor for &lt;a href="https://github.com/timarney/react-app-rewired"&gt;react-app-rewired&lt;/a&gt;, which has ceased development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# yarn&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add @craco/craco

&lt;span class="c"&gt;# npm&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @craco/craco
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After &lt;code&gt;craco&lt;/code&gt; is installed, create an empty &lt;code&gt;craco.config.js&lt;/code&gt; file. We’ll touch this later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// craco.config.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, change the npm scripts in the &lt;code&gt;package.json&lt;/code&gt; to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   "scripts": {
&lt;span class="gd"&gt;- "start": "react-scripts start",
&lt;/span&gt;&lt;span class="gi"&gt;+ "start": "craco start",
&lt;/span&gt;&lt;span class="gd"&gt;- "build": "react-scripts build",
&lt;/span&gt;&lt;span class="gi"&gt;+ "build": "craco build"
&lt;/span&gt;&lt;span class="gd"&gt;- "test": "react-scripts test",
&lt;/span&gt;&lt;span class="gi"&gt;+ "test": "craco test"
&lt;/span&gt;   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will run the CRA scripts through &lt;code&gt;craco&lt;/code&gt; which will inject the rewires set in &lt;code&gt;craco.config.js&lt;/code&gt; to the scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extend &lt;code&gt;paths&lt;/code&gt; option from a separate file
&lt;/h2&gt;

&lt;p&gt;CRA 2.0 will automatically override the &lt;code&gt;paths&lt;/code&gt; config on the base &lt;code&gt;tsconfig.json&lt;/code&gt; every time we run &lt;code&gt;npm start&lt;/code&gt;. So we’ll have to work around it by defining it from a separate file.&lt;/p&gt;

&lt;p&gt;Name this file whatever you’d like. This file exists solely because CRA 2.1 overwrites our base tsconfig every time we run &lt;code&gt;npm start&lt;/code&gt;. Always define paths in this file!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsconfig.paths.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"//"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Define absolute imports path mappings."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"//"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Don't forget to add these to `resolve.alias` on `craco.config.js`."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to set our absolute imports relative to the &lt;code&gt;src&lt;/code&gt; folder, e.g. &lt;code&gt;components/Container&lt;/code&gt;. If you prefer to use wildcard characters like &lt;code&gt;~&lt;/code&gt;, you can also use that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"//"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allows you to import modules with the `~/components/Container` format."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"~/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we can extend the config above in our main &lt;code&gt;tsconfig.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsconfig.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"//"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Extend the config we just created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.paths.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"//"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the rest of the tsconfig"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rewire webpack aliases using &lt;code&gt;craco&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now it’s time to tell the transpiler to alias a root module directory to its correct path. There are two ways to do this, one through Babel using &lt;code&gt;babel-plugin-module-resolver&lt;/code&gt;, and the other by setting webpack aliases. We’ll do the latter.&lt;/p&gt;

&lt;p&gt;Open your &lt;code&gt;craco.config.js&lt;/code&gt; file and add the webpack config rewire.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// craco.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@craco/craco&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Add the aliases for all the top-level folders in the `src/` folder.&lt;/span&gt;
      &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/assets/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/components/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/interfaces/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/modules/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/utils/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="c1"&gt;// Another example for using a wildcard character&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;~&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;
    &lt;span class="p"&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;Start the development server again, and now your absolute imports should work!&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Jest’s &lt;code&gt;moduleNameMapper&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you use Jest, you should also let it know how to handle absolute imports. We can, of course, do this through &lt;code&gt;craco&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Add the aliases for all the top-level folders in the `src/` folder.&lt;/span&gt;
      &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/assets/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/components/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/interfaces/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/modules/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/utils/`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="c1"&gt;// Another example for using a wildcard character&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;~&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appSrc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;moduleNameMapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Jest module mapper which will detect our absolute imports.&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^assets(.*)$&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="s1"&gt;&amp;lt;rootDir&amp;gt;/src/assets$1&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="s1"&gt;^components(.*)$&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="s1"&gt;&amp;lt;rootDir&amp;gt;/src/components$1&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="s1"&gt;^interfaces(.*)$&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="s1"&gt;&amp;lt;rootDir&amp;gt;/src/interfaces$1&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="s1"&gt;^modules(.*)$&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="s1"&gt;&amp;lt;rootDir&amp;gt;/src/modules$1&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="s1"&gt;^utils(.*)$&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="s1"&gt;&amp;lt;rootDir&amp;gt;/src/utils$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// Another example for using a wildcard character&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="s1"&gt;&amp;lt;rootDir&amp;gt;/src$1&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  And that’s it!
&lt;/h2&gt;

&lt;p&gt;Your CRA 2.0 setup now respects TypeScript’s absolute imports. Pretty simple, right?&lt;/p&gt;

&lt;p&gt;Enjoy the power of TypeScript in your React app! If you want to learn more about how TypeScript can help you in React, check out the &lt;a href="https://github.com/sw-yx/react-typescript-cheatsheet"&gt;React TypeScript Cheatsheet&lt;/a&gt;. It also includes cheatsheets for common React patterns in TypeScript.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>tips</category>
    </item>
    <item>
      <title>Migrating to TypeScript, Part 2: Trust the compiler!</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Mon, 25 Feb 2019 08:53:00 +0000</pubDate>
      <link>https://forem.com/resir014/migrating-to-typescript-part-2-trust-the-compiler-4o87</link>
      <guid>https://forem.com/resir014/migrating-to-typescript-part-2-trust-the-compiler-4o87</guid>
      <description>&lt;p&gt;&lt;em&gt;Header image by &lt;a href="https://unsplash.com/photos/nYIQYg8cQVc"&gt;Irina Iriser&lt;/a&gt; on &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In part 1, we explored how to initialise a project with the TypeScript compiler and the new TypeScript Babel preset. In this part, we’ll go through a quick primer of TypeScript’s features and what they’re for. We’ll also learn how to migrate your existing JavaScript project gradually to TypeScript, using an actual code snippet from an existing project. This will get you to learn how to trust the compiler along the way.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thinking in TypeScript
&lt;/h2&gt;

&lt;p&gt;The idea of static typing and type safety in TypeScript might feel overwhelming coming from a dynamic typing background, but it doesn’t have to be that way.&lt;/p&gt;

&lt;p&gt;The main thing people often tell you about TypeScript is that it’s “just JavaScript with types”. Since JavaScript is dynamically typed, a lot of features like type coercion is often abused to make use of the dynamic nature of the language. So the idea of type-safety might never come across your average JS developer. This makes the idea of static typing and type safety feel overwhelming, but it doesn’t have to be that way.&lt;/p&gt;

&lt;p&gt;The trick is to rewire our thinking as we go along. And to do that we need to have a mindset. The primary mindset, as defined in &lt;a href="https://basarat.gitbooks.io/typescript/docs/javascript/recap.html"&gt;Basarat’s book&lt;/a&gt;, is &lt;strong&gt;Your JavaScript is already TypeScript&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  But why is TypeScript important?
&lt;/h3&gt;

&lt;p&gt;A more appropriate question to ask would be &lt;strong&gt;“why is static typing in JavaScript important?”&lt;/strong&gt; Sooner or later, you’re going to start writing medium to large-scale apps with JavaScript. When your codebase gets larger, detecting bugs will become a more tedious task. Especially when it’s one of those pesky &lt;code&gt;Cant read property 'x' of undefined&lt;/code&gt; errors. JavaScript is a dynamically-typed language by nature and it has a lot of its quirks, like &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; types, type coercion, and the like. Sooner or later, these tiny quirks will work against you down the road.&lt;/p&gt;

&lt;p&gt;Static typing ensures the correctness of your code in order to help detect bugs early. Static type checkers like TypeScript and &lt;a href="https://flow.org/"&gt;Flow&lt;/a&gt; help reduce the amount of bugs in your code by detecting type errors during compile time. In general, using static typing in your JavaScript code &lt;a href="https://blog.acolyer.org/2017/09/19/to-type-or-not-to-type-quantifying-detectable-bugs-in-javascript/"&gt;can help prevent about 15%&lt;/a&gt; of the bugs that end up in committed code.&lt;/p&gt;

&lt;p&gt;TypeScript also provides various productivity enhancements like the ones listed below. You can see these features on editors with first-class TypeScript support like &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced statement completion through IntelliSense&lt;/li&gt;
&lt;li&gt;Smarter code refactoring&lt;/li&gt;
&lt;li&gt;Ability to infer types from usage&lt;/li&gt;
&lt;li&gt;Ability to type-check JavaScript files (and infer types from JSDoc annotations)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Strict mode
&lt;/h2&gt;

&lt;p&gt;TypeScript’s “strict mode” is where the meat are of the whole TypeScript ecosystem. The &lt;code&gt;--strict&lt;/code&gt; compiler flag, introduced in &lt;a href="https://blog.mariusschulz.com/2017/06/09/typescript-2-3-the-strict-compiler-option"&gt;TypeScript 2.3&lt;/a&gt;, activates TypeScript’s strict mode. This will set all strict typechecking options to true by default, which includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--noImplicitAny&lt;/code&gt; - Raise error on expressions and declarations with an implied ‘any’ type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--noImplicitThis&lt;/code&gt; - Raise error on ‘this’ expressions with an implied ‘any’ type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--alwaysStrict&lt;/code&gt; - Parse in strict mode and emit “use strict” for each source file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--strictBindCallApply&lt;/code&gt; - Enable strict ‘bind’, ‘call’, and ‘apply’ methods on functions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--strictNullChecks&lt;/code&gt; - Enable &lt;a href="https://basarat.gitbooks.io/typescript/docs/options/strictNullChecks.html"&gt;strict null checks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--strictFunctionTypes&lt;/code&gt; - Enable strict checking of function types.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--strictPropertyInitialization&lt;/code&gt; - Enable strict checking of property initialization in classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;code&gt;strict&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt; in your &lt;code&gt;tsconfig.json&lt;/code&gt;, all of the options above are set to &lt;code&gt;true&lt;/code&gt;. If some of these options give you problems, you can override strict mode by overriding the options above one by one. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strictFunctionTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strictPropertyInitialization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will enable all strict type-checking options &lt;em&gt;except&lt;/em&gt; &lt;code&gt;--strictFunctionTypes&lt;/code&gt; and &lt;code&gt;--strictPropertyInitialization&lt;/code&gt;. Fiddle around with these options when they give you trouble. Once you get more comfortable with them, slowly re-enable them one by one.&lt;/p&gt;
&lt;h2&gt;
  
  
  Linting
&lt;/h2&gt;

&lt;p&gt;Linting and static analysis tools are one of the many essential tools for any language. There are currently two popular linting solutions for TypeScript projects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://palantir.github.io/tslint/"&gt;TSLint&lt;/a&gt;&lt;/strong&gt; used to be the de-facto tool for linting TypeScript code. It has served the TS community well throughout the years, but it has fallen out of favour as of late. Development seems to have stagnated lately, with the authors even &lt;a href="https://medium.com/palantir/tslint-in-2019-1a144c2317a9"&gt;announcing its deprecation&lt;/a&gt; recently in favour of ESLint. Even Microsoft themselves have &lt;a href="https://github.com/Microsoft/TypeScript/issues/29288"&gt;noticed some architectural and performance issues&lt;/a&gt; in TSLint as of late, and recommended against it. Which brings me to the next option.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;&lt;/strong&gt; - yeah, I know. But hear me out for a second. Despite being a tool solely for linting JavaScript for quite some time, ESLint has been adding more and more features to better support TS. It has announced plans to &lt;a href="https://eslint.org/blog/2019/01/future-typescript-eslint"&gt;better support TS&lt;/a&gt; through the new &lt;a href="https://github.com/typescript-eslint/typescript-eslint"&gt;typescript-eslint&lt;/a&gt; project. It contains a TypeScript parser for ESLint, and even a plugin which &lt;a href="https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules"&gt;ports many TSLint rules into ESLint&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, ESLint might be the better choice going forward. To learn more about using ESLint for TypeScript, read through the docs of the &lt;a href="https://github.com/typescript-eslint/typescript-eslint"&gt;typescript-eslint&lt;/a&gt; project.&lt;/p&gt;
&lt;h2&gt;
  
  
  A quick primer to TypeScript types
&lt;/h2&gt;

&lt;p&gt;The following section contains some quick references on how TypeScript type system works. For a more detailed guide, read this &lt;a href="http://2ality.com/2018/04/type-notation-typescript.html"&gt;2ality blog post&lt;/a&gt; on TypeScript’s type system.&lt;/p&gt;
&lt;h3&gt;
  
  
  Applying types
&lt;/h3&gt;

&lt;p&gt;Once you’ve renamed your &lt;code&gt;.js&lt;/code&gt; files to &lt;code&gt;.ts&lt;/code&gt; (or &lt;code&gt;.tsx&lt;/code&gt;), you can enter type annotations. Type annotations are written using the &lt;code&gt;: TypeName&lt;/code&gt; syntax.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;assignedNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;

&lt;span class="nx"&gt;assignedNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;greetPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also define return types for a function.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isFinishedGreeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;getPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;isGreeted&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;h3&gt;
  
  
  Primitive &amp;amp; unit types
&lt;/h3&gt;

&lt;p&gt;TypeScript has a few supported primitive types. These are the most basic data types available within the JavaScript language, and to an extent TypeScript as well.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Boolean&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isDone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;// Number&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xf00d&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mb"&gt;0b1010&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;octal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mo"&gt;0o744&lt;/span&gt;

&lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;standardString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;templateString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Your number is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These primitive types can also be turned into &lt;strong&gt;unit types&lt;/strong&gt; , where values can be their own types.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This variable can only have one possible value: 42.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fortyTwo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;

&lt;span class="c1"&gt;// A unit type can also be combined with other types.&lt;/span&gt;
&lt;span class="c1"&gt;// The `|` turns this into a union type. We'll go through it in the next section.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;maybeFalsey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Intersection &amp;amp; union types
&lt;/h3&gt;

&lt;p&gt;You can combine two or more types together using intersection and union types.&lt;/p&gt;

&lt;p&gt;Union types can be used for types/variables that have have one of several types. This tells TypeScript that &lt;strong&gt;“variable/type X can be of either type A or type B.”&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;formatCommandline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Intersection types can be used to combine multiple types into one. This tells TypeScript that &lt;strong&gt;“variable/type X contains type A and B.”&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="c1"&gt;// { a: string, b: string }&lt;/span&gt;

&lt;span class="c1"&gt;// Example usage of intersection types.&lt;/span&gt;
&lt;span class="c1"&gt;// Here we take two objects, then combining them into one whilst using intersection types&lt;/span&gt;
&lt;span class="c1"&gt;// to combine the types of both objects into one.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// use TypeScript type casting to create an object with the combined type.&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt;

  &lt;span class="c1"&gt;// combine the object.&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&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="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// `x` now has both `a` and `b` property&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;type&lt;/code&gt;s and &lt;code&gt;interface&lt;/code&gt;s
&lt;/h3&gt;

&lt;p&gt;For defining types of objects with a complex structure, you can use either the &lt;code&gt;type&lt;/code&gt; or the &lt;code&gt;interface&lt;/code&gt; syntax. Both work essentially the same, with &lt;code&gt;interface&lt;/code&gt; being well-suited for object-oriented patterns with classes.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Types&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ComponentProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ReactComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Interfaces&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TaskImpl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CreepTask&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;TaskImpl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

  &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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;h3&gt;
  
  
  Generics
&lt;/h3&gt;

&lt;p&gt;Generics provide meaningful type constraints between members.&lt;/p&gt;

&lt;p&gt;In the example below, we define an Action type where the &lt;code&gt;type&lt;/code&gt; property can be anything that we pass into the generic.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The type that we defined inside the generic will be passed down to the &lt;code&gt;type&lt;/code&gt; property. In the example below, &lt;code&gt;type&lt;/code&gt; will have a unit type of &lt;code&gt;'FETCH_USERS'&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// You can also use `Action&amp;lt;string&amp;gt;` for any string value.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;FetchUsersAction&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FETCH_USERS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserInfo&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AddUserAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_USER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AddUserAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADD_USER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Declaration files
&lt;/h3&gt;

&lt;p&gt;You can let TypeScript know that you’re trying to describe a some code that exists somewhere in your library (a module, global variables/interfaces, or runtime environments like Node). To do this, we use the &lt;code&gt;declare&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;Declaration files always have a &lt;code&gt;.d.ts&lt;/code&gt; file extension.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// For example, to annotate Node's `require()` call&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;

&lt;span class="c1"&gt;// Now you can use `require()` everywhere in your code!&lt;/span&gt;
&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;whatwg-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can include this anywhere in your code, but normally they’re included in a declaration file. Declaration files have a &lt;code&gt;.d.ts&lt;/code&gt; extension, and are used to declare the types of your own code, or code from other libraries. Normally, projects will include their declaration files in something like a &lt;code&gt;declarations.d.ts&lt;/code&gt; file and will not be emitted in your compiled code.&lt;/p&gt;

&lt;p&gt;You can also constrain declarations to a certain module in the &lt;code&gt;declare module&lt;/code&gt; syntax. For example, here’s a module that has a default export called &lt;code&gt;doSomething()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// You can also export types inside modules so library consumers can use them.&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ExportedType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExportedType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let’s migrate!
&lt;/h2&gt;

&lt;p&gt;Alright, enough with the lectures, let’s get down and dirty! We’re going to take a look at a real-life project, take a few modules, and convert them to TypeScript.&lt;/p&gt;

&lt;p&gt;To do this, I’ve taken upon the help of my Thai friend named &lt;a href="https://dt.in.th/"&gt;Thai&lt;/a&gt; (yeah, I know). He has a massive, web-based rhythm game project named &lt;a href="https://bemuse.ninja"&gt;Bemuse&lt;/a&gt;, and he’s been planning to migrate it to TypeScript. So let’s look at some parts of the code and try migrating them to TS where we can.&lt;/p&gt;
&lt;h3&gt;
  
  
  From &lt;code&gt;.js&lt;/code&gt; to &lt;code&gt;.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Consider the following module:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0-CMYAei--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bi681uy6marceq0zrmrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0-CMYAei--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bi681uy6marceq0zrmrr.png" alt="1-non-js-file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we have your typical JavaScript module. A simple module with a function type-annotated with JSDoc, and two other non-annotated functions. And we’re going to turn this bad boy into TypeScript.&lt;/p&gt;

&lt;p&gt;To make a file in your project a TypeScript file, we just need to rename it from &lt;code&gt;.js&lt;/code&gt; to &lt;code&gt;.ts&lt;/code&gt;. Easy, right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6V-QEF3s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mug06higec3p1pa63qot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6V-QEF3s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mug06higec3p1pa63qot.png" alt="2-rename-to-ts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh no! We’re starting to see some red! What did we do wrong?&lt;/p&gt;

&lt;p&gt;This is fine, actually! We’ve just enabled our TypeScript type-checking by doing this, so what’s left for us is to add types as we see fit.&lt;/p&gt;

&lt;p&gt;The first thing to do is to add parameter types to these functions. As a quick way to get started, TypeScript allows us to infer types from usage and include them in our code. If you use Visual Studio Code, click on the lightbulb that appears when your cursor is in the function name, and click on “Infer parameter types from usage”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/jy8Ii9UdsRGZxQETgq/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/jy8Ii9UdsRGZxQETgq/giphy.gif" alt="infer-types-from-usage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your functions/variables are documented using &lt;a href="http://usejsdoc.org/"&gt;JSDoc&lt;/a&gt;, this gets much easier as TS can also infer parameter types from JSDoc annotations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/fMzOUcjYX6k8GdC8a3/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/fMzOUcjYX6k8GdC8a3/giphy.gif" alt="infer-types-from-jsdoc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that TypeScript generated a partial object schema for the function at the bottom of this file based on usage. We can use it as a starting point to improve its definition using &lt;code&gt;interface&lt;/code&gt;s and &lt;code&gt;type&lt;/code&gt;s. For example, let’s take a look at this line.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Returns the accuracy number for a play record.
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;formattedAccuracyForRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;formatAccuracy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calculateAccuracy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&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;We already know that we have properties &lt;code&gt;count&lt;/code&gt; and &lt;code&gt;total&lt;/code&gt; in this parameter. To make this code cleaner, we can put this declaration into a separate &lt;code&gt;type&lt;/code&gt;/&lt;code&gt;interface&lt;/code&gt;. You can include this within the same file, or separately on a file reserved for common types/interfaces, e.g. &lt;code&gt;types.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RecordItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
  &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RecordItem&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path/to/types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Returns the accuracy number for a play record.
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;formattedAccuracyForRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RecordItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;formatAccuracy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calculateAccuracy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&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;h3&gt;
  
  
  Dealing with external modules
&lt;/h3&gt;

&lt;p&gt;With that out of the way, now we’re going to look at how to migrate files with external modules. For a quick example, we have the following module:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oihrnIwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yb3fpxlnj4yv9ph7ta3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oihrnIwG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yb3fpxlnj4yv9ph7ta3v.png" alt="4-raw-ts-with-modules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve just renamed this raw JS file into &lt;code&gt;.ts&lt;/code&gt; and we’re seeing a few errors. Let’s take a look at them.&lt;/p&gt;

&lt;p&gt;On the first line, we can see that TypeScript doesn’t understand how to deal with the &lt;code&gt;lodash&lt;/code&gt; module we imported. If we hovered over the red squiggly line, we can see the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not find a declaration file for module 'lodash-es'. '/Users/resir014/etc/repos/bemusic/bemuse/node_modules/lodash/lodash.js' implicitly has an 'any' type.
  Try `npm install @types/lodash` if it exists or add a new declaration (.d.ts) file containing `declare module 'lodash';`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As the error message says, all we need to do to fix this error is to install the type declaration for &lt;code&gt;lodash&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install --save-dev @types/lodash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This declaration file comes from &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped"&gt;DefinitelyTyped&lt;/a&gt;, an extensive library community-maintained declaration files for the Node runtime, as well as many popular libraries. All of them are autogenerated and published in the &lt;code&gt;@types/&lt;/code&gt; scope on npm.&lt;/p&gt;

&lt;p&gt;Some libraries include their own declaration files. If a project is compiled from TypeScript, the declarations will be automatically generated. You can also create declaration files manually for your own library, even when your project is not built using TypeScript. When generating declaration files inside a module, be sure to include them inside a &lt;code&gt;types&lt;/code&gt;, or &lt;code&gt;typings&lt;/code&gt; key in the &lt;code&gt;package.json&lt;/code&gt;. This will make sure the TypeScript compiler knows where to look for the declaration file for said module.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./lib/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./types/index.d.ts"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;OK, so now we have the type declarations installed, how does our TS file look like?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0pe_ZNn4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ui0btlep4ymrk8tls75k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0pe_ZNn4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ui0btlep4ymrk8tls75k.png" alt="5-installed-declarations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whoa, what’s this? I thought only one of those errors would be gone? What’s happening here?&lt;/p&gt;

&lt;p&gt;Another power of TypeScript is that it’s able to infer types based on how data flows throughout your module. This is called &lt;em&gt;control-flow based type analysis&lt;/em&gt;. This means that TypeScript will know that the &lt;code&gt;chart&lt;/code&gt; inside the &lt;code&gt;.orderBy()&lt;/code&gt; call comes from what was passed from the previous calls. So the only type error that we have to fix now would be the function parameter.&lt;/p&gt;

&lt;p&gt;But what about libraries without type declaration? On the first part of my post, I’ve come across this comment.&lt;/p&gt;


&lt;div class="liquid-comment"&gt;
    &lt;div class="details"&gt;
      &lt;a href="/vignesh0025"&gt;
        &lt;img class="profile-pic" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ycrQmqPM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--NHm0ck9S--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_50%2Cq_auto%2Cw_50/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/117330/484330db-e8df-4c3a-8fd7-b5c132ddbe86.jpeg" alt="vignesh0025 profile image"&gt;
      &lt;/a&gt;
      &lt;a href="/vignesh0025"&gt;
        &lt;span class="comment-username"&gt;Vignesh D&lt;/span&gt;
      &lt;/a&gt;
      &lt;span class="color-base-30 px-2 m:pl-0"&gt;•&lt;/span&gt;

&lt;a href="https://dev.to/vignesh0025/comment/834k" class="comment-date crayons-link crayons-link--secondary fs-s"&gt;
  &lt;time&gt;
    Jan 9 '19
  &lt;/time&gt;

&lt;/a&gt;

    &lt;/div&gt;
    &lt;div class="body"&gt;
      

&lt;p&gt;I was trying to use Typescript with react and Evergreen-Ui react library. But Evergreen-ui doesn't have typescript support. It's asking for declaration file which I couldn't understand. How to proceed with it? &lt;/p&gt;



    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Some packages include their own typings within the project, so oftentimes it will get picked up by the TypeScript compiler. But in case we have neither built-in typings nor &lt;code&gt;@types&lt;/code&gt; package for the library, we can create a shim for these libraries using ambient declarations (&lt;code&gt;*.d.ts&lt;/code&gt; files).&lt;/p&gt;

&lt;p&gt;First, create a folder in your source directory to hold ambient declarations. Call it &lt;code&gt;types/&lt;/code&gt; or something so we can easily find them. Next, create a file to hold our own custom declarations for said library. Usually we use the library name, e.g. &lt;code&gt;evergreen-ui.d.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now inside the &lt;code&gt;.d.ts&lt;/code&gt; file we just created, put the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;evergreen-ui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will shim the &lt;code&gt;evergreen-ui&lt;/code&gt; module so we can import it safely without the “Cannot find module” errors.&lt;/p&gt;

&lt;p&gt;Note that this doesn’t give you the autocompletion support, so you will have to declare the API for said library manually. This is optional of course, but very useful if you want better autocompletion.&lt;/p&gt;

&lt;p&gt;For example, if we were to use Evergreen UI’s Button component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import React's base types for us to use.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;evergreen-ui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;DimensionProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SpacingProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PositionProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LayoutProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The above extended props props are examples for extending common props and are not included in this example for brevity.&lt;/span&gt;

    &lt;span class="nl"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;danger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;appearance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;minimal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;

    &lt;span class="c1"&gt;// Again, skipping the rest of the props for brevity, but you get the idea.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ButtonProps&lt;/span&gt;&lt;span class="o"&gt;&amp;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;And that’s it for part 2! The full guide concludes here, but if there are any more questions after this post was published, I’ll try to answer some of them in part 3.&lt;/p&gt;

&lt;p&gt;As a reminder, the &lt;code&gt;#typescript&lt;/code&gt; channel on the &lt;a href="https://www.reactiflux.com/"&gt;Reactiflux&lt;/a&gt; Discord server has a bunch of lovely people who know TypeScript inside and out. Feel free to hop in and ask any question about TypeScript!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Phoenix with React: The Right Way™</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Mon, 21 Jan 2019 06:27:06 +0000</pubDate>
      <link>https://forem.com/resir014/phoenix-with-react-the-right-way-25gi</link>
      <guid>https://forem.com/resir014/phoenix-with-react-the-right-way-25gi</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a long-awaited rewrite of my original post on the perfect setup to use Phoenix with React, originally posted on &lt;a href="https://resir014.xyz/" rel="noopener noreferrer"&gt;my website&lt;/a&gt;. Phoenix 1.4 ships with &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt; by default, therefore making the setup much more straightforward than before. The long-overdue rewrite has been finished, and has also been made up-to-date following recent updates to Phoenix. The &lt;a href="https://github.com/resir014/phoenix_react_playground" rel="noopener noreferrer"&gt;sample repo&lt;/a&gt; has also been updated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For those looking for Part 2 of my Migrating to TypeScript guide, rest assured! It will be finished within the next week.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I've been playing around with &lt;a href="https://elixir-lang.org/" rel="noopener noreferrer"&gt;Elixir&lt;/a&gt; a lot lately. Recently a friend showed me &lt;a href="https://blog.discordapp.com/scaling-elixir-f9b8e1e7c29b" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; by the Discord engineering team about how they could scale their platform through the power of Elixir, and after reading it I was convinced to give it a try. If you're about to learn the language, and you came from Node.js like me, I suggest you go watch &lt;a href="https://www.youtube.com/watch?v=q8wueg2hswA" rel="noopener noreferrer"&gt;this introductory video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If Ruby has &lt;a href="http://rubyonrails.org/" rel="noopener noreferrer"&gt;Rails&lt;/a&gt;, and PHP has &lt;a href="https://laravel.com/" rel="noopener noreferrer"&gt;Laravel&lt;/a&gt;, then Elixir has &lt;a href="http://phoenixframework.org/" rel="noopener noreferrer"&gt;Phoenix&lt;/a&gt;. If you've ever used Rails before, you'll feel right at home. It has the bare essentials of your typical web framework, although it has some neat additional features like &lt;a href="https://hexdocs.pm/phoenix/channels.html" rel="noopener noreferrer"&gt;Channels&lt;/a&gt;, which makes building web apps with sockets much easier.&lt;/p&gt;

&lt;p&gt;My ideal stack for a web app usually includes a React frontend. So naturally, I wanted to know how I could build a Phoenix app with a React frontend. Unfortunately, setting up React with Phoenix isn't as straightforward as many people think. Almost every guide that I came across on the internet only goes as far as rendering a single React component and doesn't cover essential things like routing and API fetching. It took me a while, but finally, I found a setup that Actually Works™.&lt;/p&gt;

&lt;p&gt;So if you're like me and have been wondering how the heck do you actually get it to work, I'm going to show you how. Hopefully this will answer this question once and for all.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;If reading's not your thing, I have prepared the end result of this guide &lt;a href="https://github.com/resir014/phoenix_react_playground" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Once you're all set up, you should have a working Phoenix setup with the following stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elixir (&lt;code&gt;^1.7.4&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Node.js (&lt;code&gt;^10.15.0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;npm (&lt;code&gt;^6.4.1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Phoenix (&lt;code&gt;^1.4.0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;React (&lt;code&gt;^16.7.0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;TypeScript (&lt;code&gt;^3.0.0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Webpack (&lt;code&gt;^4.0.0&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;In this guide, I will assume that you already have &lt;a href="https://elixir-lang.org/" rel="noopener noreferrer"&gt;Elixir&lt;/a&gt;, &lt;a href="https://hexdocs.pm/phoenix/installation.html" rel="noopener noreferrer"&gt;Phoenix&lt;/a&gt;, and &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; installed. If you haven't already, open the links above in a new tab and do it. Don't worry, I'll wait.&lt;/p&gt;

&lt;p&gt;We're also going to use Phoenix 1.4, the latest version available at the time of writing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The boilerplate
&lt;/h3&gt;

&lt;p&gt;We're going to set up a new Phoenix project, complete with the build environment we're going to use.&lt;/p&gt;

&lt;p&gt;As of version 1.4, Phoenix ships with &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt; by default. By running the following command we'll have a Phoenix setup with built-in support for JS bundling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix phx.new phoenix_react_playground
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're asked if you want to fetch and install dependencies as well, answer No. We'll get to it later.&lt;/p&gt;

&lt;p&gt;By default, the &lt;code&gt;package.json&lt;/code&gt; file, the Webpack config, and the &lt;code&gt;.babelrc&lt;/code&gt; file are located in the &lt;code&gt;assets/&lt;/code&gt; folder instead of the project root. This is not ideal, since it could fuck up with IDEs like &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;. So let's move them to the project root instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd phoenix_react_playground
$ mv assets/package.json .
$ mv assets/webpack.config.js .
$ mv assets/.babelrc .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we'll need to change some of the defaults provided by Phoenix:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;@@ -26,7 +26,7 @@&lt;/span&gt; phoenix_react_playground-*.tar
 npm-debug.log
&lt;span class="err"&gt;
&lt;/span&gt; # The directory NPM downloads your dependencies sources to.
&lt;span class="gd"&gt;-/assets/node_modules/
&lt;/span&gt;&lt;span class="gi"&gt;+node_modules/
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt; # Since we are building assets from assets/,
 # we ignore priv/static. You may want to comment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;@@ -6,8 +6,8 @@&lt;/span&gt;
     "watch": "webpack --mode development --watch"
   },
   "dependencies": {
&lt;span class="gd"&gt;-    "phoenix": "file:../deps/phoenix",
-    "phoenix_html": "file:../deps/phoenix_html"
&lt;/span&gt;&lt;span class="gi"&gt;+    "phoenix": "file:deps/phoenix",
+    "phoenix_html": "file:deps/phoenix_html"
&lt;/span&gt;   },
   "devDependencies": {
     "@babel/core": "^7.0.0",
&lt;span class="p"&gt;@@ -18,7 +18,7 @@&lt;/span&gt;
     "mini-css-extract-plugin": "^0.4.0",
     "optimize-css-assets-webpack-plugin": "^4.0.0",
     "uglifyjs-webpack-plugin": "^1.2.4",
&lt;span class="gd"&gt;-    "webpack": "4.4.0",
-    "webpack-cli": "^2.0.10"
&lt;/span&gt;&lt;span class="gi"&gt;+    "webpack": "4.28.4",
+    "webpack-cli": "^3.2.1"
&lt;/span&gt;   }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;webpack.config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;@@ -13,11 +13,11 @@&lt;/span&gt; module.exports = (env, options) =&amp;gt; ({
     ]
   },
   entry: {
&lt;span class="gd"&gt;-      './js/app.js': ['./js/app.js'].concat(glob.sync('./vendor/**/*.js'))
&lt;/span&gt;&lt;span class="gi"&gt;+    app: './assets/js/app.js'
&lt;/span&gt;   },
   output: {
     filename: 'app.js',
&lt;span class="gd"&gt;-    path: path.resolve(__dirname, '../priv/static/js')
&lt;/span&gt;&lt;span class="gi"&gt;+    path: path.resolve(__dirname, 'priv/static/js')
&lt;/span&gt;   },
   module: {
     rules: [
&lt;span class="p"&gt;@@ -36,6 +36,10 @@&lt;/span&gt; module.exports = (env, options) =&amp;gt; ({
   },
   plugins: [
     new MiniCssExtractPlugin({ filename: '../css/app.css' }),
&lt;span class="gd"&gt;-    new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
-  ]
&lt;/span&gt;&lt;span class="gi"&gt;+    new CopyWebpackPlugin([{ from: 'assets/static/', to: '../' }])
+  ],
+  resolve: {
+    // Add '.ts' and '.tsx' as resolvable extensions.
+    extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
+  }
&lt;/span&gt; });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above Webpack configuration works for the ideal Phoenix setup of placing unbundled assets on the &lt;code&gt;assets/&lt;/code&gt; folder. We need to make sure that Phoenix correctly runs the Webpack command as our watcher. To do so, modify &lt;code&gt;config/dev.exs&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-  watchers: []
&lt;/span&gt;&lt;span class="gi"&gt;+  watchers: [
+    {"node", [
+      "node_modules/webpack/bin/webpack.js",
+      "--watch-stdin",
+      "--colors"
+    ]}
+  ]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make sure everything works, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mix deps.get
$ npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Does everything work? Good! Next, we'll set up our TypeScript environment.&lt;/p&gt;

&lt;p&gt;First, we'll install the TypeScript + React preset for Babel, and put it into our &lt;code&gt;.babelrc&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn add --dev @babel/preset-react @babel/preset-typescript @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;@@ -1,5 +1,10 @@&lt;/span&gt;
 {
&lt;span class="gd"&gt;-    "presets": [
-        "@babel/preset-env"
-    ]
-}
&lt;/span&gt;&lt;span class="gi"&gt;+  "presets": [
+    "@babel/preset-env",
+    "@babel/preset-react",
+    "@babel/preset-typescript"
+  ],
+  "plugins": [
+    "@babel/plugin-proposal-class-properties",
+    "@babel/plugin-proposal-object-rest-spread"
+  ]
+}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we'll create a standard &lt;code&gt;tsconfig.json&lt;/code&gt; file and fill it up with the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowSyntheticDefaultImports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"isolatedModules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esnext"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jsx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"preserve"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2016"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esnext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"preserveConstEnums"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"removeComments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sourceMap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./**/*.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./**/*.tsx"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, modify our Webpack config so that the &lt;code&gt;babel-loader&lt;/code&gt; accepts JS and TS files. Don't forget to change the extension of your Webpack entry file too!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;@@ -13,7 +13,7 @@&lt;/span&gt; module.exports = (env, options) =&amp;gt; ({
     ]
   },
   entry: {
&lt;span class="gd"&gt;-    app: './assets/js/app.js'
&lt;/span&gt;&lt;span class="gi"&gt;+    app: './assets/js/app.tsx'
&lt;/span&gt;   },
   output: {
     filename: 'app.js',
&lt;span class="p"&gt;@@ -22,7 +22,7 @@&lt;/span&gt; module.exports = (env, options) =&amp;gt; ({
   module: {
     rules: [
       {
&lt;span class="gd"&gt;-        test: /\.js$/,
&lt;/span&gt;&lt;span class="gi"&gt;+        test: /\.(js|jsx|ts|tsx)$/,
&lt;/span&gt;         exclude: /node_modules/,
         use: {
           loader: 'babel-loader'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've got your boilerplate set up, your Phoenix project's folder structure should now look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;phoenix_react_playground/
├── assets/
│   ├── js/
│   │   ├── ...
│   │   └── app.tsx
│   ├── scss/
│   │   ├── ...
│   │   └── app.scss
│   └── static/
│       ├── images/
│       │   └── ...
│       ├── favicon.ico
│       └── robots.txt
├── config/
│   └── ...
├── lib/
│   └── ...
├── priv/
│   └── ...
├── test/
│   └── ...
├── .gitignore
├── mix.exs
├── package.json
├── README.md
├── tsconfig.json
└── webpack.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up React
&lt;/h3&gt;

&lt;p&gt;Let's now hook up React with Phoenix the right way. First, of course, we'll need to install React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn add react react-dom react-router-dom
$ yarn add --dev @types/react @types/react-dom @types/react-router-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we can set up our base React boilerplate. In our assets folder, rename &lt;code&gt;app.js&lt;/code&gt; to &lt;code&gt;app.tsx&lt;/code&gt;, and rewrite the file as follows.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;assets/js/app.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../css/app.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;phoenix_html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Root&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// This code starts up the React app when it runs in a browser. It sets up the routing&lt;/span&gt;
&lt;span class="c1"&gt;// configuration and injects the app into a DOM element.&lt;/span&gt;
&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Root&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-app&lt;/span&gt;&lt;span class="dl"&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;code&gt;assets/js/Root.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Switch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;HomePage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Root&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;exact&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;HomePage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&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;code&gt;assets/js/components/Header.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"navigation"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://hexdocs.pm/phoenix/overview.html"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Get Started&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"http://phoenixframework.org/"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"phx-logo"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/images/phoenix.png"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Phoenix Framework Logo"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;assets/js/components/Main.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;assets/js/pages/index.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RouteComponentProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RouteComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;HomePage&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;HomePage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should do it.&lt;/p&gt;

&lt;p&gt;Now, open our project's &lt;code&gt;router.ex&lt;/code&gt; folder, and modify our routes in the &lt;code&gt;"/"&lt;/code&gt; scope as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-    get "/", PageController, :index
&lt;/span&gt;&lt;span class="gi"&gt;+    get "/*path", PageController, :index
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, modify our template files so that it properly loads up our React code. In the base layout template, we can everything inside the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag with our script.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;templates/layout/app.html.eex&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;view_module&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;view_template&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;assigns&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= Routes.static_path(@conn, "&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;js&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;app.js&lt;/span&gt;&lt;span class="err"&gt;")&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now the Index page template. Be sure you set the &lt;code&gt;id&lt;/code&gt; attribute to the one you set as the application entry point specified on &lt;code&gt;app.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;templates/page/index.html.eex&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"react-app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sanity check
&lt;/h2&gt;

&lt;p&gt;Now we're going to check if everything works. Run &lt;code&gt;mix deps.get&lt;/code&gt; and &lt;code&gt;npm install&lt;/code&gt; once again just to make sure, then run &lt;code&gt;mix ecto.setup&lt;/code&gt; to build our database (if we have any set up). Then run &lt;code&gt;mix phx.server&lt;/code&gt;, wait until the Webpack process is complete, then head over to &lt;code&gt;localhost:4000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If it works and you can see your webpage loading up, congratulations! Let's move on to the fancy part.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fanjgwq1dsmm3p16278zk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fanjgwq1dsmm3p16278zk.png" alt="Screen Shot 2019-01-20 at 21.24.25" width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating additional pages with &lt;code&gt;react-router&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have our basic Phoenix server running, let's create several examples of the nifty things you could do with React. The most common example that people make when demonstrating the capabilities of React is a Counter app.&lt;/p&gt;

&lt;p&gt;First, we're going add the Counter route to our &lt;code&gt;Root.tsx&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; import * as React from 'react'
 import { BrowserRouter, Route, Switch } from 'react-router-dom'
&lt;span class="err"&gt;
&lt;/span&gt; import Header from './components/Header'
 import HomePage from './pages'
&lt;span class="gi"&gt;+import CounterPage from './pages/counter'
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt; export default class Root extends React.Component {
   public render(): JSX.Element {
     return (
       &amp;lt;&amp;gt;
         &amp;lt;Header /&amp;gt;
         &amp;lt;BrowserRouter&amp;gt;
           &amp;lt;Switch&amp;gt;
             &amp;lt;Route exact path="/" component={HomePage} /&amp;gt;
&lt;span class="gi"&gt;+            &amp;lt;Route path="/counter" component={CounterPage} /&amp;gt;
&lt;/span&gt;           &amp;lt;/Switch&amp;gt;
         &amp;lt;/BrowserRouter&amp;gt;
       &amp;lt;/&amp;gt;
     )
   }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we'll add the &lt;code&gt;Counter&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;assets/js/pages/counter.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Interface for the Counter component state&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;currentCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;currentCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the initial state of the component in a constructor.&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Counter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;The Counter is the simplest example of what you can do with a React component.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Current count: &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* We apply an onClick event to these buttons to their corresponding functions */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;incrementCounter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Increment counter
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button button-outline"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decrementCounter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Decrement counter
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button button-clear"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetCounter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Reset counter
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Back to home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;incrementCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;currentCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;decrementCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;currentCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentCount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;resetCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;currentCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&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;Now go to &lt;code&gt;localhost:4000/counter&lt;/code&gt; and test your creation. If it works, we can continue to the next part.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsv4kpzkv8ymgsmka4t1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsv4kpzkv8ymgsmka4t1a.png" alt="Screen Shot 2019-01-20 at 21.25.24" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching APIs - a painless example
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, almost every React + Phoenix tutorial that I ever found on the internet only went as far as rendering a single React component. They never seem to explain how to make both React and Phoenix properly so that they could communicate with each other. Hopefully this will explain everything.&lt;/p&gt;

&lt;p&gt;Before you start, please please &lt;em&gt;please&lt;/em&gt; make sure that on &lt;code&gt;router.ex&lt;/code&gt;, you have the &lt;code&gt;"/api"&lt;/code&gt; scope declared &lt;em&gt;on top of&lt;/em&gt; the &lt;code&gt;/*path&lt;/code&gt; declaration. Seriously. I spent a whole week figuring why my API routes aren't working, and then only recently realised that I had the routing declarations the other way around.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;router.ex&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;  # &lt;span class="p"&gt;...&lt;/span&gt;

  scope &lt;span class="s2"&gt;"/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; PhoenixReactPlaygroundWeb &lt;span class="k"&gt;do&lt;/span&gt;
    pipe_through &lt;span class="p"&gt;:&lt;/span&gt;api

    # &lt;span class="p"&gt;...&lt;/span&gt;your API endpoints
  end

  # &lt;span class="p"&gt;...&lt;/span&gt;

  scope &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; PhoenixReactPlaygroundWeb &lt;span class="k"&gt;do&lt;/span&gt;
    pipe_through &lt;span class="p"&gt;:&lt;/span&gt;browser # Use the default browser stack

    # This route declaration MUST be below everything &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; Else&lt;span class="p"&gt;,&lt;/span&gt; it will
    # override the rest of the routes&lt;span class="p"&gt;,&lt;/span&gt; even the `/api` routes we'&lt;span class="k"&gt;ve&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; above&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nb"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;"/*path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; PageController&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;index&lt;/span&gt;
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we have them all set, create a new context for our sample data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mix phx.gen.json Example Language languages name:string proverb:string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;router.ex&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;    scope "/api", PhoenixReactPlaygroundWeb do
      pipe_through :api
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     resources "/languages", LanguageController, except: [:new, :edit]
&lt;/span&gt;    end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also create a database seed to pre-populate the data beforehand. More information on how to do that is available on this &lt;a href="https://elixircasts.io/seeding-data-in-phoenix" rel="noopener noreferrer"&gt;Elixir Casts course&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Time for another sanity check! Run the Phoenix server and go to &lt;code&gt;localhost:4000/api/languages&lt;/code&gt;. If everything works correctly, you should see either a blank or populated JSON (depending on whether you preloaded the database first or not).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmuhgwbi60vonn66g403.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmuhgwbi60vonn66g403.png" alt="Screen Shot 2019-01-20 at 21.24.56" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything works well, we can now proceed to our component.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Root.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; import * as React from 'react'
 import { BrowserRouter, Route, Switch } from 'react-router-dom'
&lt;span class="err"&gt;
&lt;/span&gt; import Header from './components/Header'
 import HomePage from './pages'
 import CounterPage from './pages/counter'
&lt;span class="gi"&gt;+import FetchDataPage from './pages/fetch-data'
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt; export default class Root extends React.Component {
   public render(): JSX.Element {
     return (
       &amp;lt;&amp;gt;
         &amp;lt;Header /&amp;gt;
         &amp;lt;BrowserRouter&amp;gt;
           &amp;lt;Switch&amp;gt;
             &amp;lt;Route exact path="/" component={HomePage} /&amp;gt;
             &amp;lt;Route path="/counter" component={CounterPage} /&amp;gt;
&lt;span class="gi"&gt;+            &amp;lt;Route path="/fetch-data" component={FetchDataPage} /&amp;gt;
&lt;/span&gt;           &amp;lt;/Switch&amp;gt;
         &amp;lt;/BrowserRouter&amp;gt;
       &amp;lt;/&amp;gt;
     )
   }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;pages/fetch-data.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The interface for our API response&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ApiResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// The interface for our Language model.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;proverb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;FetchDataExampleState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FetchDataPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="nx"&gt;FetchDataExampleState&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the data from our API.&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/languages&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;renderLanguagesTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Language&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Example proverb&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;proverb&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;em&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;em&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;FetchData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderLanguagesTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Fetch Data&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          This component demonstrates fetching data from the Phoenix API
          endpoint.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Back to home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&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;All good! Now go to &lt;code&gt;localhost:4000/fetch-data&lt;/code&gt; and give it a try.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93zklt8d7iw5p6ctebfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93zklt8d7iw5p6ctebfz.png" alt="Screen Shot 2019-01-20 at 21.25.43" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;If you're still here, congratulations, your setup is complete! Run &lt;code&gt;mix phx.server&lt;/code&gt; again and go through everything. If everything works, double congratulations!&lt;/p&gt;

&lt;p&gt;You can now use this knowledge to build your next React + Phoenix application. The end result of this guide is available &lt;a href="https://github.com/resir014/phoenix_react_playground" rel="noopener noreferrer"&gt;here&lt;/a&gt; for everyone to try out.&lt;/p&gt;

&lt;p&gt;Good luck! Feel free to &lt;a href="https://twitter.com/resir014" rel="noopener noreferrer"&gt;tweet at me&lt;/a&gt; if you have any questions.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://tilde.town/~selsky" rel="noopener noreferrer"&gt;~selsky&lt;/a&gt; for their help on proofreading this post!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>elixir</category>
      <category>phoenix</category>
    </item>
    <item>
      <title>Migrating to TypeScript, Part 1: Introduction and getting started</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Wed, 09 Jan 2019 09:48:00 +0000</pubDate>
      <link>https://forem.com/resir014/migrating-to-typescript-part-1-getting-started-n4l</link>
      <guid>https://forem.com/resir014/migrating-to-typescript-part-1-getting-started-n4l</guid>
      <description>&lt;p&gt;&lt;em&gt;Header image by &lt;a href="https://unsplash.com/photos/vkfrFrAIO4o"&gt;Franz Harvin Aceituna&lt;/a&gt; on &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/"&gt;TypeScript (TS)&lt;/a&gt; is a language which has seen quite a meteoric rise lately. It’s gone some favourable results on the &lt;a href="https://2018.stateofjs.com/javascript-flavors/typescript/"&gt;2018 State of JavaScript (JS)&lt;/a&gt; survey. It has even come to the point where big names like &lt;a href="https://twitter.com/kentcdodds/status/1075853845048188929"&gt;Kent C. Dodds&lt;/a&gt; started migrating into it.&lt;/p&gt;

&lt;p&gt;To learn more about how the TypeScript type system works, and how it can help you, watch this talk by Anders Hejlsberg, the creator of TypeScript.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hDACN-BGvI8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;For many of us already using TypeScript, we could never imagine writing JS without it anymore. And with newly-added support for Babel compilation, it gets much easier to integrate with the rest of the JS ecosystem. But for many people looking to migrate their apps into it, it could feel a little too overwhelming. This gets further out of control when you’re looking at a medium/large-sized app, all already written in JavaScript.&lt;/p&gt;

&lt;p&gt;A lot of TypeScript learning materials out there never seem to dive deep on migrating a well-matured app to TypeScript. Worse still, TypeScript does have their own, &lt;a href="https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html"&gt;official migration guide&lt;/a&gt; - but it’s horribly outdated.&lt;/p&gt;

&lt;p&gt;So in this series of posts, I try to outline my personal steps on how to migrate an existing codebase to TypeScript. The first part will go through the steps on preparing your project for the Big Rewrite. This includes setting up the TS compiler, and the basic essentials of the TypeScript compiler.&lt;/p&gt;




&lt;h2&gt;
  
  
  So what is TypeScript, exactly?
&lt;/h2&gt;

&lt;p&gt;TypeScript is a superset of JavaScript that compiles to plain JavaScript code. It enables great tooling and developer experience through the power of static typing. Some of the improved JS experience being unlocked by static typing includes better refactoring tools, statement completion, and more.&lt;/p&gt;

&lt;p&gt;TypeScript was authored by Anders Hejlsberg, known for being the lead architect of C# and creator of &lt;a href="https://en.wikipedia.org/wiki/Turbo_Pascal"&gt;Turbo Pascal&lt;/a&gt;. TypeScript 2.0 was released on September 2016, with much-improved Node.js modules support and stricter &lt;code&gt;null&lt;/code&gt; checking. Since then, the language is continuously improved with features like object rest/spread, &lt;code&gt;--strict&lt;/code&gt; mode, conditional types, and more. &lt;a href="https://blogs.msdn.microsoft.com/typescript/2018/07/30/announcing-typescript-3-0/"&gt;TypeScript 3.0&lt;/a&gt;, released in July 2018, even has support for monorepos through project references.&lt;/p&gt;

&lt;p&gt;To read more about TypeScript, I recommend the &lt;a href="https://basarat.gitbooks.io/typescript/"&gt;TypeScript Deep Dive&lt;/a&gt; book by Basarat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with TypeScript
&lt;/h2&gt;

&lt;p&gt;So to start off, we will need to set up our environment for TypeScript. There are two ways to set this up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You use Babel 7 + TypeScript preset to compile, and have the TypeScript compiler only do the type-checking.&lt;/li&gt;
&lt;li&gt;You use the TypeScript compiler to both type-check and compile your code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since we’re migrating from JavaScript, we can assume that we’re already using Babel in our development toolchain, so we can go with the first option. You can also run the second option and chain with Babel. But the first option is still better if we want to have finer control over the Babel presets/plugins we use as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialising the compiler
&lt;/h3&gt;

&lt;p&gt;This guide will make use of TypeScript 3.2. It should work as well on any versions starting from 3.0+.&lt;/p&gt;

&lt;p&gt;To get started with TypeScript, install the TypeScript compiler CLI by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install -g typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run &lt;code&gt;tsc --init&lt;/code&gt; to initialise a &lt;code&gt;tsconfig.json&lt;/code&gt; file with the default options. It lists out all the options available as well as an explanation, with the non-essential options commented out. The number of options may overwhelm you, but let’s break the config down to just the essentials.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsconfig.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checkJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"downlevelIteration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"esnext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dom"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noUnusedLocals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esnext"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup will take everything from the &lt;code&gt;src&lt;/code&gt; and compile it into the &lt;code&gt;dist&lt;/code&gt; folder. There are some other essential compiler options here, but we’ll go through them in the next section. To compile, run the &lt;code&gt;tsc&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you use webpack to compile things, you don’t need the &lt;code&gt;outDir&lt;/code&gt; option!&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up build tasks
&lt;/h3&gt;

&lt;p&gt;Now that the TypeScript compiler works, we can include it as a script in our &lt;code&gt;package.json&lt;/code&gt; file!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, you can simply run &lt;code&gt;yarn build&lt;/code&gt; (or &lt;code&gt;npm run build&lt;/code&gt; if you’re running npm) to build your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wiring up the TypeScript Babel preset (Optional)
&lt;/h3&gt;

&lt;p&gt;If you already use Babel to compile your ES6+ JS code, you can use the &lt;a href="https://babeljs.io/docs/en/babel-preset-typescript"&gt;TS preset for Babel&lt;/a&gt;. Note that you need &lt;strong&gt;Babel 7 and above&lt;/strong&gt; to use this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"presets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-typescript"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/plugin-proposal-class-properties"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/plugin-proposal-object-rest-spread"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The TypeScript compiler supports all modern ES2015 features, as well as next-generaton ES features. Though one common pitfall is that &lt;strong&gt;you can’t use next-generation syntax newer than stage-3&lt;/strong&gt; , since TS doesn’t support it. This means that using proposed syntax like the &lt;a href="https://github.com/tc39/proposal-pipeline-operator"&gt;pipeline&lt;/a&gt; will give you type errors. The proposal plugins should include the stage-3 features required for TypeScript transpilation.&lt;/p&gt;

&lt;p&gt;Note that the Babel compiler &lt;strong&gt;only&lt;/strong&gt; removes the types from your code. &lt;strong&gt;It does not do any extra type-checking!&lt;/strong&gt; Make sure to run type-checking separately with &lt;code&gt;tsc --noEmit&lt;/code&gt;. Or better yet, add it as a compiler option into your &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noEmit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This option will run the TypeScript compiler without outputting any code, so it only runs type-checking. You can then add the &lt;code&gt;tsc&lt;/code&gt; command to your &lt;code&gt;package.json&lt;/code&gt; scripts, which will help if you use a CI system as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type-check"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you use Flowtype, you can’t use the Flowtype Babel preset together with the TypeScript preset. You have to choose one or the other!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;tsconfig.json&lt;/code&gt; essentials
&lt;/h2&gt;

&lt;p&gt;The above &lt;code&gt;tsconfig.json&lt;/code&gt; file already contains the essential compiler options when working with TypeScript. Let’s go through the essentials one by one.&lt;/p&gt;

&lt;h3&gt;
  
  
  TS/JS interoperability
&lt;/h3&gt;

&lt;p&gt;The TypeScript compiler can also be set up to type-check and compile JS files alongside TS files. &lt;code&gt;allowJs&lt;/code&gt; allows regular JavaScript files to be compiled. If you want to also enable type-checking in JavaScript files, you can also enable &lt;code&gt;checkJs&lt;/code&gt;. If you’re just getting started, it’s recommended to disable &lt;code&gt;checkJs&lt;/code&gt; and manually enable per-file type checking. To do that, add a &lt;code&gt;// @ts-check&lt;/code&gt; comment on the top of the JS file you’d like to type-check.&lt;/p&gt;

&lt;p&gt;Another compiler option to take note of is &lt;code&gt;esModuleInterop&lt;/code&gt;. This allows you to do default imports with CommonJS modules (e.g. &lt;code&gt;import React from 'react';&lt;/code&gt;). For TS veterans, this option is similar to &lt;code&gt;allowSyntheticDefaultImports&lt;/code&gt;. The only difference is that it added some helpers during compile time for improved Babel interoperability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Libraries and compile targets
&lt;/h3&gt;

&lt;p&gt;There are three options that define how your TS code is interpreted by the compiler.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib&lt;/code&gt; outlines the TS library files used for compilation. Some libraries that are commonly used are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;esnext&lt;/code&gt; - Modern ESnext features (up to stage-3 recommendations)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;es201x&lt;/code&gt; - Yearly ES specifications. Note than including one year will include all of the yearly specs before it (e.g. &lt;code&gt;es2018&lt;/code&gt; will also include &lt;code&gt;es2017&lt;/code&gt;, &lt;code&gt;es2016&lt;/code&gt; and &lt;code&gt;es2015&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dom&lt;/code&gt; - DOM-specific APIs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;webworker&lt;/code&gt; - APIs for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API"&gt;Web workers&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;target&lt;/code&gt; defines the target version of ES.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;module&lt;/code&gt; defines the module type the TS compiler will generate. If you set &lt;code&gt;target&lt;/code&gt; to &lt;code&gt;es5&lt;/code&gt; or below, it will default to &lt;code&gt;commonjs&lt;/code&gt; (standard CommonJS modules for Node.js compatibility). Otherwise, it will default to &lt;code&gt;esnext&lt;/code&gt; (ES Modules).&lt;/p&gt;




&lt;p&gt;And that’s it for this part. In part 2, we’ll go through how to make your TypeScript migration painless by adding types gradually. We’ll also go through the quirks of TypeScript’s type system, as well as changing your way of thinking to write TypeScript apps.&lt;/p&gt;

&lt;p&gt;Once again, I really recommend the &lt;a href="https://basarat.gitbooks.io/typescript/"&gt;TypeScript Deep Dive&lt;/a&gt; book by Basarat. His book on TypeScript has helped me a lot on learning this amazing language. Should you ever get stuck, the &lt;code&gt;#typescript&lt;/code&gt; channel on the &lt;a href="https://www.reactiflux.com/"&gt;Reactiflux&lt;/a&gt; Discord server has a bunch of lovely people who know TypeScript inside and out. Feel free to hop in and ask questions!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Redux 4 + TypeScript: A type-safe approach</title>
      <dc:creator>Resi Respati</dc:creator>
      <pubDate>Fri, 06 Jul 2018 16:09:40 +0000</pubDate>
      <link>https://forem.com/resir014/redux-4--typescript-29-a-type-safe-approach-2lf4</link>
      <guid>https://forem.com/resir014/redux-4--typescript-29-a-type-safe-approach-2lf4</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is also published on my &lt;a href="https://resir014.xyz/posts/2018/07/06/redux-4-plus-typescript/"&gt;personal website&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Even when the JavaScript community is slowly growing mixed opinions about it, I couldn't help but continue using &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt;. Its patterns on immutable state management has become all too familiar to us, and is especially useful when building large apps. Its TypeScript support is exceptional too, with much-needed improvements to its type declarations arriving in Redux 4.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/resir014/a-type-safe-approach-to-redux-stores-in-typescript--5ajm"&gt;I wrote a guide on it&lt;/a&gt; a few months ago, and it has received some amount of attention. The feedback has helped me improve beyond what I normally would've done, and I couldn't thank you enough for that.&lt;/p&gt;

&lt;p&gt;In spirit of that, I finally took the time to update said guide based on the feedbacks I've received, making everything up to date with the latest version of React, Redux, and TypeScript, as well as introducing some neat new tricks.&lt;/p&gt;

&lt;p&gt;Note that the following guide is tested on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;react@^16.4.0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;redux@^4.0.0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;react-redux@^6.0.0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;typescript@^3.3.0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we're building
&lt;/h2&gt;

&lt;p&gt;To demonstrate this post, we're going to build a simple app. We're going to create a website which pulls data from the &lt;a href="https://docs.opendota.com/"&gt;OpenDota API&lt;/a&gt;, and display information about certain heroes and professional teams. This will also demonstrate how to structure your stores for each feature/module in a Redux-enabled app.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;If you want to jump straight to the examples, I've also published a sample project in GitHub, based on the feedback from my previous post. Click &lt;a href="https://github.com/resir014/react-redux-typescript-example"&gt;here&lt;/a&gt; to go there.&lt;/p&gt;




&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2018-12-08:&lt;/strong&gt; Updated &lt;code&gt;Dispatch&lt;/code&gt; to be imported from &lt;code&gt;redux&lt;/code&gt; instead of &lt;code&gt;react-redux&lt;/code&gt;. The guide is also now tested to work on TypeScript &lt;code&gt;^3.0.0&lt;/code&gt;. (Thanks &lt;a href="https://github.com/resir014/react-redux-typescript-example/pull/2"&gt;cancerberoSgx&lt;/a&gt;!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2019-01-05:&lt;/strong&gt; Changed &lt;code&gt;const enum&lt;/code&gt;s to &lt;code&gt;enum&lt;/code&gt;s due to Babel not supporting it. (Thanks &lt;a href="https://github.com/nextriot"&gt;Kyle Gillen&lt;/a&gt;!) &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2019-03-09:&lt;/strong&gt; The latest version of &lt;code&gt;react-redux&lt;/code&gt; broke the typings for the"children-props-as-redux-container" approach I mentioned in the previous version of this post. I would suggest against using this pattern nowadays, but if you still want to use it, I've upgraded the corresponding section in this article to have the same pattern, making use of the newly-introduced &lt;code&gt;ReactReduxContext&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2019-09-22:&lt;/strong&gt; The above pattern breaks on a Create React App setup. The entire &lt;code&gt;LayoutContainer&lt;/code&gt; is now rewritten using built-in &lt;code&gt;react-redux&lt;/code&gt; hooks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Directory structure
&lt;/h2&gt;

&lt;p&gt;I'll level with you, one of the hardest steps in getting started with working on React + Redux for me is figuring out how to structure your project. There's really no &lt;em&gt;de facto&lt;/em&gt; way to do this, but it's still important to get this right so to not cause further distractions down the road. Here's how I normally do it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a dedicated &lt;code&gt;store/&lt;/code&gt; directory
&lt;/h3&gt;

&lt;p&gt;A lot of the guides/projects out there structure their store separately inside a root &lt;code&gt;actions/&lt;/code&gt; and &lt;code&gt;reducers/&lt;/code&gt; directory, to mimic the patterns in Redux architecture.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note that the following directory trees assume that your code is placed inside a &lt;code&gt;src/&lt;/code&gt; directory.)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
|-- actions
|   |-- chat.ts
|   |-- index.ts
|   `-- layout.ts
|-- components
|   |-- Footer.tsx
|   `-- Header.tsx
|-- containers
|   `-- ChatWindow.tsx
|-- reducers
|   |-- chat.ts
|   |-- index.ts
|   `-- layout.ts
|-- ...
|-- index.tsx
`-- types.d.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, I personally find this to be distracting. When your codebase grows larger, you would end up scattering code which shares the same context across a great length of the directory tree, which wouldn't be intuitive for newcomers who wanted to take a quick glance at your code. Therefore, roughly following the Redux pattern in this case is less advantageous in terms of code readability.&lt;/p&gt;

&lt;p&gt;So I decided to dedicate a &lt;code&gt;store/&lt;/code&gt; directory for all my Redux actions/reducers. This method is mostly borrowed from &lt;a href="https://hackernoon.com/redux-step-by-step-a-simple-and-robust-workflow-for-real-life-apps-1fdf7df46092"&gt;this guide&lt;/a&gt; made by Tal Kol of Wix, with a few adjustments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
|-- components
|   |-- Footer.tsx
|   `-- Header.tsx
|-- containers
|   `-- LayoutContainer.tsx
|-- pages
|   |-- index.tsx
|   |-- matches.tsx
|   `-- heroes.tsx
|-- store
|   |-- heroes
|   |   |-- actions.ts
|   |   |-- reducer.ts
|   |   `-- types.ts
|   |-- layout
|   |   |-- actions.ts
|   |   |-- reducer.ts
|   |   `-- types.ts
|   `-- index.ts
|-- ...
|-- index.tsx
`-- types.d.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Group stores by context
&lt;/h3&gt;

&lt;p&gt;As an extension to the guides above, the state tree should be structured &lt;strong&gt;by context&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
`- store
    |-- heroes // Handles application states inside the `/heroes` page.
    |   |-- actions.ts
    |   |-- reducer.ts
    |   `-- types.ts
    ├── layout // Handles global layout settings, e.g. theme, small/large text.
    |   |-- actions.ts
    |   |-- reducer.ts
    |   `-- types.ts
    `-- index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Combine reducers inside &lt;code&gt;store/index.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Include an &lt;code&gt;index.ts&lt;/code&gt; file at the root of the &lt;code&gt;store/&lt;/code&gt; directory. We'll use this to declare the top-level application state object type, as well as exporting our combined reducers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/store/index.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;combineReducers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AnyAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connectRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RouterState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connected-react-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LayoutState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layoutReducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// The top-level state object.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// `connected-react-router` already injects the router state typings for us,&lt;/span&gt;
&lt;span class="c1"&gt;// so we can ignore them here.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ApplicationState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LayoutState&lt;/span&gt;
  &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RouterState&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Whenever an action is dispatched, Redux will update each top-level application state property&lt;/span&gt;
&lt;span class="c1"&gt;// using the reducer with the matching name. It's important that the names match exactly, and that&lt;/span&gt;
&lt;span class="c1"&gt;// the reducer acts on the corresponding ApplicationState property type.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createRootReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;History&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;combineReducers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;layoutReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;connectRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;history&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;h2&gt;
  
  
  Store types
&lt;/h2&gt;

&lt;p&gt;Include a &lt;code&gt;types.ts&lt;/code&gt; file inside each store module. This is where we hold our state types, as well as any other types related to this Redux store module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/store/heroes/types.ts&lt;/span&gt;

&lt;span class="c1"&gt;// Response object for GET /heroes&lt;/span&gt;
&lt;span class="c1"&gt;// https://docs.opendota.com/#tag/heroes%2Fpaths%2F~1heroes%2Fget&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;localized_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;primary_attr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;attack_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="nx"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This type is basically shorthand for `{ [key: string]: any }`. Feel free to replace `any` with&lt;/span&gt;
&lt;span class="c1"&gt;// the expected return type of your API response.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ApiResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Use `enum`s for better autocompletion of action type names. These will&lt;/span&gt;
&lt;span class="c1"&gt;// be compiled away leaving only the final value in your compiled code.&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// Define however naming conventions you'd like for your action types, but&lt;/span&gt;
&lt;span class="c1"&gt;// personally, I use the `@@context/ACTION_TYPE` convention, to follow the convention&lt;/span&gt;
&lt;span class="c1"&gt;// of Redux's `@@INIT` action.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;FETCH_REQUEST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@heroes/FETCH_REQUEST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FETCH_SUCCESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@heroes/FETCH_SUCCESS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FETCH_ERROR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@heroes/FETCH_ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SELECTED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@@heroes/SELECTED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Declare state types with `readonly` modifier to get compile time immutability.&lt;/span&gt;
&lt;span class="c1"&gt;// https://github.com/piotrwitek/react-redux-typescript-guide#state-with-type-level-immutability&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;HeroesState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Typing actions
&lt;/h2&gt;

&lt;p&gt;Now that we have everything scaffolded, time to set up our actions!&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing typesafe actions with &lt;code&gt;typesafe-actions&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/piotrwitek"&gt;Piotrek Witek&lt;/a&gt; created the &lt;a href="https://github.com/piotrwitek/typesafe-actions"&gt;&lt;code&gt;typesafe-actions&lt;/code&gt;&lt;/a&gt; library, which provides useful helper functions to create type-safe Redux actions. We'll use this to write our Redux actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/store/heroes/actions.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typesafe-actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Here we use the `action` helper function provided by `typesafe-actions`.&lt;/span&gt;
&lt;span class="c1"&gt;// This library provides really useful helpers for writing Redux actions in a type-safe manner.&lt;/span&gt;
&lt;span class="c1"&gt;// For more info: https://github.com/piotrwitek/typesafe-actions&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FETCH_REQUEST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Remember, you can also pass parameters into an action creator. Make sure to&lt;/span&gt;
&lt;span class="c1"&gt;// type them properly as well.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FETCH_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FETCH_ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Typing reducers
&lt;/h2&gt;

&lt;p&gt;Typing reducers is a lot more straightforward with Redux 4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/store/heroes/reducer.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Reducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HeroesState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Type-safe initialState!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HeroesState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Thanks to Redux 4's much simpler typings, we can take away a lot of typings on the reducer side,&lt;/span&gt;
&lt;span class="c1"&gt;// everything will remain type-safe.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HeroesState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FETCH_REQUEST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FETCH_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FETCH_ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Instead of using default export, we use named exports. That way we can group these exports&lt;/span&gt;
&lt;span class="c1"&gt;// inside the `index.js` folder.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;heroesReducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling actions asynchronously with &lt;code&gt;redux-saga&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If your action dispatcher involves making numerous asynchronous tasks, it's better to include a library which handles side-effects on Redux. The two commonly-used libraries for this are &lt;a href="https://github.com/reduxjs/redux-thunk"&gt;redux-thunk&lt;/a&gt; and &lt;a href="https://redux-saga.js.org/"&gt;redux-saga&lt;/a&gt;. We're going to use &lt;code&gt;redux-saga&lt;/code&gt; due to its cleaner API, which makes use of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*"&gt;generator functions&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/store/heroes/sagas.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;takeEvery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-saga/effects&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchSuccess&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;callApi&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../utils/callApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;

&lt;span class="c1"&gt;// Here we use `redux-saga` to trigger actions asynchronously. `redux-saga` uses something called a&lt;/span&gt;
&lt;span class="c1"&gt;// "generator function", which you can read about here:&lt;/span&gt;
&lt;span class="c1"&gt;// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;handleFetch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// To call async functions, use redux-saga's `call()`.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callApi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;API_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/heroes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;An unknown error occured.&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This is our watcher function. We use `take*()` functions to watch Redux for a specific action&lt;/span&gt;
&lt;span class="c1"&gt;// type, and run our saga, for example the `handleFetch()` saga above.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;watchFetchRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;takeEvery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HeroesActionTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FETCH_REQUEST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleFetch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Export our root saga.&lt;/span&gt;
&lt;span class="c1"&gt;// We can also use `fork()` here to split our saga into multiple watchers.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;heroesSaga&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;watchFetchRequest&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;To include them in our root store, we add a &lt;code&gt;rootSaga()&lt;/code&gt; generator function which collects all of our store sagas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/store/index.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-saga/effects&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// We `fork()` these tasks so they execute in the background.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rootSaga&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heroesSaga&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;teamsSaga&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// `fork()` any other store sagas down here...&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;h2&gt;
  
  
  Initialising Redux store
&lt;/h2&gt;

&lt;p&gt;Initialising the Redux store should be done inside a &lt;code&gt;configureStore()&lt;/code&gt; function. Inside this function, we bootstrap the required middlewares (including &lt;code&gt;redux-saga&lt;/code&gt;) and combine them with our reducers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/configureStore.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;applyMiddleware&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;createSagaMiddleware&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-saga&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// `react-router-redux` is deprecated, so we use `connected-react-router`.&lt;/span&gt;
&lt;span class="c1"&gt;// This provides a Redux middleware which connects to our `react-router` instance.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connectRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;routerMiddleware&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connected-react-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// We'll be using Redux Devtools. We can use the `composeWithDevTools()`&lt;/span&gt;
&lt;span class="c1"&gt;// directive so we can pass our middleware along with it&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;composeWithDevTools&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux-devtools-extension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// If you use react-router, don't forget to pass in your history type.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;History&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;history&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Import the state interface and our combined reducers/sagas.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApplicationState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createRootReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rootSaga&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;History&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApplicationState&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApplicationState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// create the composing function for our middlewares&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;composeEnhancers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;composeWithDevTools&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
  &lt;span class="c1"&gt;// create the redux-saga middleware&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sagaMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createSagaMiddleware&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// We'll create our store with the combined reducers/sagas, and the initial Redux state that&lt;/span&gt;
  &lt;span class="c1"&gt;// we'll be passing from our entry point.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;createRootReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;composeEnhancers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;applyMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;sagaMiddleware&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Don't forget to run the root saga, and return the store object.&lt;/span&gt;
  &lt;span class="nx"&gt;sagaMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootSaga&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Connecting with React
&lt;/h2&gt;

&lt;p&gt;Now let's hook everything up with React.&lt;/p&gt;

&lt;h3&gt;
  
  
  Container components
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; The latest version of &lt;code&gt;react-redux&lt;/code&gt; broke the typings for the"children-props-as-redux-container" approach I mentioned in the previous version of this post. I would suggest against using this pattern nowadays, but if you still want to use it, here's a way to upgrade, using the brand-new &lt;code&gt;useDispatch&lt;/code&gt; and &lt;code&gt;useSelector&lt;/code&gt; hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/containers/LayoutContainer&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApplicationState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThemeColors&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../store/layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;layoutActions&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../store/layout/actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Redux-specific props.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LayoutContainerProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ThemeColors&lt;/span&gt;
  &lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ThemeColors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Wrapper props for render/children callback.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LayoutContainerRenderProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;render&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LayoutContainerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactElement&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LayoutContainerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactElement&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LayoutContainer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LayoutContainerRenderProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We can use Hooks to call in our selector/dispatch functions.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApplicationState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Create the `setTheme` handler. We use the `dispatch` we got from `useDispatch()` to create said selector.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ThemeColors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;layoutActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="c1"&gt;// Create a render/children props wrapper with the above variables set as a callback.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;LayoutContainer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, we can use the Redux store linking from any component!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/components/layouts/Header.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;LayoutContainer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../containers/LayoutContainer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SFC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LayoutContainer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CurrentTheme&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Current theme: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CurrentTheme&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&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="s1"&gt;dark&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="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Switch theme&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;LayoutContainer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Page components
&lt;/h3&gt;

&lt;p&gt;When connecting pure React components, it's a good idea to connect them at the page level. As a reminder, when mapping states/action dispatcher to a component, we need to combine the state/action dispatcher prop types of the store we're mapping to our component prop types as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Separate state props + dispatch props to their own interfaces.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PropsFromState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// We can use `typeof` here to map our dispatch types to the props, like so.&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PropsFromDispatch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;fetchRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;heroesActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchRequest&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Combine both state + dispatch props - as well as any props we want to pass - in a union type.&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AllProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PropsFromState&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;PropsFromDispatch&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ConnectedReduxProps&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;HeroesIndexPage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AllProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TableWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LoadingOverlay&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TableWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;renderData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HeroesTable&lt;/span&gt; &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&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="s1"&gt;Legs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;widths&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&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="s1"&gt;120px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HeroLoading&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;colSpan&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;HeroLoading&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HeroDetail&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HeroIcon&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;API_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HeroName&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/heroes/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localized_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;HeroName&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;HeroDetail&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;legs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;HeroesTable&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&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;h3&gt;
  
  
  Using &lt;code&gt;react-redux&lt;/code&gt;'s &lt;code&gt;connect()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;react-redux&lt;/code&gt; &lt;code&gt;connect()&lt;/code&gt; function is what connects our React component to the redux store.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/pages/heroes.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Dispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApplicationState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="c1"&gt;// It's usually good practice to only include one context at a time in a connected component.&lt;/span&gt;
&lt;span class="c1"&gt;// Although if necessary, you can always include multiple contexts. Just make sure to&lt;/span&gt;
&lt;span class="c1"&gt;// separate them from each other to prevent prop conflicts.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapStateToProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;heroes&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ApplicationState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;heroes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;heroes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;heroes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// mapDispatchToProps is especially useful for constraining our actions to the connected component.&lt;/span&gt;
&lt;span class="c1"&gt;// You can access these via `this.props`.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapDispatchToProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;fetchRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heroesActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchRequest&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Now let's connect our component!&lt;/span&gt;
&lt;span class="c1"&gt;// With redux v4's improved typings, we can finally omit generics here.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;mapStateToProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;mapDispatchToProps&lt;/span&gt;
&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;HeroesPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Additional helper type
&lt;/h2&gt;

&lt;p&gt;We can also add a helper type for our connected Redux components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Additional props for connected React components. This prop is passed by default with `connect()`&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ConnectedReduxProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AnyAction&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Correct types for the `dispatch` prop passed by `react-redux`.&lt;/span&gt;
  &lt;span class="c1"&gt;// Additional type information is given through generics.&lt;/span&gt;
  &lt;span class="na"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Dispatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now on any Redux-connected component, we can extend its props interface with the interface above&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Extend the interface (for example).&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComponentProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ConnectedReduxStore&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We can use the extended interface above as follows.&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;layoutActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchRequest&lt;/span&gt;&lt;span class="p"&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;h2&gt;
  
  
  Sample code
&lt;/h2&gt;

&lt;p&gt;Hope you've found this guide useful! Based on your feedback as well, I've also published a sample project following the guides above on GitHub. Click &lt;a href="https://github.com/resir014/react-redux-typescript-example"&gt;here&lt;/a&gt; to go there.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;To learn more about React, Redux, and TypeScript, the following guides are a good read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/sw-yx/react-typescript-cheatsheet"&gt;React + TypeScript cheatsheet&lt;/a&gt; by &lt;a href="https://github.com/sw-yx"&gt;@sw-yx&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/piotrwitek/react-redux-typescript-guide"&gt;React &amp;amp; Redux in TypeScript&lt;/a&gt; by &lt;a href="https://github.com/piotrwitek"&gt;@piotrwitek&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
