<?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: Asjad Anis</title>
    <description>The latest articles on Forem by Asjad Anis (@asjadanis).</description>
    <link>https://forem.com/asjadanis</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%2F314332%2Fc2928c62-aa40-4e22-8bba-22178413f84d.jpg</url>
      <title>Forem: Asjad Anis</title>
      <link>https://forem.com/asjadanis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/asjadanis"/>
    <language>en</language>
    <item>
      <title>Retrieval Augmented Generation 101</title>
      <dc:creator>Asjad Anis</dc:creator>
      <pubDate>Fri, 01 Sep 2023 00:37:43 +0000</pubDate>
      <link>https://forem.com/asjadanis/retrieval-augmented-generation-101-1p1o</link>
      <guid>https://forem.com/asjadanis/retrieval-augmented-generation-101-1p1o</guid>
      <description>&lt;p&gt;I recently came across RAG (Retrieval Augmented Generation), at first it looked like a very fancy tech jargon but after learning more about it I found it to be a very interesting and clever technique to supplement an LLM in order to perform well on your custom data without hallucinating and going through the process of fine-tuning the model. &lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Hallucination
&lt;/h2&gt;

&lt;p&gt;Hallucination is a behavior exhibited by Large Language Models where the model generates a response that is incorrect and the model makes up that information. You might have observed this with chat-gpt when asking for very specific details about some library it might end up making up documentation and GitHub links for specific ways of doing things that are not supported by the library. For instance, I was searching on Google on how to extend the express request object type in typescript and it told me about some made-up &lt;code&gt;extend&lt;/code&gt; method that it didn't even use&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1694857443665125885-554" src="https://platform.twitter.com/embed/Tweet.html?id=1694857443665125885"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1694857443665125885-554');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1694857443665125885&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  How To Avoid Hallucination
&lt;/h2&gt;

&lt;p&gt;There are a couple of techniques to prevent hallucinations when dealing with LLMs, we will be looking into two specific techniques for the sake of this post. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fine Tuning&lt;/li&gt;
&lt;li&gt;Retrieval Augmented Generation (RAG)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Fine Tuning
&lt;/h2&gt;

&lt;p&gt;When fine-tuning the model you basically use the pre-trained model and then re-train additional layers or the last layers at the end of the model on the target data, keeping the model's pre-trained weights so the model's general understanding could be fine-tuned to the custom data set. However, this is computationally more expensive, time-consuming, and requires more expertise in the field of ML.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps Involved In Fine Tuning
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Select a pre-trained model&lt;/li&gt;
&lt;li&gt;Prepare your custom data&lt;/li&gt;
&lt;li&gt;Tune hyperparameters&lt;/li&gt;
&lt;li&gt;Fine-tune model using transfer learning&lt;/li&gt;
&lt;li&gt;Evaluate the model&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  RAG Approach
&lt;/h2&gt;

&lt;p&gt;RAG takes a different approach to augment the generative model output by supplementing the process with a retrieval system, since LLMs are already trained on a huge corpus of text they already have a very well understanding of the contextual and semantic meaning of the words, what they lack is the additional information from a custom knowledge base in order to come up with an educated response.&lt;/p&gt;

&lt;p&gt;This is where RAG comes in and augments the LLM to prevent hallucinations by providing it with essential information in order to answer the query. Instead of passing the user query directly to the LLM it first goes through a retrieval system to fetch the relevant documents based on the user query which are then augmented on top of the user’s prompt and passed to the LLM, This makes it much more dynamic and flexible to provide external information to the model that it wasn’t aware of before in order to produce a much better response.&lt;/p&gt;

&lt;p&gt;This approach also has the benefit of updating your repository of documents without having to retrain the entire model as in the case of fine tuning. You can also employ modern semantic search techniques and Vector DB to augment the retrieval system to get the best results from your knowledge base that can then be passed to the LLM. You can see the high-level overview of a RAG system in the below diagram&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HErK1bPO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdml9y83bjbkrz11y0o7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HErK1bPO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdml9y83bjbkrz11y0o7.png" alt="RAG Flow Diagram" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any questions or feedback, feel free to reach out!&lt;/p&gt;

&lt;p&gt;Connect with me on &lt;a href="https://twitter.com/asjadanis"&gt;Twitter&lt;/a&gt;, &lt;a href="https://github.com/asjadanis"&gt;Github&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/in/asjad-anis/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>llm</category>
      <category>nlp</category>
    </item>
    <item>
      <title>Optimizing React App Performance</title>
      <dc:creator>Asjad Anis</dc:creator>
      <pubDate>Tue, 28 Sep 2021 12:39:06 +0000</pubDate>
      <link>https://forem.com/asjadanis/optimizing-react-app-performance-16lp</link>
      <guid>https://forem.com/asjadanis/optimizing-react-app-performance-16lp</guid>
      <description>&lt;h3&gt;
  
  
  Quick Summary
&lt;/h3&gt;

&lt;p&gt;This article aims to explain how to write efficient and performant React components along with some common profiling techniques at our disposal that we can use to figure out unoptimized rendering behaviors in our app and improve the performance.&lt;/p&gt;




&lt;h3&gt;
  
  
  Audience
&lt;/h3&gt;

&lt;p&gt;The targeted audience for this article is mid-senior level React engineers who are well familiar with the library and have a good understanding of how the library works especially the Virtual DOM, Reconciliation, and how the library renders and updates the actual DOM.&lt;/p&gt;




&lt;p&gt;React is a great library that allows you to write applications declaratively, this approach is great because it abstracts away all the functional and internal details on how the library achieves a specific UI state and ensures to keep the DOM in sync with the state you describe. This is achieved by keeping a Virtual DOM and the process of reconciliation. Let's look at these two terms in order to understand them properly&lt;/p&gt;

&lt;h3&gt;
  
  
  Virtual DOM and Reconciliation
&lt;/h3&gt;

&lt;p&gt;The Virtual DOM as the word itself suggests is basically a virtual representation of the UI, you can think of it as a blueprint that contains all the necessary details required to construct an actual DOM. React relies on the Virtual DOM to efficiently render only the components that have been updated. Any interaction with the application that is associated with some state will likely cause the application to trigger a re-render, but React does this part efficiently by only updating the Virtual DOM first instead of the actual DOM and then applying a comparison algorithm on the new and old Virtual DOM's to detect if an actual DOM update is required. &lt;br&gt;
This diffing algorithm is basically what enables React to determine what DOM elements or attributes to update and makes it efficient. &lt;/p&gt;

&lt;p&gt;You can read more about the diffing algorithm on the official &lt;a href="https://reactjs.org/docs/reconciliation.html" rel="noopener noreferrer"&gt;React docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of the main reasons for performance issues in a React app is some faulty implementation on our end or unnecessary re-rendering especially when its resource-intensive and doing some expensive calculations that causes repeated triggering of this diffing and rendering cycle and triggering updates to the actual DOM which can result in a performance hit and a slow experience.&lt;/p&gt;

&lt;p&gt;In order to achieve good performance on our application, we need to ensure that React is only updating the components that are affected by the state change and ideally ignore all other components, this will result in saving up the wasted CPU cycles and resources that went in for re-rendering the unaffected components and give us a performance boost in our application.&lt;/p&gt;

&lt;p&gt;Optimizing a React application without profiling or benchmarking won't do us much good as there is a cost associated with the optimization techniques and if not done correctly the performance gains might not be worth the complexity introduced in the codebase and could potentially affect the performance.&lt;/p&gt;

&lt;p&gt;Let's get started with a very simple application that I have created and profile it along the way to see if the optimizations are doing us any good&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// Clone the repo and switch to profiling branch

git clone https://github.com/asjadanis/react-performance-tutorial
git checkout profiling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install node modules by running yarn and then start the application by running yarn start you should see something like below in your browser.&lt;/p&gt;

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

&lt;p&gt;Now open up the browser console and play with the application add some books, courses and if you see some odd rendering behavior great, if you can't figure it out I'll break it down for you when you add a book you will notice that the courses list gets rendered too and vice versa. This is sub-optimal and not the desired behavior and we will be optimizing our components to ensure that only those components get rendered that are affected by the state change. Before we dive into profiling let us quickly go through the code so we know what we are dealing with.&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;// App.js&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;useState&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="s2"&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="nx"&gt;List&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./List&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./styles.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBooks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;courses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCourses&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;onAddBook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="nx"&gt;updatedItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`book-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;books&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;1&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="nf"&gt;setBooks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedItems&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="nx"&gt;onAddCourse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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="nx"&gt;updatedItems&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="nx"&gt;courses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`course-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;courses&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;1&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="nf"&gt;setCourses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedItems&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;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;"App"&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;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Books &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&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;List&lt;/span&gt; &lt;span class="na"&gt;onAddItem&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onAddBook&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;listKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"books"&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;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;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Courses &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&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;List&lt;/span&gt; &lt;span class="na"&gt;onAddItem&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onAddCourse&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;courses&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;listKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"courses"&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;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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AddItem.js&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;useState&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&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;AddItem&lt;/span&gt; &lt;span class="o"&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="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;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&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;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="nx"&gt;addItem&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;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;item&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onAddItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&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;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="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&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;placeholder&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;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;addItem&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Add &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;/&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;AddItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AddItem&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./AddItem&lt;/span&gt;&lt;span class="dl"&gt;"&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;List&lt;/span&gt; &lt;span class="o"&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="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;items&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;List rendered: &lt;/span&gt;&lt;span class="dl"&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;listKey&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;AddItem&lt;/span&gt; &lt;span class="na"&gt;onAddItem&lt;/span&gt;&lt;span class="p"&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;onAddItem&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Add book"&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&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;item&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;return&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="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;item&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&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;li&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;ul&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our app is composed of three components first up is &lt;code&gt;App.js&lt;/code&gt; that is our main component it contains the logic for adding books and courses and it passes down the handlers and books/courses states as props to the &lt;code&gt;List&lt;/code&gt; component.&lt;br&gt;
The &lt;code&gt;List&lt;/code&gt; component provides input control to add books or courses using the &lt;code&gt;AddItem&lt;/code&gt; component and maps over the list of books and courses to render them.&lt;/p&gt;

&lt;p&gt;That's pretty straightforward, every time we add a book or a course we are updating the state in our &lt;code&gt;App.js&lt;/code&gt; component causing it to render and its children. So far so good now we can jump straight into our IDE and fix this behavior but in this article, we are going to take a step back and first profile our application to see what's happening. &lt;/p&gt;

&lt;p&gt;I pre-configured the repo with a nice package &lt;a href="https://github.com/welldone-software/why-did-you-render" rel="noopener noreferrer"&gt;why-did-you-render&lt;/a&gt; which basically enables you to see any avoidable re-renders in your application during the development mode.&lt;/p&gt;

&lt;p&gt;You can check out the package docs to see how you can configure it with your setup.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Don't use this package in your production build, this should only be used in the development mode and should be in your devDependencies.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Profiling
&lt;/h3&gt;

&lt;p&gt;First of all, you need to set up the &lt;a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en" rel="noopener noreferrer"&gt;React Developer Tools&lt;/a&gt; which is available as a browser extension and allows us to profile our React applications. You'll need to set it up for your browser in order to follow along with the profiling section, once you have it set up head over to the application on &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3000/&lt;/code&gt;&lt;/a&gt; and open developer tools.&lt;/p&gt;

&lt;p&gt;Now head over to the profiler tab and you should be able to see something like the below screenshot in your dev-tools&lt;/p&gt;

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

&lt;p&gt;In order to profile our application for performance hits and see how rendering is happening we need to record our application while using it, let's do that. Hit the record button and then interact with the application add some books and courses and then stop recording. You should be able to see a flame graph of your app components and how long each component took to render out of the total render duration. The greyed-out components indicate that they did not render during that commit.&lt;/p&gt;

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

&lt;p&gt;From here onwards you can step through the various commits in the graph and take notes of which components are taking the most time to render and if there are any wasted renders. The bars peak is a quick visual indicator for which commit took the most time to render and then you can click on it to further see each of the components that caused it. In our case, we can see a yellow peak followed by a couple of green peaks which indicate the rendering happening when we add a book or course.&lt;/p&gt;

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

&lt;p&gt;Here we can see that our App component is rendering which makes sense as we are updating the state. Rendering both lists is although unoptimized as we can only update one list at a given time and we only want the respective list to render but in our case, both lists are re-rendering along with the AddItem component they compose of. Now that we have a clear picture of what's happening let's fix this behavior by wrapping our List component in React.memo which is a higher-order component that enables React to skip rendering for a specific component given the new props are the same as old props. Note that React.memo only compares props so if your wrapped component includes internal state, updating that will still cause the component to re-render which is desired.&lt;/p&gt;
&lt;h3&gt;
  
  
  Optimizing the Components
&lt;/h3&gt;

&lt;p&gt;In order to fix this behavior head over to the &lt;code&gt;List&lt;/code&gt; component and import &lt;code&gt;memo&lt;/code&gt; from React and wrap the default export with &lt;code&gt;memo&lt;/code&gt;&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;// List.js&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;memo&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&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;List&lt;/span&gt; &lt;span class="o"&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="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="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="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks good now let's give it a try keep your browser console open and add a book to the list you should notice that even after wrapping our component in React.memo both our lists are still rendering sound strange right? You should also notice some additional console logs telling us why the List component re-rendered as below&lt;/p&gt;

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

&lt;p&gt;These console logs are coming from the &lt;a href="https://github.com/welldone-software/why-did-you-render" rel="noopener noreferrer"&gt;why-did-you-render&lt;/a&gt; package that we talked about earlier which enables us to see any avoidable re-renders in our React app. Here it's telling us that the component re-rendered because of props changes and specifically the &lt;code&gt;onAddItem&lt;/code&gt; function. This is happening because of the referential equality in JavaScript, every time our &lt;code&gt;App&lt;/code&gt; component renders it will create new functions for our handlers and the referential equality will fail as both functions won't be pointing to the same address in memory this is just how JavaScript works. You should read more about referential equality in JavaScript in order to get a good grasp of this concept. &lt;/p&gt;

&lt;p&gt;To fix this behavior in React what we can do is wrap our handlers in a &lt;a href="https://reactjs.org/docs/hooks-reference.html#usecallback" rel="noopener noreferrer"&gt;useCallback&lt;/a&gt; hook which basically returns a memoized version of our handlers and it will change only if one of the provided dependencies changes. This will ensure that the new instance of our functions are not created and will prevent the re-rendering. Note here that &lt;a href="https://en.wikipedia.org/wiki/Memoization" rel="noopener noreferrer"&gt;memoization&lt;/a&gt; is not something specific to React but a general optimization technique used in programming to store results of expensive computations and return cached results when already computed.&lt;/p&gt;

&lt;p&gt;Let's wrap our handlers in a &lt;code&gt;useCallback&lt;/code&gt;&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCallback&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&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;onAddBook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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="nf"&gt;setBooks&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;books&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;books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`book-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;books&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;1&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onAddCourse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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="nf"&gt;setCourses&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;courses&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;...&lt;/span&gt;&lt;span class="nx"&gt;courses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`course-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;courses&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;1&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;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are passing an empty dependency list as we don't want our handlers to be re-initialized on every render but if required you can add the dependencies there, Let's run the application now and see how it behaves, if you add any book or a course now you will immediately notice that only the respective list gets re-rendered which is great but let's also profile it to see if we have gained any significant performance boost although our sample application is very simple and straight forward but if it were to be a bit complex consider each list item had a children array on it which can be further listed down and included some logic that was resource intensive and so on you can imagine in such a scenario the re-rendering would definitely be a problem. Below are the results after profiling you can give it a try yourself too.&lt;/p&gt;

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

&lt;p&gt;We can see above that after memoization the total render duration for the highest peak in our flame-graph took about &lt;strong&gt;2.8ms&lt;/strong&gt; compared to &lt;strong&gt;7.3ms&lt;/strong&gt; before and our second &lt;code&gt;List&lt;/code&gt; component did not render, this sounds great we have successfully saved around &lt;strong&gt;4.5ms&lt;/strong&gt; wasted in rendering time by putting in about 15-20 mins debugging, profiling, optimizing and the performance benefits in our case don't make any visual difference as the app is quite simple and doesn't take a lot of resources in re-rendering, but this doesn't mean we did this all for nothing the purpose was to understand the behavior and reasoning behind re-rendering and objectively approaching at optimizing the application instead of randomly wrapping everything in &lt;code&gt;React.memo&lt;/code&gt; and &lt;code&gt;React.useCallback&lt;/code&gt;. Now we have developed a basic mental model that we can use when approaching performance-related issues in a React app.&lt;/p&gt;

&lt;p&gt;Another thing to keep in mind here is that React is smart enough to determine which DOM nodes to actually update, in our example above even though our List component is unnecessarily re-rendering React isn't triggering actual DOM updates unless necessary you can verify this is in your browser dev-tools and since React is taking care of the more expensive part i.e DOM updates in our simple example above we probably don't even need to optimize our components. Such optimizations are more fruitful when our components are expensive to render or include some expensive calculations during the rendering phase that is just wasting CPU cycles and is not required.&lt;/p&gt;

&lt;h3&gt;
  
  
  General Guidelines
&lt;/h3&gt;

&lt;p&gt;Keep the below points in mind when using &lt;code&gt;React.memo&lt;/code&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React.memo does &lt;a href="https://github.com/facebook/react/blob/v16.8.6/packages/shared/shallowEqual.js" rel="noopener noreferrer"&gt;shallow&lt;/a&gt; comparison of props by default&lt;/li&gt;
&lt;li&gt;You can pass in a custom function as a second argument to &lt;code&gt;React.memo&lt;/code&gt; adding your custom logic to compare props.&lt;/li&gt;
&lt;li&gt;If you need to do a deep comparison of props then keep in mind that it comes with additional cost depending on the complexity of your props.&lt;/li&gt;
&lt;li&gt;It makes sense to use &lt;code&gt;React.memo&lt;/code&gt; when your component renders the same thing when it's given the same props or if it's computationally expensive to render unlike our list component above.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are working with React class components you can use &lt;code&gt;shouldComponentUpdate&lt;/code&gt; life-cycle method or &lt;code&gt;React.PureComponent&lt;/code&gt; to achieve the same behavior but make sure you aid it with profiling.&lt;/p&gt;

&lt;p&gt;You can use the &lt;a href="https://reactjs.org/docs/hooks-reference.html#usememo" rel="noopener noreferrer"&gt;useMemo&lt;/a&gt; hook to memoize any computationally expensive calculations on every render, make sure to provide a dependency array in case the memoized value is dependent on some other fields and needs to be recalculated if any of those fields is changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The objective of this blog was to build a mental model when approaching optimization problems in React applications and emphasize on profiling techniques to objectively achieve it. Optimization techniques come with a cost if not used properly and wrapping everything in &lt;code&gt;memo&lt;/code&gt; or &lt;code&gt;useCallback&lt;/code&gt; won't magically make your apps fast, but using them properly and profiling along the way could definitely be a lifesaver.&lt;br&gt;
As always feel free to share your thoughts with me in the comment section or connect with me on &lt;a href="https://twitter.com/asjadanis" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>webperf</category>
    </item>
    <item>
      <title>TypeScript: Custom Type Guards</title>
      <dc:creator>Asjad Anis</dc:creator>
      <pubDate>Tue, 07 Sep 2021 08:46:50 +0000</pubDate>
      <link>https://forem.com/asjadanis/typescript-custom-type-guards-4jel</link>
      <guid>https://forem.com/asjadanis/typescript-custom-type-guards-4jel</guid>
      <description>&lt;p&gt;Did TypeScript ever annoy you with the error &lt;code&gt;Object is possibly undefined&lt;/code&gt; even if you filter out all the &lt;code&gt;undefined&lt;/code&gt; values, if yes then this post is for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Setup
&lt;/h3&gt;

&lt;p&gt;Let's quickly setup a very basic example to see how we can get to such a situation.&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;Item&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;string&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;description&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Item&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bla bla bla&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item-2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yada yada yada&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item-3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bla bla bla&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yada yada yada&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;itemIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&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="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="dl"&gt;"&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;getItems&lt;/span&gt; &lt;span class="o"&gt;=&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Item&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;=&amp;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;myItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;itemIds&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;getItems&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;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example we have an array of &lt;code&gt;Items&lt;/code&gt; and list of &lt;code&gt;itemIds&lt;/code&gt; , and we are trying to get the metadata of the &lt;code&gt;itemId&lt;/code&gt; . When you run this code and hover over &lt;code&gt;items&lt;/code&gt; , TypeScript will tell you that the variable &lt;code&gt;items&lt;/code&gt; is of type &lt;code&gt;(Item | undefined)[]&lt;/code&gt; which makes sense as some id's won't match and return undefined so far so good, now the undefined items in the array are of no use to us and we don't want to deal with the undefined errors when further referring the &lt;code&gt;items&lt;/code&gt; variable in our codebase, so lets quickly fix this by filtering out all the undefined values.&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;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;itemIds&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;getItems&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;item&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;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// No undefined values in items&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great now we can easily loop over the items array and process it without having to deal with undefined values, let's quickly try it.&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;const&lt;/span&gt; &lt;span class="nx"&gt;processItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Item&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;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;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&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;toUpperCase&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;processedItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&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;item&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;return&lt;/span&gt; &lt;span class="nx"&gt;processItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Argument of type 'Item | undefined' is not assignable to parameter of type 'Item'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait but why? we already handled this above, let's hover over &lt;code&gt;items&lt;/code&gt; and see it's type&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;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)[]&lt;/span&gt; &lt;span class="c1"&gt;// Wait whaaat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that the &lt;code&gt;.filter&lt;/code&gt; method will always return an array of the type with which you initially started so in our case it was &lt;code&gt;Item | undefined&lt;/code&gt; which makes sense now but how do we fix this 🤔&lt;/p&gt;

&lt;h3&gt;
  
  
  Type Guards to the Rescue
&lt;/h3&gt;

&lt;p&gt;This is where TypeScript &lt;strong&gt;custom type guards&lt;/strong&gt; come to rescue, a custom type guard is basically a function that's return type is a &lt;strong&gt;type predicate&lt;/strong&gt;. It's a very simple and intuitive approach for fixing the above problem properly, let's see it in action.&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;// Our type-guard&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Item&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;return&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&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;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;itemIds&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;getItems&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//items: Item[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's how you can filter out the undefined values properly in TypeScript with type guards and keeping the types intact in your codebase. This same approach can be extended to a use-case where you are dealing with a Union type and you want to make sure you are accessing the right properties of the instance of that type.&lt;/p&gt;

&lt;p&gt;As always do share your thoughts on this approach in the comments below and feel free to connect with me on &lt;a href="https://twitter.com/asjadanis"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Essential JavaScript Tooling</title>
      <dc:creator>Asjad Anis</dc:creator>
      <pubDate>Fri, 03 Sep 2021 21:45:30 +0000</pubDate>
      <link>https://forem.com/asjadanis/essential-javascript-tooling-139a</link>
      <guid>https://forem.com/asjadanis/essential-javascript-tooling-139a</guid>
      <description>&lt;h3&gt;
  
  
  Quick Summary
&lt;/h3&gt;

&lt;p&gt;Software development is great and fun but it can be a mess and a very bad influence if the developer experience is not given the importance and prioritized. Some standard development practices along with proper tooling can greatly improve this experience. This also aids in keeping the codebase clean and the repository in a good health. In this article, we will cover some development practices and essential tools to help you improve the development experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Audience
&lt;/h3&gt;

&lt;p&gt;This article is essentially for JS developers and covers tooling around the JS ecosystem, however, the same concepts can be applied in other languages with the tooling available there. We will cover the below topics in this article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code Linting using &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Code Formatting using &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Setting up &lt;a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" rel="noopener noreferrer"&gt;Git Hooks&lt;/a&gt; for linting and code-formatting.&lt;/li&gt;
&lt;li&gt;Conventional Commits using &lt;a href="https://github.com/commitizen/cz-cli" rel="noopener noreferrer"&gt;Commitizen&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;Github Actions&lt;/a&gt; for CI/CD&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Code-Linting
&lt;/h3&gt;

&lt;p&gt;Code linting is very essential and important especially when you are working with an interpreted language like JavaScript. Linters are essentially static code analyzers it scans through your code without running it and flags any programmatic errors, stylistic errors, and any suspicious contracts. Properly setting up a linter in your codebase can help catch errors early on and ensure that some standard practices are being followed. This makes the codebase clean and helps in code reviews.&lt;/p&gt;

&lt;p&gt;Linters can enforce code styling and rules like no unused variables or no console.log statements or no unused imports in fact it's a very powerful tool and can do much more than that.&lt;/p&gt;

&lt;p&gt;Setting up Linters can be tedious and tiring but it brings great results once you adopt it and start using it properly in your team. I personally believe that linters and such tools should come with the language itself and developers shouldn't have to worry about setting one up. This experience is much more improved with &lt;a href="https://deno.land/" rel="noopener noreferrer"&gt;deno&lt;/a&gt; (A secure runtime for JavaScript and TypeScript) which ships with a built-in linter and formatter for JavaScript and TypeScript.  &lt;/p&gt;

&lt;p&gt;Now that we have a basic understanding of linters let's see how we can set one up in a TypeScript project. We will be using ESLint which is very popular in the JS ecosystem and is fully pluggable. Every single rule in ESLint is a plugin, this means you can start off with a base configuration and then extend the rules to your needs by adding in more rules as a plugin.&lt;/p&gt;

&lt;p&gt;Create a new folder and run &lt;code&gt;npm init -y&lt;/code&gt; to initialize your project, this will create a &lt;code&gt;package.json&lt;/code&gt; in the root directory with some stub fields.&lt;/p&gt;

&lt;p&gt;Next, install the required &lt;code&gt;dev-dependencies&lt;/code&gt; into the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; nodemon ts-node eslint typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's first quickly setup TypeScript by running &lt;code&gt;tsc --init&lt;/code&gt; which will initialize the &lt;code&gt;tsconfig.json&lt;/code&gt; file in the project root, the only thing we are going to change is uncommenting &lt;code&gt;outdir&lt;/code&gt; option and change it to &lt;code&gt;dist&lt;/code&gt;&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="s2"&gt;"outDir"&lt;/span&gt;: &lt;span class="s2"&gt;"dist"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add a &lt;code&gt;.eslintrc&lt;/code&gt; file in the project's root directory. This is going to be the configuration file for &lt;code&gt;eslint&lt;/code&gt; where we can customize our rules. To quickly get started let's add a bare minimum configuration to the 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;"root"&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;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@typescript-eslint/parser"&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="s2"&gt;"@typescript-eslint"&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="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/recommended"&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;Let's look at some of these options briefly, the &lt;code&gt;root&lt;/code&gt; key basically tells eslint to stop looking for configuration files in the parent directories. By default, eslint looks for config files in all parent folders until the root directory which can lead to unexpected results, plus this option can be very handy when you have a monorepo in place and each project uses a different configuration.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;extends&lt;/code&gt; key lets you add the configuration you want to use for your project this can be a string that specifies a configuration or a path to a configuration file, here we are using two configurations first one is the &lt;a href="https://eslint.org/docs/rules/" rel="noopener noreferrer"&gt;eslint-recommended&lt;/a&gt;, and the next up is typescript-eslint recommended. You can also use &lt;a href="https://www.npmjs.com/package/eslint-config-airbnb-typescript" rel="noopener noreferrer"&gt;airbnb-typescript&lt;/a&gt; config which is also very popular.&lt;/p&gt;

&lt;p&gt;Now let's add some scripts in our &lt;code&gt;package.json&lt;/code&gt; to run our project in dev mode and a script for linting.&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="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodemon --watch '**/*.ts' --exec 'ts-node' src/index.ts"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint . --ext .ts"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for the sake of testing our eslint setup let's create an &lt;code&gt;index.ts&lt;/code&gt; file and very simple for loop with an intended unused variable.&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/index.ts&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i : &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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 let's run &lt;code&gt;yarn lint&lt;/code&gt; and we will get a warning on our console.&lt;/p&gt;

&lt;p&gt;This is great our eslint setup is working, but let's say we want to be more strict on our code base and want this to be an error and cause lint to fail, to do that head over to your &lt;code&gt;.eslintrc&lt;/code&gt; file and add the below rule.&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;"root"&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;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@typescript-eslint/parser"&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="s2"&gt;"@typescript-eslint"&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="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/recommended"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&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;"no-unused-vars"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"warn"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&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;Now if you run &lt;code&gt;yarn lint&lt;/code&gt; your console will display this as an error and lint won't succeed, also if you have the eslint extension installed on vs code it will highlight this issue.&lt;/p&gt;

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

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

&lt;p&gt;We can also add another script to auto-fix the lint issues, note that not all issues can be auto-fixed and you can get a list of all the rules that can be auto-fixed &lt;a href="https://eslint.org/docs/rules/" rel="noopener noreferrer"&gt;here&lt;/a&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="nl"&gt;"lint-fix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint . --ext .ts --fix"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's pretty much for the linting setup, I hope you can now create a mental model for yourself and see how useful this tool can be if used properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Formatting
&lt;/h3&gt;

&lt;p&gt;Let's accept it, seeing different code styles in a repo is a mess and if not controlled you can see all sorts of code conventions being followed in the repo. This is where code formatters come to our rescue, but before we jump into setting one up in our project we first need to understand that code formatters and linters are essentially not the same things, although there is a very thin line between them but they both serve a different purpose. Code-formatters essentially deal with the formatting of code and apply the code styling you have specified, they don't check code for potential bugs or issues and adhere to the styling. &lt;/p&gt;

&lt;p&gt;Prettier is a very famous tool in the JS ecosystem and we will be setting it up in our project, with prettier we can enforce style rules like max-length, tab width, single-quotes, semicolon, etc. It's basically an opinionated code formatter that takes your code and parses it into an AST (Abstract Syntax Tree) discarding the original styling, after that it just pretty prints the AST with the code-styling you have specified.&lt;/p&gt;

&lt;p&gt;Let get started, first we need to install the dev dependencies&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; prettier eslint-config-prettier eslint-plugin-prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's quickly explain the above dev-dependencies and what purpose do they serve.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;prettier&lt;/code&gt;: opinionated code-formatter.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-config-prettier&lt;/code&gt;: used to disable all eslint rules that might conflict with prettier.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-prettier&lt;/code&gt;: runs prettier as an eslint rule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now create a &lt;code&gt;.prettierrc&lt;/code&gt; file in the root of your directory and add the below config.&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="err"&gt;//.prettierrc&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;"semi"&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;"trailingComma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&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;"printWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tabWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"arrowParens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bracketSpacing"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These rules specify to put semicolons at the end, remove trailing commas, use double quotes for strings, etc, you can read more about the rules &lt;a href="https://prettier.io/docs/en/options.html" rel="noopener noreferrer"&gt;here&lt;/a&gt; and set them up to your preference.&lt;/p&gt;

&lt;p&gt;Now that we have the rules set up, let's add a script to format our code.&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="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --config .prettierrc 'src/**/*.ts' --write"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it we have configured prettier in our project, now whenever you run this script it will format all your source code in the &lt;code&gt;src&lt;/code&gt; directory according to the config you defined. Give it a test, use some single quotes or remove semicolons and then run &lt;code&gt;yarn format&lt;/code&gt;. You can also install the prettier vs code extension and set it to format on save. &lt;/p&gt;

&lt;p&gt;Now that we have prettier setup let's configure it with eslint, update your &lt;code&gt;.eslintrc&lt;/code&gt; as below and you'll have prettier working with eslint and configured as a plugin in eslint config.&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;"root"&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;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@typescript-eslint/parser"&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="s2"&gt;"@typescript-eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier"&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="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"plugin:@typescript-eslint/recommended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"prettier"&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;"rules"&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;"no-unused-vars"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prettier/prettier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&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;h3&gt;
  
  
  Git Hooks
&lt;/h3&gt;

&lt;p&gt;Cool, if you have been following till here this is where it gets the most exciting, you must be wondering it's great that we have set these tools up, but someone can still commit to the repo without running these scripts, this is where git hooks come to our rescue. Git hooks are just scripts that run automatically every time an event occurs in the repository. We will use a tool called &lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;husky&lt;/a&gt; that makes working with git-hooks easy. &lt;/p&gt;

&lt;p&gt;Let's quickly install it as a dev dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; husky

// Also add a prepare script to your package.json as below.

&lt;span class="s2"&gt;"prepare"&lt;/span&gt;: &lt;span class="s2"&gt;"husky install"&lt;/span&gt;

// Now run

yarn prepare
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;prepare&lt;/code&gt; is an npm lifecycle script that will run on &lt;code&gt;npm install&lt;/code&gt; and this will ensure that whenever node modules are installed husky is installed too. Read more on life-cycle scrips &lt;a href="https://docs.npmjs.com/cli/v7/using-npm/scripts#life-cycle-scripts" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's it, husky is now set up in our project, and we can configure it to run our &lt;code&gt;lint&lt;/code&gt; and &lt;code&gt;format&lt;/code&gt; scripts before commit, for that we can use the &lt;code&gt;pre-commit&lt;/code&gt; hook that runs before a commit. Let's add that hook now, head over to the terminal, and run the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky add .husky/pre-commit &lt;span class="s2"&gt;"yarn lint &amp;amp;&amp;amp; yarn format"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice that now there's a &lt;code&gt;.husky&lt;/code&gt; folder in the root of your repo and it contains a file &lt;code&gt;pre-commit&lt;/code&gt; with the below contents. This hook will run every time you commit to your repo.&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;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/_/husky.sh"&lt;/span&gt;

yarn lint &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try committing something in the repo now, and you will notice that &lt;code&gt;lint&lt;/code&gt; and &lt;code&gt;format&lt;/code&gt; scripts are executed first. If everything looks good, your commit will be added successfully, in case of issues it won't be committed to the repo and you'll have to fix those issues in order to make a commit. You should be able to make a mental model of this now, this ensures that no code with potential bugs or styling issues gets committed to the repo. This can help you save a lot of time in code reviews if these conventions are properly followed.&lt;/p&gt;

&lt;p&gt;This configuration is great but if you notice there is one problem with this approach, if we have a very large codebase and we run linting and formatting on every commit in the code-base it can take up much longer and that's not the intended use case, we only want to run it on the files that have been staged for the commit because ideally only those files should be checked that are being committed to the repo, that's where another tool &lt;code&gt;lint-staged&lt;/code&gt; comes to our rescue and it will ensure that our pre-commit hooks only run on staged files. This can be configured very quickly too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; lint-staged

// Add below config to your package.json

&lt;span class="s2"&gt;"lint-staged"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"src/**/*.ts"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"yarn lint"&lt;/span&gt;,
    &lt;span class="s2"&gt;"yarn format"&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And update your &lt;code&gt;pre-commit&lt;/code&gt; hook to run &lt;code&gt;npx lint-staged&lt;/code&gt; instead of running &lt;code&gt;yarn lint &amp;amp;&amp;amp; yarn format&lt;/code&gt;&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;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/_/husky.sh"&lt;/span&gt;

npx lint-staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, now lint will only run against the staged files, you can quickly test it by creating a file in the repo with some lint-issues and don't stage it while staging some other files that are compliant with the lint rules and you should notice that git commit will run fine, but if you stage the file with the lint issues, it will block the commit and give you the lint errors on the terminal that should be fixed. If you want to lint the entire project you can still do it by running &lt;code&gt;yarn lint&lt;/code&gt;. Now our tooling is set up well enough to ensure that the whole team can follow it and adhere to the same coding standards and style guides.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conventional Commits
&lt;/h3&gt;

&lt;p&gt;Our development setup is pretty much complete but there's still one area where the team can adopt different conventions, that will be the commit messages yes that's right people can have different preferences when adding commit messages and we need to ensure that the team conforms to a standard convention. We will be adopting the &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;conventional commits specification&lt;/a&gt; in our project and ensure it using a tool named &lt;code&gt;commitizen&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;The general syntax for this specification is as follow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;

[optional body]

[optional footer(s)]

// Example

feat(landing-page): add new landing page

A new landing page for the website...

Closes #&amp;lt;github-issue-number&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright now that we have an understanding of the specification let's configure our project to use this tool.&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 -D commitizen cz-conventional-changelog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add this to your &lt;code&gt;pacakge.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="nl"&gt;"config"&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;"commitizen"&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;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cz-conventional-changelog"&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="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;"cz"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&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;em&gt;Note: If you end up naming your script &lt;code&gt;commit&lt;/code&gt; then it might run twice because of &lt;a href="https://github.com/commitizen/cz-cli#optional-install-and-run-commitizen-locally" rel="noopener noreferrer"&gt;this issue&lt;/a&gt; mentioned on the repo.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now try committing to the repo by running &lt;code&gt;yarn cz&lt;/code&gt; and you will be prompted a couple of questions on the terminal to make the proper commit. Great now our conventional-commits are set up we can also set it up as a git hook by running the below command and running commitizen with our &lt;code&gt;prepare-commit-msg&lt;/code&gt; hook which is invoked by &lt;code&gt;git commit&lt;/code&gt; however there's an issue with this approach which triggers the git commit twice when running &lt;code&gt;yarn cz&lt;/code&gt;. The issue is opened on the repo &lt;a href="https://github.com/commitizen/cz-cli/issues/844" rel="noopener noreferrer"&gt;here&lt;/a&gt;, I would advise not to use this approach until this issue is fixed and rely on the previous script &lt;code&gt;yarn cz&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky add .husky/prepare-commit-msg &lt;span class="s2"&gt;"exec &amp;lt; /dev/tty &amp;amp;&amp;amp; node_modules/.bin/cz --hook || true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Github Actions
&lt;/h3&gt;

&lt;p&gt;In the last part, we will focus on setting up a GitHub action to ensure that our lint and format jobs are run on every commit and how Github actions can help in our CI/CD pipeline. Setting up a good and fast CI/CD pipeline is very essential in modern software development now. As your software evolves it might become a very tedious task to compile the builds manually and if it needs to be compiled on multiple platforms you can imagine how time taking this could be.&lt;/p&gt;

&lt;p&gt;Github actions are a handy tool to automate software workflows and provides CI/CD right out of your Github code repo. Github actions are event-driven and basically require a &lt;code&gt;.yaml&lt;/code&gt; file where you can provide your configuration in steps.&lt;/p&gt;

&lt;p&gt;Some key terminologies to keep in consideration when working with Github Actions include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflows:&lt;/strong&gt; automated work procedures that contain one or more jobs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Events:&lt;/strong&gt; an activity that triggers a workflow (e.g push to a branch)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobs:&lt;/strong&gt; a set of steps that execute on the same runner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step:&lt;/strong&gt; a task that can execute commands on a job.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read more about these on the official &lt;a href="https://docs.github.com/en/actions/learn-github-actions/introduction-to-github-actions" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, initialize a git repo in your project if you haven't already by running &lt;code&gt;git init&lt;/code&gt; and commit your changes to the repo. Make sure you add a &lt;code&gt;.gitignore&lt;/code&gt; file and add &lt;code&gt;node_modules&lt;/code&gt; and &lt;code&gt;dist&lt;/code&gt; to it so they don't get committed to the repo.&lt;/p&gt;

&lt;p&gt;Next, create a repo on your Github account and copy the remote's origin url, now head over to your local repo and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin &amp;lt;remote-repo-origin&amp;gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next head over to your Github repo and click on the Actions tab and select set up a workflow yourself&lt;/p&gt;

&lt;p&gt;In the editor name the file &lt;code&gt;lint.yml&lt;/code&gt; and clear the default action and replace it with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;lint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node.js environment&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2.4.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;14.16.1'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Node Modules&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint and format&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;npm run lint&lt;/span&gt;
          &lt;span class="s"&gt;npm run format&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This action file is pretty straight forward and you should be able to navigate through it very easily, we are declaring our workflow name as Lint that has a single job &lt;code&gt;lint&lt;/code&gt;. A workflow can have multiple jobs and by default, jobs run in parallel but can be configured to make them run sequentially by using the &lt;code&gt;needs &amp;lt;job-id&amp;gt;&lt;/code&gt; syntax in the &lt;code&gt;.yml&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;Next, we are specifying to run the job on Ubuntu's latest version and set up Node v14.16.1 using a &lt;a href="https://github.com/marketplace/actions/setup-node-js-environment" rel="noopener noreferrer"&gt;marketplace action&lt;/a&gt;. After that, we are just installing node modules and running our lint/format scripts. &lt;/p&gt;

&lt;p&gt;Note this is a very simple example but you can extend it to your needs, for example, let's say you have set up tests in your repo then you can define another &lt;code&gt;test&lt;/code&gt; job that runs after &lt;code&gt;linting&lt;/code&gt;, and if the test job succeeds, you can run a &lt;code&gt;build&lt;/code&gt; job to compile a build and deploy to staging. You can basically configure it to adapt to your needs and automate your development workflow. Github actions are indeed a powerful tool and you should definitely explore them.&lt;/p&gt;

&lt;p&gt;You can see all of this in action on my GitHub repo &lt;a href="https://github.com/asjadanis/ts-tooling" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The idea with this blog was not to go into the depths of each tool but rather give you an overview of all these tools that can help you in our development process and ensure a better development experience. Setting up these tools can be a very boring and cumbersome task but these tools are your friends and once you adopt them properly in your code-base you won't regret it. Feel free to share your thoughts with me in the comment section or connect with me on &lt;a href="https://twitter.com/asjadanis" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>tutorial</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Parsing .env with TypeScript</title>
      <dc:creator>Asjad Anis</dc:creator>
      <pubDate>Sat, 28 Aug 2021 12:39:08 +0000</pubDate>
      <link>https://forem.com/asjadanis/parsing-env-with-typescript-3jjm</link>
      <guid>https://forem.com/asjadanis/parsing-env-with-typescript-3jjm</guid>
      <description>&lt;p&gt;When working with Node.js its a common practice to keep our credentials and secrets in a separate &lt;code&gt;.env&lt;/code&gt; file, that's never pushed to our repo. In order to access these variables in our code, we simply use &lt;a href="https://github.com/motdotla/dotenv" rel="noopener noreferrer"&gt;dotenv&lt;/a&gt; package to parse the &lt;code&gt;.env&lt;/code&gt; file and load our env variables into &lt;code&gt;process.env&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Here's a quick example on how to do this in plain JavaScript.&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;// .env&lt;/span&gt;

&lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;DB_URI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;YOUR_DB_URL&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;Now to access these variables we can do something like&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;// index.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&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;connectDB&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;...&lt;/span&gt;
  &lt;span class="nx"&gt;mongooose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&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;DB_URI&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;Since JavaScript doesn't care much about the type so we can pretty much access any property on &lt;code&gt;process.env&lt;/code&gt; and our code won't give us any red signs untill we run it and find out that process.env.DB_URI is &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now let's say we had to do the same thing in TypeScript, and keep it fully typed and have all the benefits that come with a typed system. In order to keep it fully typed we will have to first extend the &lt;code&gt;ProcessEnv&lt;/code&gt; Interface to have our custom env variables available on the interface. For this we will have to use &lt;a href="https://www.typescriptlang.org/docs/handbook/declaration-merging.html" rel="noopener noreferrer"&gt;Declaration-Merging&lt;/a&gt; which is a TypeScript feature for combining two or more declarations with the same name.&lt;/p&gt;

&lt;p&gt;You can have a quick overview of this feature and its use case on this twitter thread&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1431000236269477889-457" src="https://platform.twitter.com/embed/Tweet.html?id=1431000236269477889"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1431000236269477889-457');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1431000236269477889&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;We will use the same feature to extend the &lt;code&gt;ProcessEnv&lt;/code&gt; interface with our custom env varibales.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;global.d.ts&lt;/code&gt; with the below contents&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;namespace&lt;/span&gt; &lt;span class="nx"&gt;NodeJS&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;ProcessEnv&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;MONGO_URI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&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;Above we are just extending the ProcessEnv Interface that's accessible under NodeJS namespace and specifying our custom env varibales types.&lt;/p&gt;

&lt;p&gt;Now if you write &lt;code&gt;process.env&lt;/code&gt; in your code, intellisense would autosuggest you the fields avaialable on &lt;code&gt;process.env&lt;/code&gt; which is great &lt;code&gt;process.env.MONGO_URI&lt;/code&gt; is no longer a mystery in our code.&lt;/p&gt;

&lt;p&gt;Make sure you specify the path to this file in your &lt;code&gt;tsconfig.json&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;A better approach would be to have a folder lets say &lt;code&gt;extended-types&lt;/code&gt; and keep all your extended types there and just specify the path to that folder here instead of a single file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

"typeRoots": ["./global.d.ts", "./node_modules/@types"]


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

&lt;/div&gt;

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

&lt;p&gt;Now let's create a &lt;code&gt;config.ts&lt;/code&gt; file that will encapsulate the logic for parsing &lt;code&gt;.env&lt;/code&gt; file and converting it into our own custom &lt;code&gt;Config&lt;/code&gt; type that we want to use in the code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&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;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Parsing the env file.&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../config/config.env&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="c1"&gt;// Interface to load env variables&lt;/span&gt;
&lt;span class="c1"&gt;// Note these variables can possibly be undefined&lt;/span&gt;
&lt;span class="c1"&gt;// as someone could skip these varibales or not setup a .env file at all&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ENV&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&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="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;MONGO_URI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;Config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;MONGO_URI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Loading process.env as ENV interface&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;ENV&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&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;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="p"&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;PORT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&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;PORT&lt;/span&gt;&lt;span class="p"&gt;)&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;MONGO_URI&lt;/span&gt;&lt;span class="p"&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;MONGO_URI&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Throwing an Error if any field was undefined we don't &lt;/span&gt;
&lt;span class="c1"&gt;// want our app to run if it can't connect to DB and ensure &lt;/span&gt;
&lt;span class="c1"&gt;// that these fields are accessible. If all is good return&lt;/span&gt;
&lt;span class="c1"&gt;// it as Config which just removes the undefined from our type &lt;/span&gt;
&lt;span class="c1"&gt;// definition.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getSanitzedConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&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;Config&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;for &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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&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;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Missing key &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; in config.env`&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;config&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Config&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="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getConfig&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;sanitizedConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getSanitzedConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&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;sanitizedConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;




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

&lt;/div&gt;

&lt;p&gt;Now you can simple import config.ts in your code and access the fields and it would be super cool to have the intelllisense give you type inference about the fields present on config object.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongoose&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;config&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config&lt;/span&gt;&lt;span class="dl"&gt;"&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;connectDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="nx"&gt;connection&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;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MONGO_URI&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🟢 Mongo db connected:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&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;I hope this post helped you and you can extend the same concept to other similar use cases when working with TypeScript.&lt;/p&gt;

&lt;p&gt;Feel free to drop any suggestions or improvements on my approach for this, and you can always connect with me on &lt;a href="https://twitter.com/asjadanis" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why you should always use virtualenv when working in Python</title>
      <dc:creator>Asjad Anis</dc:creator>
      <pubDate>Sun, 13 Dec 2020 21:49:29 +0000</pubDate>
      <link>https://forem.com/asjadanis/why-you-should-always-use-virtualenv-when-working-in-python-5cob</link>
      <guid>https://forem.com/asjadanis/why-you-should-always-use-virtualenv-when-working-in-python-5cob</guid>
      <description>&lt;p&gt;If you have been developing in Python, you must have had a tough time with dependency conflicts when working on multiple projects, and it's kind of inevitable you have to face this issue at least once in your python development career before you look for solutions and come across the term virtual-environments or virtualenv.&lt;/p&gt;

&lt;p&gt;If you have faced such issues then this post is exactly for you to give an understanding of how python run time works and why virtual-environments are needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pip's Default Choice
&lt;/h3&gt;

&lt;p&gt;Pip is the default package manager for python just like npm is for Node, and by default, pip will install any package globally and this is where things start to get a little out of hands. Now imagine you are working on two projects both of these projects have a common dependency, and for the sake of simplicity, we will call it &lt;strong&gt;dependency A&lt;/strong&gt;. &lt;em&gt;Project 1&lt;/em&gt; requires version &lt;strong&gt;1.0.0&lt;/strong&gt; of &lt;strong&gt;dependency A&lt;/strong&gt; and &lt;em&gt;Project 2&lt;/em&gt; requires version &lt;strong&gt;2.0.0&lt;/strong&gt; of &lt;strong&gt;dependency A&lt;/strong&gt; and since at any given time the python interpreter can only maintain one version of the &lt;strong&gt;dependency A&lt;/strong&gt; we won't be able to run these two projects without having to manually install the correct version every time we switch between projects which will soon become a hindrance in our development flow. This was a very basic example now imagine a specific version of &lt;strong&gt;dependency A&lt;/strong&gt; is dependent on a specific version of &lt;strong&gt;dependency B&lt;/strong&gt; and you can kind of get an idea on how this could potentially break other projects. &lt;/p&gt;

&lt;h3&gt;
  
  
  Virtual-Environments to Rescue
&lt;/h3&gt;

&lt;p&gt;This is where Virtual Environments come to play and facilitate us in creating isolated environments for each project. Virtual Environment is basically a fancy term for a directory within your project that encapsulates executables and packages that are required to run the project. Virtual Environment contains links to the python interpreters that are installed on the disk and this essentially means that by tweaking this property you can define which python-runtime you want to run your project with, sounds cool right let's see how we can set up a virtual environment in our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;pip3 install virtualenv. &lt;/li&gt;
&lt;li&gt;cd &amp;lt; project-path &amp;gt;. &lt;/li&gt;
&lt;li&gt;virtualenv &amp;lt; name-of-your-env &amp;gt;. (Generally a good practice to name it venv)&lt;/li&gt;
&lt;li&gt;source ./&amp;lt; name-of-your-env &amp;gt;/bin/activate. (To activate your environment)&lt;/li&gt;
&lt;li&gt;deactivate (To deactivate)&lt;/li&gt;
&lt;li&gt;virtualenv -p &amp;lt; path-to-python-interpreter &amp;gt; &amp;lt; name-of-your-env &amp;gt; (To switch to python interpreter of your choice)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's it once the virtual environment is created you can install any package and that will be installed locally within that project without affecting your global packages and creating dependency conflicts.&lt;/p&gt;

&lt;p&gt;Now if you use a modern IDE like &lt;a href="https://www.jetbrains.com/pycharm/"&gt;PyCharm&lt;/a&gt; you would have noticed that every time you create a new project PyCharm creates a virtual environment for you and configures it, and this is exactly what's going on behind the scenes. Now that you know what virtualenv is why its a handy tool when developing in python you should always try to use virtual environments, this would greatly increase your productivity and save you a lot of time that is spent figuring out dependency conflicts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Food for thought
&lt;/h3&gt;

&lt;p&gt;If you have had the chance of working in Node or Javascript you must have noticed that npm deals with this very nicely by default installation in the local space rather than global-space plus the package.json file helps maintain the dependencies and differentiates between dev-dependencies and production dependencies in an elegant manner. Managing dependencies for a python project with a &lt;em&gt;requirements.txt&lt;/em&gt; file can become very tricky when your dependencies have sub-dependencies etc. Although both have their pro's and con's I have always wondered why pip installs packages globally and why there isn't any project configuration file when working in Python. Let me know in the comments if you know why thing's happen like this in python. &lt;/p&gt;

&lt;p&gt;If you like this post do share it with your friends.&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/asjadanis"&gt;Twitter&lt;/a&gt;&lt;br&gt;
Add me on &lt;a href="https://www.linkedin.com/in/asjad-anis/"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>codequality</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
