<?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>DEV Community: Derk-Jan Karrenbeld</title>
    <description>The latest articles on DEV Community by Derk-Jan Karrenbeld (@sleeplessbyte).</description>
    <link>https://dev.to/sleeplessbyte</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%2F28162%2F6a23b5b8-ddca-4322-bf10-73b33bac4fa8.jpeg</url>
      <title>DEV Community: Derk-Jan Karrenbeld</title>
      <link>https://dev.to/sleeplessbyte</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sleeplessbyte"/>
    <language>en</language>
    <item>
      <title>Predicate (Programming logic)</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Wed, 03 Jun 2020 12:38:46 +0000</pubDate>
      <link>https://dev.to/sleeplessbyte/predicate-programming-logic-7f3</link>
      <guid>https://dev.to/sleeplessbyte/predicate-programming-logic-7f3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://derk-jan.com/2020/05/predicate/"&gt;derk-jan.com&lt;/a&gt;. I have recently &lt;a href="https://derk-jan.com/here-we-go-again/"&gt;taken up writing, again&lt;/a&gt; and am trying to commit to at least one helpful post each week for the next 49 weeks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In university I had to study &lt;a href="https://www.metalevel.at/prolog"&gt;Prolog&lt;/a&gt; when using &lt;a href="https://multiagentcontest.org/publications/AppliedGOAL.pdf"&gt;Goal&lt;/a&gt;, in order to create an agent (artificial intelligence) to play &lt;em&gt;and win&lt;/em&gt; capture the flag in Unreal Tournament. This article is not about Prolog, or Goal, but it helps me to mentally model what &lt;em&gt;predicates&lt;/em&gt; are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Predicates in English
&lt;/h2&gt;

&lt;p&gt;In English, a predicate is a verb phrase template that describes a property, or a relationship, represented by the variables in that template. For example, the phrases &lt;strong&gt;"Jessica is running"&lt;/strong&gt;, &lt;strong&gt;"The program is running"&lt;/strong&gt; and &lt;strong&gt;"The machine that assembles the car parts is running"&lt;/strong&gt; all come from the same template "x is running", where x is replaced by the appropriate noun or noun phrase. The phrase &lt;strong&gt;"is running"&lt;/strong&gt; is a predicate, and it describe the property of 'being in a running state'.&lt;/p&gt;

&lt;p&gt;This does not limit itself to properties, as &lt;strong&gt;"The function produces an error when it runs"&lt;/strong&gt;, &lt;strong&gt;"The operation produces a value when it compiles"&lt;/strong&gt; and &lt;strong&gt;"The API produces a new model when it is deployed"&lt;/strong&gt; are all created by substituting the &lt;strong&gt;a&lt;/strong&gt;, &lt;strong&gt;b&lt;/strong&gt; and &lt;strong&gt;c&lt;/strong&gt; in the template &lt;strong&gt;"a produces b when c"&lt;/strong&gt;. The latter is a predicate and describes the relationship between two objects and a state. This could be represented as &lt;code&gt;Produces(A, B, C)&lt;/code&gt; or even &lt;code&gt;P(a, b, c)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Predicates in Programming
&lt;/h2&gt;

&lt;p&gt;Now, in mathematical logic, predicates are usually &lt;a href="https://en.wikipedia.org/wiki/Boolean-valued_function"&gt;Boolean-valued functions&lt;/a&gt; which isn't much more than a function that takes a set of inputs, and only outputs a boolean value.&lt;/p&gt;

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

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="nx"&gt;isEven&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="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function &lt;code&gt;isEven&lt;/code&gt; takes a set of inputs (all natural numbers) and returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;, based on the predicate. More concretely, it returns &lt;code&gt;true&lt;/code&gt; &lt;em&gt;if it satisfies&lt;/em&gt; the predicate, and &lt;code&gt;false&lt;/code&gt; otherwise. The function &lt;code&gt;isEven&lt;/code&gt; is therefore a predicate.&lt;/p&gt;

&lt;p&gt;Apart from &lt;em&gt;specifically&lt;/em&gt; creating functions that return &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;, predicates are used all over. For example, in many languages there is a &lt;code&gt;filter()&lt;/code&gt; function on something that is enumerable, like a list-like data structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Arrays&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.function.Predicate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JavaExample&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Predicate&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="c1"&gt;// 8&lt;/span&gt;
&lt;span class="c1"&gt;// 34&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this Java example, the &lt;em&gt;lambda&lt;/em&gt; (anonymous function, which we've named &lt;code&gt;isEven&lt;/code&gt;) has the type &lt;code&gt;Predicate&amp;lt;Integer&amp;gt;&lt;/code&gt;, which is a function that takes an &lt;code&gt;Integer&lt;/code&gt; and returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. The function is a &lt;em&gt;predicate&lt;/em&gt;. The &lt;em&gt;predicate&lt;/em&gt; is passed into the function &lt;code&gt;.filter()&lt;/code&gt;, which will execute the predicate for each item in the list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;

&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;

&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;

&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;

&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;

&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;

&lt;span class="n"&gt;isEven&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The final "list" of items that makes it to the &lt;code&gt;.forEach&lt;/code&gt; are those that evaluate to &lt;code&gt;true&lt;/code&gt;, because that is what &lt;code&gt;.filter()&lt;/code&gt; does: keep the items for which the &lt;em&gt;predicate&lt;/em&gt; returns &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A language doesn't need to be typed to support predicates. Here is the equivalent example in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&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;isEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="nx"&gt;numbers&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;isEven&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&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="o"&gt;=&amp;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;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="c1"&gt;// 8&lt;/span&gt;
&lt;span class="c1"&gt;// 34&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Again, each value in the &lt;code&gt;numbers&lt;/code&gt; array is given to the &lt;code&gt;isEven()&lt;/code&gt; &lt;em&gt;predicate&lt;/em&gt;, and those that evaluate the &lt;em&gt;predicate&lt;/em&gt; to &lt;code&gt;true&lt;/code&gt;, will be kept (and are then logged in the &lt;code&gt;.forEach&lt;/code&gt;). It doesn't really matter if you name the predicate, using an in-line, anonymous function doesn't change the fact that it's a predicate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;numbers&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;n&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;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&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="o"&gt;=&amp;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;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="c1"&gt;// 8&lt;/span&gt;
&lt;span class="c1"&gt;// 34&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ruby has a language feature &lt;strong&gt;built-in&lt;/strong&gt; to support predicates! Predicate methods in Ruby are those methods that end with a question mark &lt;code&gt;?&lt;/code&gt;; they return either &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. The same example in Ruby looks a bit like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;NUMBERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="no"&gt;NUMBERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Or alternatively&lt;/span&gt;
&lt;span class="no"&gt;NUMBERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:even?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# 2&lt;/span&gt;
&lt;span class="c1"&gt;# 8&lt;/span&gt;
&lt;span class="c1"&gt;# 34&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [2, 8, 34]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Predicates are used all over, and now you can name them as such. Each time a function (e.g. &lt;code&gt;.filter()&lt;/code&gt;) takes an argument - an argument that must be &lt;em&gt;a function&lt;/em&gt; itself; a function which returns &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; based on some input (e.g &lt;code&gt;isEven&lt;/code&gt;) - you know you're dealing with a &lt;code&gt;predicate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Oh, and in Prolog? In Prolog define an &lt;code&gt;even&lt;/code&gt; predicate like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight prolog"&gt;&lt;code&gt;&lt;span class="ss"&gt;even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="ss"&gt;is&lt;/span&gt; &lt;span class="ss"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="ss"&gt;even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;false&lt;/span&gt;

&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="ss"&gt;even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then filter a list based on even items:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight prolog"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** Predicates */&lt;/span&gt;

&lt;span class="ss"&gt;even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="ss"&gt;is&lt;/span&gt; &lt;span class="ss"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="ss"&gt;odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="ss"&gt;is&lt;/span&gt; &lt;span class="ss"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Filter the list on even elements only
 * 1. true when empty
 * 2. otherwise, there are two options
 *    - if Element (first item) is odd, the Next list does not get Element
 *    - if Element is even, the Next list gets Element
 */&lt;/span&gt;
&lt;span class="ss"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;
&lt;span class="ss"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;        &lt;span class="nv"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;  &lt;span class="ss"&gt;odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="ss"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;T&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="ss"&gt;even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;T&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Prints a list by iteration through each element
 * 1. true when empty
 * 2. separate Element (first item) and the Tail (...rest)
 *    - write the element + new line
 *    - continue printlist with the tail of the list
 */&lt;/span&gt;
&lt;span class="ss"&gt;printlist&lt;/span&gt;&lt;span class="p"&gt;([]).&lt;/span&gt;
&lt;span class="ss"&gt;printlist&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="ss"&gt;nl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;printlist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Tail&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;


&lt;span class="o"&gt;?-&lt;/span&gt; &lt;span class="ss"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;NewList&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;printlist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;NewList&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="m"&gt;34&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;Want these short articles in your e-mail? &lt;a href="https://buttondown.email/SleeplessByte"&gt;📧 Sign up for my newsletter&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>javascript</category>
      <category>ruby</category>
      <category>java</category>
    </item>
    <item>
      <title>Cross tab events</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Wed, 27 May 2020 14:18:00 +0000</pubDate>
      <link>https://dev.to/sleeplessbyte/cross-tab-events-48g</link>
      <guid>https://dev.to/sleeplessbyte/cross-tab-events-48g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://derk-jan.com/2020/05/cross-tab-events/"&gt;derk-jan.com&lt;/a&gt;. I have recently &lt;a href="https://derk-jan.com/here-we-go-again/"&gt;taken up writing, again&lt;/a&gt; and am trying to commit to at least one helpful post each week for the next 50 weeks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Last week I had an instance where I needed to update all tabs of the same site when a user chose something from a dropdown. Think of the dropdown's current value being a global setting and changing it on one tab, feels like it should change it every where.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use a &lt;code&gt;BroadcastChannel&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The recommended way is to use a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel"&gt;&lt;code&gt;BroadcastChannel&lt;/code&gt;&lt;/a&gt;, which takes a &lt;em&gt;name&lt;/em&gt; upon construction, which is unique for all &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/browsing_context"&gt;browsing contexts&lt;/a&gt; of the same &lt;em&gt;origin&lt;/em&gt;. In other words, most of the time this equals all tabs and windows on the same site. One of the great things about &lt;code&gt;BroadcastChannel&lt;/code&gt;s is that there is no real indirection, &lt;em&gt;and&lt;/em&gt; it is available in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API"&gt;Web Workers&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;timeRange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// fictional function that reloads the current page contents&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleSettingsBroadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;time-range.changed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timeRange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;handleSettingsBroadcast&lt;/span&gt;

&lt;span class="c1"&gt;// Callback when the drop down is changed&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;onChangeTimeRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;time-range.changed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextValue&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;In the example above, I've chosen to use a single channel &lt;code&gt;settings&lt;/code&gt;, with structured data. You could, instead, make&lt;br&gt;
a channel per "message-type", or even use a single channel &lt;code&gt;com.yourdomain.app&lt;/code&gt; for everything.&lt;/p&gt;
&lt;h3&gt;
  
  
  React use case
&lt;/h3&gt;

&lt;p&gt;If you're using something like flux, redux or another state manager, you can send "updated state" across tabs, but be weary: if you have side-effects on state changes, this will run those side-effects multiple times.&lt;/p&gt;

&lt;p&gt;Additionally, you can use a hook to receive updates, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useBroadcastValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initial&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="kd"&gt;const&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="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a new channel on this name. The channel will be able to receive&lt;/span&gt;
    &lt;span class="c1"&gt;// data as long as it's not closed.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;broadcastChannel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Receives messages and forwards them to the setValue dispatch if they&lt;/span&gt;
    &lt;span class="c1"&gt;// match the type. This requires each event in this channel to have the&lt;/span&gt;
    &lt;span class="c1"&gt;// shape:&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="c1"&gt;// {&lt;/span&gt;
    &lt;span class="c1"&gt;//   type: 'event-type',&lt;/span&gt;
    &lt;span class="c1"&gt;//   value: &amp;lt;some value&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// }&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="nx"&gt;broadcastChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&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;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Close the channel -- we no longer want to receive messages&lt;/span&gt;
    &lt;span class="k"&gt;return&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;broadcastChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&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="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&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;timeRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useBroadcastValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;time-range.updated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the same fashion, a "send on change" broadcast can be achieved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useBroadcastState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initial&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="kd"&gt;const&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="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initial&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;broadcastChannel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// You can do all this without a use-effect, as it's not expensive code. You&lt;/span&gt;
  &lt;span class="c1"&gt;// could also do this in a single use-effect. However, I've often gotten&lt;/span&gt;
  &lt;span class="c1"&gt;// questions how you do something like this: have two variables and update&lt;/span&gt;
  &lt;span class="c1"&gt;// them independently, whilst maintaining integrity. This is how you could do&lt;/span&gt;
  &lt;span class="c1"&gt;// that.&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a new channel on this name. The channel will be able to receive&lt;/span&gt;
    &lt;span class="c1"&gt;// and send data as long as it's not closed.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// This allows the channel to be used outside this effect&lt;/span&gt;
    &lt;span class="nx"&gt;setBroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Close the channel -- we no longer want to receive or send messages, as&lt;/span&gt;
    &lt;span class="c1"&gt;// the channel name has changed (or the hook is in a component that is being&lt;/span&gt;
    &lt;span class="c1"&gt;// unmounted).&lt;/span&gt;
    &lt;span class="k"&gt;return&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;pipe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&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="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&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;broadcastChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&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;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Each time the channel changes (different name, initial mount) or the&lt;/span&gt;
    &lt;span class="c1"&gt;// event we want to listen to changes, run this hook.&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;broadcastChannel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;setAndBroadcastValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Broadcast the value&lt;/span&gt;
      &lt;span class="nx"&gt;broadcastChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextValue&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

      &lt;span class="c1"&gt;// ...but also update it locally&lt;/span&gt;
      &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;broadcastChannel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAndBroadcastValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MySettingComponent&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;timeRange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTimeRange&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useBroadcastState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;time-range.updated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Compatibility
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://caniuse.com/#feat=broadcastchannel"&gt;Support&lt;/a&gt; is &lt;a href="https://caniuse.com/#feat=broadcastchannel"&gt;pretty good&lt;/a&gt;, but at moment of writing, no Safari. This probably makes this solution not-workable for many of you. Luckily, there is a, now almost "ancient" way to do this with even better support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use &lt;code&gt;localStorage&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage"&gt;LocalStorage&lt;/a&gt; has been around for longer and that shows when you look at the &lt;a href="https://caniuse.com/#feat=mdn-api_window_localstorage"&gt;support&lt;/a&gt;. Not only is it supported on Safari, it also works on mobile browsers and even IE. Great.&lt;/p&gt;

&lt;p&gt;How can we use &lt;code&gt;localStorage&lt;/code&gt; to send data across tabs? As you can imagine, data from &lt;code&gt;localStorage&lt;/code&gt; is available in all the tabs of the same origin (scheme, port, hostname), but that doesn't magically broadcast changes everywhere. It actually does!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;timeRange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// fictional function that reloads the current page contents&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleSettingsBroadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;settings.time-range.changed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timeRange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newValue&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSettingsBroadcast&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Callback when the drop down is changed&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;onChangeTimeRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;settings.time-range.changed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  React hook
&lt;/h3&gt;

&lt;p&gt;The implementation for a react hook is less complex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useBroadcastState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get the initial value from local storage. Remove the initializer if you&lt;/span&gt;
  &lt;span class="c1"&gt;// don't intend to store the value _anyway_. For our settings, it makes&lt;/span&gt;
  &lt;span class="c1"&gt;// perfect sense, as they're not sensitive.&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;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;null&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&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;onStorage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&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="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;event&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="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// This will trigger on storage events. That usually means that it will&lt;/span&gt;
    &lt;span class="c1"&gt;// trigger in all browsing contexts that are currently blurred (so not the&lt;/span&gt;
    &lt;span class="c1"&gt;// current, active/focussed one). This doesn't hold for older browsers. IE10&lt;/span&gt;
    &lt;span class="c1"&gt;// for example will send the event to the calling tab as well. That's okay,&lt;/span&gt;
    &lt;span class="c1"&gt;// just expect a double render.&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onStorage&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onStorage&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="nx"&gt;event&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;setAndBroadcastValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Broadcast the value&lt;/span&gt;
      &lt;span class="nx"&gt;localStorage&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="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

      &lt;span class="c1"&gt;// ...but also update it locally&lt;/span&gt;
      &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;event&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAndBroadcastValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Onwards
&lt;/h2&gt;

&lt;p&gt;There are various ways to send information across tabs. This can be really helpful if context is key. Users sometimes open sites in many tabs at the same time. Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In CMS or on edit pages, you can broadcast that editing is in progress in a different tab&lt;/li&gt;
&lt;li&gt;In systems where you only want one socket connection open, you can broadcast that socket connections should close&lt;/li&gt;
&lt;li&gt;In adminsitrative dashboards you might want to reload index/show pages when content is CRUDed, for that type&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Want these short articles in your e-mail? &lt;a href="https://buttondown.email/SleeplessByte"&gt;📧 Sign up for my newsletter&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>webapi</category>
    </item>
    <item>
      <title>FFMPEG examples</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Wed, 20 May 2020 11:51:41 +0000</pubDate>
      <link>https://dev.to/sleeplessbyte/ffmpeg-examples-51l7</link>
      <guid>https://dev.to/sleeplessbyte/ffmpeg-examples-51l7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://derk-jan.com/2020/04/ffmpeg-examples/"&gt;derk-jan.com&lt;/a&gt;. I have recently &lt;a href="https://derk-jan.com/here-we-go-again/"&gt;taken up writing, again&lt;/a&gt; and am trying to commit to at least one helpful post each week for the next 51 weeks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For &lt;a href="https://soundersmusic.com/"&gt;Sounders Music&lt;/a&gt; I had to write a few new file processors. In their eco-system, audio tracks are uploaded and transcoded to a format that is playable in their front-ends, such as their apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ffmpeg.org/"&gt;&lt;code&gt;ffmpeg&lt;/code&gt;&lt;/a&gt; is a free and open-source library which, depending on how it's built, supports (almost) all industry standard encodings. On top of that: it works cross-platform! Their &lt;a href="https://www.ffmpeg.org/documentation.html"&gt;documentation&lt;/a&gt; is very extensive and, with a bit of patience and perseverance, you can probably make most of it work. This article holds &lt;em&gt;some&lt;/em&gt; of the commands I regularly need when working with media files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is written for FFMPEG 4.2.2+. It will probably work with most versions in the 4.x.x range, but YMMV.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Transcoding a file
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://en.wikipedia.org/wiki/Transcoding"&gt;WikiPedia&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“&lt;a href="https://en.wikipedia.org/wiki/Transcoding"&gt;Transcoding&lt;/a&gt; is the direct digital-to-digital conversion of one &lt;a href="https://en.wikipedia.org/wiki/Character_encoding"&gt;encoding&lt;/a&gt; to another, &lt;strong&gt;[&lt;a href="http://searchmicroservices.techtarget.com/definition/transcoding"&gt;1&lt;/a&gt;]&lt;/strong&gt; such as for movie data files, audio files (e.g., &lt;a href="https://en.wikipedia.org/wiki/MP3"&gt;MP3&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/WAV"&gt;WAV&lt;/a&gt;), or character encoding (e.g., &lt;a href="https://en.wikipedia.org/wiki/UTF-8"&gt;UTF-8&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/ISO/IEC_8859"&gt;ISO/IEC 8859&lt;/a&gt;).”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following command converts &lt;em&gt;any&lt;/em&gt; media file to an &lt;code&gt;.mp4&lt;/code&gt; (with audio encoded using Advanced Audio Coding).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; input_path &lt;span class="nt"&gt;-c&lt;/span&gt;:a aac &lt;span class="nt"&gt;-b&lt;/span&gt;:a 160k &lt;span class="nt"&gt;-vn&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; mp4 &lt;span class="nt"&gt;-movflags&lt;/span&gt; +faststart output_path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;-i&lt;/code&gt;: Takes the input at &lt;code&gt;input_path&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-y&lt;/code&gt;: Writing at &lt;code&gt;output_path&lt;/code&gt;, overwriting;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-c:a&lt;/code&gt;: Transcodes all audio streams using the &lt;a href="https://www.ffmpeg.org/ffmpeg-all.html#aac"&gt;Advanced Audio Coding (AAC) encoder (&lt;code&gt;aac&lt;/code&gt;)&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-b:a&lt;/code&gt;: Setting the bitrate of all audio streams to a CBR of &lt;code&gt;160k&lt;/code&gt; bits per second;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-vn&lt;/code&gt;: Blocking all video streams;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f&lt;/code&gt;: Forcing the type of the file (instead of guessing it based on the file name);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-movflags +faststart&lt;/code&gt;: And ensuring that the output &lt;code&gt;mp4&lt;/code&gt; has its metadata moved to the start, so that it can start playing earlier&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Advanced Audio Coding works on all our target devices (such as modern browsers, Android and iOS devices) and the bitrate chosen is generally a good trade-off between size and quality.&lt;/p&gt;

&lt;p&gt;I generally have to force the "input type" because the files come in without an extension. However, I do usually determine the type using a mime-type analyzer before calling this function (&lt;a href="https://github.com/shrinerb/shrine/blob/master/doc/plugins/determine_mime_type.md#analyzers"&gt;Ruby&lt;/a&gt;, &lt;a href="https://github.com/sindresorhus/file-type#file-type-"&gt;JavaScript or TypeScript&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Blocking the video streams seems to save some processing time and, if not correctly configured, ensures that the output is really an audio file. It also allows to accept video ánd audio files.&lt;/p&gt;

&lt;p&gt;Finally the &lt;code&gt;movflags&lt;/code&gt; enhance the playback when &lt;em&gt;streaming&lt;/em&gt; or &lt;em&gt;preloading&lt;/em&gt; the file. Normally, a MOV/MP4 file has all the metadata about all packets stored in one location (written at the end of the file, it can be moved to the start for better playback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example call and output
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ffmpeg -y -i ./"-3 Daniel Powter - Bad Day.mp3" -c:a aac -b:a 160k -vn -f mp4 -movflags +faststart ./"Daniel Powter.mp4"

ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 9.2.1 (GCC) 20200122
  configuration: --enable-gpl --enable-version3 --enable-sdl2
   --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass
   --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame
   --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg
   --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr
   --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack
   --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2
   --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab
   --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa
   --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx
   --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va
   --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
   --enable-libopenmpt
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Input #0, mp3, from './-3 Daniel Powter - Bad Day.mp3':
  Metadata:
    title           : Bad Day
    comment         : www.mediahuman.com
    Software        : Lavf58.20.100
    artist          : Daniel Powter
  Duration: 00:03:55.18, start: 0.025057, bitrate: 182 kb/s
    Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 182 kb/s
    Metadata:
      encoder         : LAME3.98r
Stream mapping:
  Stream #0:0 -&amp;gt; #0:0 (mp3 (mp3float) -&amp;gt; aac (native))
Press [q] to stop, [?] for help
Output #0, mp4, to './Daniel Powter.mp4':
  Metadata:
    title           : Bad Day
    comment         : www.mediahuman.com
    Software        : Lavf58.20.100
    artist          : Daniel Powter
    encoder         : Lavf58.29.100
    Stream #0:0: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 160 kb/s
    Metadata:
      encoder         : Lavc58.54.100 aac
[mp4 @ 0000021d07bf3940] Starting second pass: moving the moov atom to the beginning of the file
size=    4636kB time=00:03:55.14 bitrate= 161.5kbits/s speed=78.9x
video:0kB audio:4596kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.881678%
[aac @ 0000021d07c18a40] Qavg: 508.682
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Probing the duration
&lt;/h2&gt;

&lt;p&gt;In the example above, there is a &lt;strong&gt;Input&lt;/strong&gt; section with &lt;em&gt;Metadata&lt;/em&gt; and &lt;em&gt;Duration&lt;/em&gt;. This information can be extracted using &lt;a href="https://www.ffmpeg.org/ffprobe-all.html"&gt;&lt;code&gt;ffprobe&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ffprobe input
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In particular, I am interested in the &lt;em&gt;duration&lt;/em&gt; of the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ffprobe input &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;duration &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;noprint_wrappers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1:nokey&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;-v&lt;/code&gt;: Sets the log level to error, set that only errors &lt;em&gt;and&lt;/em&gt; the "formatted" output is shown;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-show_entries&lt;/code&gt;: When this is present, the output only contains the entries as set in this option. Its value (&lt;code&gt;section:field&lt;/code&gt;) will result in an output &lt;code&gt;[SECTION]field=value[/SECTION]&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-of&lt;/code&gt;: Output format, also as &lt;code&gt;-print_format&lt;/code&gt;, which is set to use the &lt;code&gt;default&lt;/code&gt; formatted, but remove the wrapper (&lt;code&gt;[SECTION]&lt;/code&gt;) and remove the &lt;code&gt;field=&lt;/code&gt; key portion;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What remains as output is either an error message or the duration, in (partial) seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example call and output
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ffprobe &lt;span class="s2"&gt;"Daniel Powter - Bad Day.mp4"&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; error &lt;span class="nt"&gt;-show_entries&lt;/span&gt; &lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;duration &lt;span class="nt"&gt;-of&lt;/span&gt; &lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;noprint_wrappers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1:nokey&lt;span class="o"&gt;=&lt;/span&gt;1
235.152000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;Want these short articles in your e-mail? &lt;a href="https://buttondown.email/SleeplessByte"&gt;📧 Sign up for my newsletter&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>audio</category>
      <category>cli</category>
      <category>ffmpeg</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Forward arguments in shell</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Wed, 13 May 2020 14:16:00 +0000</pubDate>
      <link>https://dev.to/sleeplessbyte/forward-arguments-in-shell-3fpb</link>
      <guid>https://dev.to/sleeplessbyte/forward-arguments-in-shell-3fpb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://derk-jan.com/2020/04/forward-in-shell/"&gt;derk-jan.com&lt;/a&gt;. I have recently &lt;a href="https://derk-jan.com/here-we-go-again/"&gt;taken up writing, again&lt;/a&gt; and am trying to commit to at least one helpful post each week for the next 52 weeks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For one of my CLIs, I needed to remove the first argument from the argument list and forward the rest to a next process. In this example, my shell script is called &lt;code&gt;cli_process&lt;/code&gt; and given arguments &lt;code&gt;arg1&lt;/code&gt;, &lt;code&gt;arg2&lt;/code&gt; and &lt;code&gt;arg3&lt;/code&gt;, I want to execute &lt;code&gt;forward_process&lt;/code&gt; with &lt;code&gt;arg2&lt;/code&gt; and &lt;code&gt;arg3&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="c"&gt;# Documentation on @&lt;/span&gt;
&lt;span class="c"&gt;#   https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-_0040&lt;/span&gt;
&lt;span class="c"&gt;# Documentation on shift [n]&lt;/span&gt;
&lt;span class="c"&gt;#   https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-shift&lt;/span&gt;
&lt;span class="c"&gt;# Why quoting the argument is "necessary":&lt;/span&gt;
&lt;span class="c"&gt;#   https://stackoverflow.com/questions/4824590/propagate-all-arguments-in-a-bash-shell-script/4824637#4824637&lt;/span&gt;

&lt;span class="c"&gt;# eats 1 argument&lt;/span&gt;
&lt;span class="nb"&gt;shift &lt;/span&gt;1

&lt;span class="c"&gt;# forwards the rest to "forward_process"&lt;/span&gt;
forward_process &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Originally posted as a &lt;a href="https://gist.github.com/SleeplessByte/ea551df4088d3629f2e5fddcce6b48ea"&gt;gist&lt;/a&gt;, by myself&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows
&lt;/h2&gt;

&lt;p&gt;Windows &lt;code&gt;.bat&lt;/code&gt; files support a similar token: &lt;code&gt;%*&lt;/code&gt;, which is equivalent to &lt;code&gt;$@&lt;/code&gt;.&lt;br&gt;
However, the &lt;code&gt;SHIFT&lt;/code&gt; command, unlike the bash equivalent &lt;code&gt;shift&lt;/code&gt;, doesn't modify this special token. There are various solutions that will attempt to eat the first &lt;code&gt;n&lt;/code&gt; parameters, but all of them have edge-cases in which they don't properly work. Should you need this in windows, I recommend you write out the arguments manually &lt;code&gt;%2&lt;/code&gt;, &lt;code&gt;%3&lt;/code&gt; (and skip &lt;code&gt;%1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here you can find some Windows solutions, but make sure you check the comments underneath each one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/935609/batch-parameters-everything-after-1"&gt;StackOverflow (935609): batch parameters: everything after %1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/761615/is-there-a-way-to-indicate-the-last-n-parameters-in-a-batch-file/761658#761658"&gt;StackOverflow (761615): Is there a way to indicate the last n parameters in a batch file?
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-_0040"&gt;Bash documentation&lt;/a&gt; for &lt;code&gt;@&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-shift"&gt;Bash documentation&lt;/a&gt; for &lt;code&gt;shift&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stackoverflow.com/questions/4824590/propagate-all-arguments-in-a-bash-shell-script/4824637#4824637"&gt;StackOverflow (4824590)&lt;/a&gt; on why you need the "quotes" around "@\$"&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Want these short articles in your e-mail? &lt;a href="https://buttondown.email/SleeplessByte"&gt;📧 Sign up for my newsletter&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>shell</category>
      <category>bash</category>
      <category>cli</category>
    </item>
    <item>
      <title>Internship 2019: Reading list</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Wed, 09 Oct 2019 16:57:02 +0000</pubDate>
      <link>https://dev.to/xpbytes/internship-2019-reading-list-2pjf</link>
      <guid>https://dev.to/xpbytes/internship-2019-reading-list-2pjf</guid>
      <description>&lt;p&gt;During the first half of 2019, &lt;a href="https://xpbytes.com"&gt;XP Bytes&lt;/a&gt; had two interns on the&lt;br&gt;
payroll. This time it were two students from &lt;a href="https://www.techniekcollegerotterdam.nl"&gt;Techniek College Rotterdam&lt;/a&gt;, both studying to become an "Applicatieontwikkelaar" (Software Developer). As a general rule at XP Bytes, before students may accept their position, they have to agree to a few things, among which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading and summarising at least 4 articles as given by the program manager&lt;/li&gt;
&lt;li&gt;Keep their programming fresh with exercises regarding their internship&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a student is unable or uncomfortable to read in English, which might not be their first language, or a language they're proficient at, we will attempt to provide alternatives in the form of recording or audible content.&lt;/p&gt;

&lt;p&gt;Both students graduated with good grades, and it's now time to close the book on past year's projects, which also includes archiving and documenting all the content that came out of this internship. To that end, we will release a series of articles that may aid you during your road to become a developer or may be used as a potential reading list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DwDUxrFh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/15xcs0wbnjsb10kzbkrv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DwDUxrFh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/15xcs0wbnjsb10kzbkrv.jpg" alt='Photo of an open book on a bed, with a bundle of christmas-like lights on top. Caption is "Now I can read in the dark."' title="Photo by Nong Vang (https://unsplash.com/@californong) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before I list the articles, you should know one more thing. We don't expect the student to understand everything or even grasp all the details. Instead, it's to prepare them on writing technical or semi-technical articles for the weeks to come, as well as trying to get them interested in the various products and aspects of writing software. If you're reading some of these and feel as if you don't know enough, that's okay. I would suggest to read it anyway, and come back to it, once you know more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/"&gt;The Law of Leaky Abstractions&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;11 November 2012&lt;/strong&gt;, &lt;em&gt;11 min read&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article by Joel Spolsky might be "old", its contents are (still) relevant. The reason we put it on the reading list, is that we often see &lt;em&gt;incorrect&lt;/em&gt; or &lt;em&gt;inconvenient&lt;/em&gt; abstractions, regardless of the level of the developer. However, It's good to know that abstractions are exactly that: not the concrete reality, and that every abstraction leaks: they are imperfect. And that's okay. This article shows how some well known abstractions are imperfect.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;a href="https://medium.com/swlh/why-you-need-to-build-an-mvp-app-and-5-tips-on-how-to-do-it-937d7040ee19"&gt;Why You Need to Build an MVP App &lt;small&gt;(and 5 tips on how to do it)&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;13 June 2017&lt;/strong&gt;, &lt;em&gt;9 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/swlh/why-you-need-to-build-an-mvp-app-and-5-tips-on-how-to-do-it-937d7040ee19" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ic3zqR4N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2ANpJ452K_P9LZa07ZAayZYA.png" alt="Jessi Salonen"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/swlh/why-you-need-to-build-an-mvp-app-and-5-tips-on-how-to-do-it-937d7040ee19" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Why You Need to Build an MVP App (and 5 tips on how to do it) | by Jessi Salonen | The Startup | Medium&lt;/h2&gt;
      &lt;h3&gt;Jessi Salonen ・ &lt;time&gt;Jun 19, 2017&lt;/time&gt; ・ 9 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Most of us no longer use &lt;a href="https://en.wikipedia.org/wiki/Waterfall_model"&gt;the waterfall model&lt;/a&gt; as our development cycle; we often have &lt;em&gt;way more&lt;/em&gt; ideas than time to implement those ideas; we don't know where to start when we're building an app. Building an MVP (minimal viable product) can be a great strategy when tackling issues and challenges surrounding these concepts.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced"&gt;What the heck is a callback&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;12 June 2017&lt;/strong&gt;, &lt;em&gt;5 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_N_wHhXp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/0%2AqH2Wle1736qoCJj3." alt="Brandon Morelli"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;JavaScript: What the heck is a Callback? | by Brandon Morelli | codeburst&lt;/h2&gt;
      &lt;h3&gt;Brandon Morelli ・ &lt;time&gt;Jul 5, 2017&lt;/time&gt; ・ 5 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        codeburst.io
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In JavaScript, functions can be passed around as values. Sometimes code doesn't execute in-line (synchronously), but rather concurrently (asynchronously). When an asynchronous task finishes, we often want to be notified and execute some code. This article talks about what callbacks are, what they look like, and how or when you could need and use them.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4"&gt;JavaScript Event Loop Explains&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;27 December 2017&lt;/strong&gt;, &lt;em&gt;4 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r4sObX3V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2AULCuN5xjZAA3s0bhxR6gSg.jpeg" alt="Anoop Raveendran"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;JavaScript Event Loop Explained. “How is JavaScript asynchronous and… | by Anoop Raveendran | Frontend Weekly | Medium&lt;/h2&gt;
      &lt;h3&gt;Anoop Raveendran ・ &lt;time&gt;Nov 9, 2018&lt;/time&gt; ・ 4 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;A lot of JavaScript is used in browsers, and browsers do more than just executing JavaScript. JavaScript has various tools to &lt;em&gt;schedule&lt;/em&gt; work or to listen for events (such as mouse clicks) and execute work once these occur. How this ties into &lt;em&gt;responsiveness (vs freezing)&lt;/em&gt;, and when scheduled calls are executed, is explained using the JavaScript "Orchestrator": The Event Loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://medium.com/hackernoon/web-fonts-when-you-need-them-when-you-dont-a3b4b39fe0ae"&gt;Web fonts: when you need them, when you don’t&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;13 August 2017&lt;/strong&gt;, &lt;em&gt;17 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/hackernoon/web-fonts-when-you-need-them-when-you-dont-a3b4b39fe0ae" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G1WyaO14--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/2%2AwMzreVypTZ6R-T9S2HvONQ.jpeg" alt="David Gilbertson"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/hackernoon/web-fonts-when-you-need-them-when-you-dont-a3b4b39fe0ae" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Web fonts: when you need them, when you don’t | by David Gilbertson | HackerNoon.com | Medium&lt;/h2&gt;
      &lt;h3&gt;David Gilbertson ・ &lt;time&gt;May 22, 2019&lt;/time&gt; ・ 17 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Our interns and juniors often know what fonts are and that you can use certain ones via CSS on web pages. Sometimes they also know about services such as &lt;a href="https://fonts.google.com/"&gt;Google's web fonts&lt;/a&gt;. It usually comes as a shocker when one of us tells them about all the issue, limitations and challenges that come with using web fonts. This article is a good summary of our decision tree for using or not using web fonts.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://medium.com/google-design/google-photos-45b714dfbed1"&gt;Building the Google Photos Web UI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;10 July 2018&lt;/strong&gt;, &lt;em&gt;27 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://medium.com/google-design/google-photos-45b714dfbed1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R81VUviX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2AUqbFGaRIKG9UnJwoh1ApCw.png" alt="Antin Harasymiv"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://medium.com/google-design/google-photos-45b714dfbed1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Building the Google Photos Web UI | by Antin Harasymiv | Google Design | Medium&lt;/h2&gt;
      &lt;h3&gt;Antin Harasymiv ・ &lt;time&gt;Jul 10, 2018&lt;/time&gt; ・ 27 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;If you use &lt;a href="https://photos.google.com/"&gt;Google Photos&lt;/a&gt; you might have noticed &lt;em&gt;how well&lt;/em&gt; it scrolls, and how nicely it can zoom in and out. Sometimes our interns need to build an app that can display thousands of items of data. We &lt;em&gt;don't&lt;/em&gt; expect them to be able to optimise that, but we do want to give them some sense in what went into it at the tech giant Google. Hopefully they (and you) find this as intruiging as we find it. It's not meant as a tutorial, but definitely should be a good and interesting read.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://apisyouwonthate.com/blog/api-versioning-has-no-right-way"&gt;API Versioning Has No "Right Way"&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;26 September 2017&lt;/strong&gt;, &lt;em&gt;8 min read&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Naming things is hard, versioning is harder, or so I personally like to say. Especially for those interns and juniors that will work on or build an API, we like to give them this article first, before they dive into the way we have implemented API versioning in our system. Additionally, if it makes sense, we send them over to &lt;a href="https://stripe.com/gb/blog/api-versioning"&gt;read this article&lt;/a&gt; about Stripe's API and their versioning.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://engineering.videoblocks.com/web-architecture-101-a3224e126947"&gt;Web Architecture 101&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;7 November 2017&lt;/strong&gt;, &lt;em&gt;11 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://engineering.videoblocks.com/web-architecture-101-a3224e126947" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OY0OVtFZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2ACh0s7VZLkCYCd9a5PUZj2g.jpeg" alt="Jonathan Fulton"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://engineering.videoblocks.com/web-architecture-101-a3224e126947" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Web Architecture 101. The basic architecture concepts I wish… | by Jonathan Fulton | Storyblocks Product &amp;amp; Engineering&lt;/h2&gt;
      &lt;h3&gt;Jonathan Fulton ・ &lt;time&gt;Dec 12, 2018&lt;/time&gt; ・ 11 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        engineering.videoblocks.com
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;The subtitle is "The basic architecture concepts I wish I knew when I was getting started as a web developer" and I think that pretty much sums up why we recommend this article. It's mostly a nice glossary and explanation of certain concepts you'll need to think about when building on and for the web.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://www.freecodecamp.org/news/how-to-visually-design-state-in-javascript-3a6a1aadab2b/"&gt;How to visually design state in JavaScript&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;20 July 2018&lt;/strong&gt;, &lt;em&gt;15 min read&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The reason this article is on the list is that we want our juniors to get a bit more comfortable with graph theory. Its core contents is actually not about JavaScript at all, but expresses pretty well how we like to design on paper whenever we have to deal with states and their transitions.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://uxdesign.cc/the-ultimate-guide-to-proper-use-of-animation-in-ux-10bd98614fa9"&gt;The ultimate guide to proper use of animation in UX&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;5 September 2018&lt;/strong&gt;, &lt;em&gt;11 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://uxdesign.cc/the-ultimate-guide-to-proper-use-of-animation-in-ux-10bd98614fa9" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--groipox_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2Aq7PId3fNuHJPI_O5pH8Ltw.png" alt="Taras Skytskyi"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://uxdesign.cc/the-ultimate-guide-to-proper-use-of-animation-in-ux-10bd98614fa9" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;The ultimate guide to proper use of animation in UX | by Taras Skytskyi | UX Collective&lt;/h2&gt;
      &lt;h3&gt;Taras Skytskyi ・ &lt;time&gt;Mar 9, 2019&lt;/time&gt; ・ 11 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        uxdesign.cc
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;I personally don't agree that this is &lt;em&gt;thé ultimate guide&lt;/em&gt;, but it certainly is comprehensive, and most of all crystal clear. The animations itself are executed perfectly, conveying exactly what they intend to convey. Animation is not necessarily hard, but it's easy to try to slap on animation. This guide gives great guidelines and rules when it comes to using animation to benefit UX instead of just using animation.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://uxdesign.cc/what-you-should-know-about-skeleton-screens-a820c45a571a"&gt;Everything you need to know about skeleton screens&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;19 October 2018&lt;/strong&gt;, &lt;em&gt;14 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://uxdesign.cc/what-you-should-know-about-skeleton-screens-a820c45a571a" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--plaDCyMU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2AC_RiQjmcR_LqVUXXCtuJTA.jpeg" alt="Bill Chung"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://uxdesign.cc/what-you-should-know-about-skeleton-screens-a820c45a571a" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Everything you need to know about skeleton screens | by Bill Chung | UX Collective&lt;/h2&gt;
      &lt;h3&gt;Bill Chung ・ &lt;time&gt;Jun 5, 2020&lt;/time&gt; ・ 14 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        uxdesign.cc
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Skeleton screens are powerful and research shows that they can help reducing the perceived load time of any application (Web or not). This article is a good in-depth resource about that exact research, the different ways to accomplish adding a skeleton screen and what exactly should be on it / in it.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://uxplanet.org/animation-that-matters-adding-value-to-your-interface-65496fe4c182"&gt;Animation principles for UX and UI designers&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;13 December 2018&lt;/strong&gt;, &lt;em&gt;11 min read&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://uxplanet.org/animation-that-matters-adding-value-to-your-interface-65496fe4c182" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pSHEDa_j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/fit/c/96/96/1%2A_nctLYCm5l3TKDlIjlzHMQ%402x.jpeg" alt="Vernon Joyce"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://uxplanet.org/animation-that-matters-adding-value-to-your-interface-65496fe4c182" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Animation principles for UX and UI designers | by Vernon Joyce | UX Planet&lt;/h2&gt;
      &lt;h3&gt;Vernon Joyce ・ &lt;time&gt;Jul 16, 2019&lt;/time&gt; ・ 11 min read
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KBvj_QRD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/medium_icon-90d5232a5da2369849f285fa499c8005e750a788fdbf34f5844d5f2201aae736.svg" alt="Medium Logo"&gt;
        uxplanet.org
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Whereas the "ultimate guide" is an amazing "rules and guidelines" article, this particular entry of our recommended reading list talks about the &lt;em&gt;properties&lt;/em&gt; of animation and &lt;em&gt;concepts&lt;/em&gt; on a bit more abstract level. In other words, if you work with these concepts in mind, you hopefully don't need the guidelines at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6oKpaB5A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e1ak0qorqm2txflfxv2k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6oKpaB5A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e1ak0qorqm2txflfxv2k.jpg" alt="Photo with the caption 'The urban life in Rotterdam is great to capture. Amazing buildings and a lot of people make great stories together. A lovely city for photography.', displaying a yellow bridge with high walls that connects Rotterdam's city centre with the old Nord neighbourhood, in Rotterdam, The Netherlands" title="Photo by Marc Kleen (https://unsplash.com/@marckleen) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reading list is not the final list of resources our interns used this year&lt;br&gt;
and we'll be releasing more resources as time passes, as part of a series.&lt;/p&gt;

</description>
      <category>readinglist</category>
      <category>resource</category>
      <category>internship</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Want to help people learn programming languages?</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Thu, 26 Sep 2019 02:19:15 +0000</pubDate>
      <link>https://dev.to/sleeplessbyte/want-to-help-people-learn-programming-languages-3l29</link>
      <guid>https://dev.to/sleeplessbyte/want-to-help-people-learn-programming-languages-3l29</guid>
      <description>&lt;p&gt;&lt;a href="https://exercism.io" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt; is an online platform designed to help you improve your coding skills through practice and mentorship. It currently provides &lt;em&gt;over 50 language tracks&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://exercism.io" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt; provides you with thousands of exercises spread across numerous language tracks. Once you start a language track you are presented with a core set of exercises to complete. Each one is a fun and interesting challenge designed to teach you a little more about the features of a language.&lt;/p&gt;

&lt;p&gt;At the moment of writing, I'm a maintainer of the &lt;a href="https://exercism.io/tracks/javascript" rel="noopener noreferrer"&gt;JavaScript&lt;/a&gt; and &lt;a href="https://exercism.io/tracks/typescript" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; track and &lt;a href="https://exercism.io/blog/track-anatomy-project" rel="noopener noreferrer"&gt;a while back&lt;/a&gt; we've started working on automating a part of the experience. &lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/xpbytes" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F797%2F47040c07-0898-4e54-9c16-174b0d9631b1.png" alt="XP Bytes"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F28162%2F6a23b5b8-ddca-4322-bf10-73b33bac4fa8.jpeg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/xpbytes/writing-a-code-analyzer-in-typescript-5ec3" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Writing a code analyzer in TypeScript (from scratch)&lt;/h2&gt;
      &lt;h3&gt;Derk-Jan Karrenbeld for XP Bytes ・ Jun 10 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;The post above talks extensively about how to write an analyzer and what went into this work.&lt;/p&gt;

&lt;p&gt;As part of &lt;strong&gt;Hacktoberfest&lt;/strong&gt;, I have updated the &lt;a href="https://github.com/exercism/javascript-analyzer/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;&lt;code&gt;javascript-analyzer&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/exercism/javascript/blob/17ed7e7487fd2a6f243b9bd304797e99dc4f0fa2/CONTRIBUTING.md" rel="noopener noreferrer"&gt;&lt;code&gt;javascript&lt;/code&gt;-track&lt;/a&gt; contributing guidelines. Other maintainers have done the same for their repositories.&lt;/p&gt;

&lt;h1&gt;
  
  
  What can you work on
&lt;/h1&gt;

&lt;p&gt;Because there are so many projects running at &lt;a href="https://exercism.io" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt;, there is also a lot you can work on. Here is a short list of the things I find the most interesting.&lt;/p&gt;

&lt;p&gt;I'm super biased, but with 160 repositories, and at least 90 active in the past month, there is plenty for anyone and everyone. &lt;/p&gt;

&lt;h2&gt;
  
  
  Help out your favourite language
&lt;/h2&gt;

&lt;p&gt;Given that we have over 50 &lt;em&gt;language&lt;/em&gt; tracks, your favourite language is possibly one of them. Many of them have open issues, and &lt;em&gt;all&lt;/em&gt; of them allow for &lt;em&gt;new exercises&lt;/em&gt; to be ported from other tracks. &lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/exercism/javascript/issues/660" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Checklist: exercises that could be implemented
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#660&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F1964376%3Fv%3D4" alt="SleeplessByte avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;SleeplessByte&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/exercism/javascript/issues/660" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 04, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hi there (new) contributors.&lt;/p&gt;
&lt;p&gt;The way this works is you can follow the link below to the problem specifications. This is the canonical data we have for this exercise. If you want a grasp of how this exercise might look, have a look at other tracks, where this exercise is implemented. You'll probably want to start with similar languages such as &lt;a href="https://github.com/exercism/typescript" rel="noopener noreferrer"&gt;&lt;code&gt;typescript&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/exercism/coffeescript" rel="noopener noreferrer"&gt;&lt;code&gt;coffeescript&lt;/code&gt;&lt;/a&gt;, and then perhaps other loosly-typed languages such as &lt;a href="https://github.com/exercism/ruby" rel="noopener noreferrer"&gt;&lt;code&gt;ruby&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://github.com/exercism/python" rel="noopener noreferrer"&gt;&lt;code&gt;python&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open a new issue, we'll label it with &lt;code&gt;new exercise ✨&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We'll assign the issue to you, so you get to work on this exercise&lt;/li&gt;
&lt;li&gt;Create a new folder in &lt;code&gt;/exercises&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You'll need to &lt;code&gt;sync&lt;/code&gt; this folder with the matching config files. You can use &lt;a href="https://github.com/exercism/javascript/blob/master/scripts/sync" rel="noopener noreferrer"&gt;&lt;code&gt;scripts/sync&lt;/code&gt;
&lt;/a&gt; to do this: &lt;code&gt;ASSIGNMENT=slug npx @babel/node scripts/sync&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;&amp;lt;slug&amp;gt;.js&lt;/code&gt; stub file.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;&amp;lt;slug&amp;gt;.spec.js&lt;/code&gt; test file. Here add the tests, per canonical data if possible.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;example.js&lt;/code&gt; file. Place a &lt;em&gt;working&lt;/em&gt; implementation, assuming it's renamed to &lt;code&gt;&amp;lt;slug&amp;gt;.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the tests locally, using &lt;a href="https://github.com/exercism/javascript/blob/master/scripts/test" rel="noopener noreferrer"&gt;&lt;code&gt;scripts/test&lt;/code&gt;&lt;/a&gt;: &lt;code&gt;ASSIGNMENT=slug npx @babel/node scripts/test&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open a PR.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Use &lt;a href="https://tracks.exercism.io/javascript/master/unimplemented" rel="nofollow noopener noreferrer"&gt;this&lt;/a&gt; link for a ⚡️ live list of unimplemented exercises.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/exercism/javascript/issues/660" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Write an analyzer, or help improving one
&lt;/h2&gt;

&lt;p&gt;There are currently &lt;strong&gt;17&lt;/strong&gt; (or more) analyzers! This means that there are many tracks &lt;em&gt;without&lt;/em&gt; any analyzer infrastructure. If you know a language well, you can help out with that. However, I would love your help on the &lt;a href="https://github.com/exercism/javascript-analyzer/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;&lt;code&gt;javascript-analyzer&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://github.com/exercism/typescript-analyzer/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;&lt;code&gt;typescript-analyzer&lt;/code&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write a complete new analyzer for an existing exercise. We will provide 500 &lt;code&gt;fixtures&lt;/code&gt; and what &lt;em&gt;should&lt;/em&gt; be approved and what shouldn't. We'll help writing some initial messaging, you don't need to worry about that.&lt;/li&gt;
&lt;li&gt;Help improving an existing analyzer. The coming week, more issues will be opened to indicate where improvement is required!&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/exercism/javascript-analyzer/issues/56" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Improve resistor-color-duo: detect unary +
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#56&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F1964376%3Fv%3D4" alt="SleeplessByte avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;SleeplessByte&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/exercism/javascript-analyzer/issues/56" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 26, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;&lt;strong&gt;Describe the improvement&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;When a solution has &lt;code&gt;+expression&lt;/code&gt; instead of &lt;code&gt;Number(expression)&lt;/code&gt;, and it's &lt;em&gt;otherwise optimal&lt;/em&gt;, we want to give a specific message. It should still &lt;em&gt;approve&lt;/em&gt;, but add a message that &lt;code&gt;Number(...)&lt;/code&gt; is preferred over unary &lt;code&gt;+&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which exercise&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;resistor-color-duo&lt;/code&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/exercism/javascript-analyzer/issues/56" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/exercism/javascript-analyzer/issues/55" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Improve resistor-color-duo: detect string concat
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#55&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F1964376%3Fv%3D4" alt="SleeplessByte avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;SleeplessByte&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/exercism/javascript-analyzer/issues/55" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 26, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;&lt;strong&gt;Describe the improvement&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;When the following main method is provided, the analyzer bails early:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-en"&gt;value&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;arr&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c1"&gt;COLORS&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;indexOf&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;arr&lt;/span&gt;&lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-c1"&gt;0&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s"&gt;""&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-c1"&gt;COLORS&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;indexOf&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;arr&lt;/span&gt;&lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-c1"&gt;1&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Instead, it should be caught by &lt;code&gt;hasDigitsString&lt;/code&gt;, and produce the same comment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which exercise&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;resistor-color-duo&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Additional context&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ResistorColorDuoSolution&lt;/code&gt; has a method that checks if an exercise &lt;em&gt;has a constructed string&lt;/em&gt;. It currently only detects a string template literal that looks like &lt;code&gt;${a}${b}&lt;/code&gt;, but we want to also capture the following:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s"&gt;`&lt;span class="pl-s1"&gt;&lt;span class="pl-kos"&gt;${&lt;/span&gt;&lt;span class="pl-s1"&gt;a&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/span&gt;`&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s"&gt;`&lt;span class="pl-s1"&gt;&lt;span class="pl-kos"&gt;${&lt;/span&gt;&lt;span class="pl-s1"&gt;b&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/span&gt;`&lt;/span&gt;
&lt;span class="pl-s1"&gt;a&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s"&gt;""&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;b&lt;/span&gt;
&lt;span class="pl-s1"&gt;a&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s"&gt;''&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;b&lt;/span&gt;
&lt;span class="pl-s"&gt;""&lt;/span&gt;  &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;a&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;b&lt;/span&gt;
&lt;span class="pl-s"&gt;''&lt;/span&gt;  &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;a&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;b&lt;/span&gt;
&lt;span class="pl-s1"&gt;a&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;toString&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;b&lt;/span&gt;
&lt;span class="pl-s1"&gt;a&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;toString&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-s1"&gt;b&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;toString&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
&lt;span class="pl-s1"&gt;a&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;toString&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;concat&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;b&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/exercism/javascript-analyzer/issues/55" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/exercism/javascript-analyzer/issues/53" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add analyzer for rna-transcription
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#53&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F1964376%3Fv%3D4" alt="SleeplessByte avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/SleeplessByte" rel="noopener noreferrer"&gt;SleeplessByte&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/exercism/javascript-analyzer/issues/53" rel="noopener noreferrer"&gt;&lt;time&gt;Sep 26, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;This issue is for discussion and assignment for the &lt;a href="https://github.com/exercism/javascript/tree/master/exercises/rna-transcription" rel="noopener noreferrer"&gt;&lt;code&gt;rna-transcription&lt;/code&gt;&lt;/a&gt; core exercise in the &lt;code&gt;javascript&lt;/code&gt; track.&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href="https://github.com/exercism/javascript/tree/master/exercises/rna-transcription" rel="noopener noreferrer"&gt;implementation&lt;/a&gt; | &lt;a href="https://github.com/exercism/website-copy/tree/master/tracks/javascript/exercises/rna-transcription/mentoring.md" rel="noopener noreferrer"&gt;mentor-notes&lt;/a&gt; | &lt;a href="https://github.com/exercism/problem-specifications/tree/master/exercises/rna-transcription" rel="noopener noreferrer"&gt;problem-specification&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This exercise focuses on&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;String&lt;/code&gt;&lt;/a&gt; iteration (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;String#replace&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;String#split&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;Object&lt;/code&gt;&lt;/a&gt;/&lt;code&gt;Map&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Optimal solution&lt;/h2&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-c1"&gt;TRANSCRIPTION&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;C&lt;/span&gt;: &lt;span class="pl-s"&gt;'G'&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;G&lt;/span&gt;: &lt;span class="pl-s"&gt;'C'&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;A&lt;/span&gt;: &lt;span class="pl-s"&gt;'U'&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;T&lt;/span&gt;: &lt;span class="pl-s"&gt;'A'&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;function&lt;/span&gt; &lt;span class="pl-en"&gt;toRna&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;sequence&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-s1"&gt;sequence&lt;/span&gt;
    &lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;split&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;''&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
    &lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;map&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-c1"&gt;TRANSCRIPTION&lt;/span&gt;&lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
    &lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;join&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;''&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Variations include &lt;code&gt;Set&lt;/code&gt; or &lt;code&gt;Map&lt;/code&gt; with &lt;code&gt;#get&lt;/code&gt;, which are valid!&lt;/p&gt;
&lt;h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Variations (approvable without comment)&lt;/h3&gt;
&lt;p&gt;String destructuring can also be used:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-kos"&gt;[&lt;/span&gt;...&lt;span class="pl-s1"&gt;sequence&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;map&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c"&gt;/**/&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;join&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;''&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace" rel="nofollow noopener noreferrer"&gt;String#replace&lt;/a&gt; can also be used:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-s1"&gt;sequence&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;replace&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-pds"&gt;/./g&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-c"&gt;/* */&lt;/span&gt;&lt;span class="pl-s1"&gt;&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Variations include replacing only the "known" nucleotides:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;sequence&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;replace&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-pds"&gt;/&lt;span class="pl-kos"&gt;[&lt;/span&gt;CGAT&lt;span class="pl-kos"&gt;]&lt;/span&gt;g/&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-c"&gt;/* */&lt;/span&gt;&lt;span class="pl-s1"&gt;&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Helper function variation&lt;/h3&gt;
&lt;p&gt;Instead of an anonymous function, a helper function may be used:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;function&lt;/span&gt; &lt;span class="pl-en"&gt;transcribe&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-c1"&gt;TRANSCRIPTION&lt;/span&gt;&lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This also allows for a version without a &lt;em&gt;mapping&lt;/em&gt; object:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;function&lt;/span&gt; &lt;span class="pl-en"&gt;transcribe&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;switch&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;nucleotide&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-k"&gt;case&lt;/span&gt; &lt;span class="pl-s"&gt;'C'&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-s"&gt;'G'&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt;
    &lt;span class="pl-k"&gt;case&lt;/span&gt; &lt;span class="pl-s"&gt;'G'&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-s"&gt;'C'&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt;
    &lt;span class="pl-k"&gt;case&lt;/span&gt; &lt;span class="pl-s"&gt;'A'&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-s"&gt;'U'&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt;
    &lt;span class="pl-k"&gt;case&lt;/span&gt; &lt;span class="pl-s"&gt;'T'&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-s"&gt;'A'&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;SHOULD comment and disapprove&lt;/h2&gt;
&lt;p&gt;Cases we &lt;em&gt;SHOULD&lt;/em&gt; comment on with this analyzer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;Object&lt;/code&gt;&lt;/a&gt; to keep track of the mapping instead of conditionals.&lt;/li&gt;
&lt;li&gt;Use iteration via &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;String#split&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;String#replace&lt;/code&gt;&lt;/a&gt; instead of using &lt;code&gt;for&lt;/code&gt;/&lt;code&gt;forEach&lt;/code&gt; with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;Array#push&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Discourage &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;Array#reduce&lt;/code&gt;&lt;/a&gt; for this particular solution, because it creates a lot of intermediary strings (more than the &lt;code&gt;split&lt;/code&gt; approach), except if the rest of the solution is correct (then you can mention it but approve). Using &lt;code&gt;reduce&lt;/code&gt; requires more interpretation by the reader to follow, change and maintain.&lt;/li&gt;
&lt;li&gt;Discourage &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;String#substring&lt;/code&gt;&lt;/a&gt; with foreach iteration, because character iteration via &lt;code&gt;split('')&lt;/code&gt; is more idiomatic and maintainable than &lt;code&gt;substring&lt;/code&gt; with 1. Using &lt;code&gt;split('')&lt;/code&gt; requires less interpretation by the reader to follow, change and maintain.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;Approach&lt;/h2&gt;
&lt;p&gt;The suggested approach is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;detect which &lt;em&gt;type&lt;/em&gt; of solution it is (switch, map, or for/forEach)&lt;/li&gt;
&lt;li&gt;make sure the &lt;em&gt;optimal solution&lt;/em&gt; is correctly handled. You can use the &lt;code&gt;batch&lt;/code&gt; runner to generate output for all fixtures.&lt;/li&gt;
&lt;li&gt;go from there by adding paths to disapprove.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/exercism/javascript-analyzer/issues/53" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Join the mentors
&lt;/h2&gt;

&lt;p&gt;Naturally, we are always looking for new mentors. You don't need to be an &lt;em&gt;expert&lt;/em&gt; in your language, but we'd love it if you have extensive experience. You'll be &lt;em&gt;coaching&lt;/em&gt; people on their journey to gain fluency. We also have a &lt;code&gt;#mentor-the-mentor&lt;/code&gt; program, to help you get better at mentoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the students!
&lt;/h2&gt;

&lt;p&gt;Know how to program in Java, but always wanted to learn Rust? Or maybe you finally make that step knowing TypeScript? Some tracks are currently &lt;em&gt;oversubscribed&lt;/em&gt;, but in general we welcome anyone to become a student. Note: this is &lt;em&gt;not&lt;/em&gt; a platform to &lt;em&gt;teach you how to code&lt;/em&gt;. It's a platform to &lt;em&gt;gain fluency in a &lt;strong&gt;new&lt;/strong&gt; language&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>contributorswanted</category>
      <category>exercism</category>
    </item>
    <item>
      <title>Tetris: Choosing the tools and setting up the project</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Sun, 14 Jul 2019 11:45:50 +0000</pubDate>
      <link>https://dev.to/sleeplessbyte/tetris-choosing-the-tools-and-setting-up-the-project-4kh6</link>
      <guid>https://dev.to/sleeplessbyte/tetris-choosing-the-tools-and-setting-up-the-project-4kh6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🔙 This is the &lt;em&gt;second instalment&lt;/em&gt; of a series on building a Tetris clone using React. If you've missed the first, find it &lt;a href="https://dev.to/sleeplessbyte/tetris-building-a-game-using-javascript-3j6f"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today we'll take a step towards starting the project. I'll discuss various options and choices which you might encounter when you're bootstrapping your own projects. It's important to talk about these - especially since a lot of tutorials and guides completely skip over the &lt;em&gt;why&lt;/em&gt; - and you'll notice that not everything is crystal clear of has a single way to move forward.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🎮 In this series I'll show you all the steps to build a Tetris clone, abiding by the &lt;a href="https://tetris.fandom.com/wiki/Tetris_Guideline" rel="noopener noreferrer"&gt;Tetris Guideline&lt;/a&gt;, the current specification that &lt;a href="https://tetris.fandom.com/wiki/The_Tetris_Company" rel="noopener noreferrer"&gt;The Tetris Company&lt;/a&gt; enforces for making all new (2001 and later) &lt;em&gt;Tetris&lt;/em&gt; game products alike in form.&lt;/p&gt;

&lt;p&gt;🛑 &lt;em&gt;Tetris&lt;/em&gt; is licensed which means that if you intend to take this series of articles to build your own arcade puzzler, make sure to abide by the law, if you intend to commercially release it. Even if you provide a clone for free, you could still get a cease and desist. &lt;a href="https://www.reddit.com/r/gamedev/comments/5kkk82/law_concerns_when_creating_a_game_inspired_by/" rel="noopener noreferrer"&gt;This reddit thread&lt;/a&gt; is pretty comprehensive how to go about this. Additionally, &lt;a href="https://arstechnica.com/gaming/2012/06/defining-tetris-how-courts-judge-gaming-clones/" rel="noopener noreferrer"&gt;this Ars Technica article&lt;/a&gt; talks in-depth about how courts judge gaming clones using &lt;em&gt;Tetris&lt;/em&gt; and the alleged clone &lt;em&gt;Mino&lt;/em&gt; as an example.&lt;/p&gt;

&lt;p&gt;📚 This series is purely meant as an educational, non-commercial resource. We'll only be using the &lt;em&gt;fandom wiki&lt;/em&gt; as a resource and only use the name Tetris to indicate the &lt;em&gt;type of game&lt;/em&gt; and not the actual company, game(s) or brand.&lt;/p&gt;
&lt;/blockquote&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkmddjw275q1tzeym5f74.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkmddjw275q1tzeym5f74.jpg" title="Photo by Carl Raw (https://unsplash.com/@carltraw) on Unsplash (https://unsplash.com/)" alt="Photo showing various machines in the Arcade "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Table of Contents&lt;/li&gt;
&lt;li&gt;The Game Engine&lt;/li&gt;
&lt;li&gt;
The Toolchain

&lt;ul&gt;
&lt;li&gt;Package management&lt;/li&gt;
&lt;li&gt;Bundler&lt;/li&gt;
&lt;li&gt;Compiler&lt;/li&gt;
&lt;li&gt;Linting and Styleguides&lt;/li&gt;
&lt;li&gt;Testing libraries&lt;/li&gt;
&lt;li&gt;Base Library&lt;/li&gt;
&lt;li&gt;Bootstrap&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Initialisation of the project&lt;/li&gt;

&lt;li&gt;Setting up &lt;code&gt;typescript&lt;/code&gt; correctly&lt;/li&gt;

&lt;li&gt;Setting up &lt;code&gt;babel&lt;/code&gt; correctly&lt;/li&gt;

&lt;li&gt;

Setting up &lt;code&gt;eslint&lt;/code&gt; correctly

&lt;ul&gt;
&lt;li&gt;Testing the &lt;code&gt;eslint&lt;/code&gt; configuration&lt;/li&gt;
&lt;li&gt;Fine-tuning the rules&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Setting up &lt;code&gt;jest&lt;/code&gt; correctly

&lt;ul&gt;
&lt;li&gt;Enabling &lt;code&gt;jest-dom&lt;/code&gt; extensions&lt;/li&gt;
&lt;li&gt;Getting a coverage report&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Setting up &lt;code&gt;prettier&lt;/code&gt; correctly

&lt;ul&gt;
&lt;li&gt;Automatically formatting&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Game Engine
&lt;/h2&gt;

&lt;p&gt;Since this series has a game as its deliverable, it can be wise to pick a game engine. As taken from the &lt;a href="https://en.wikipedia.org/wiki/Game_engine" rel="noopener noreferrer"&gt;WikiPedia article&lt;/a&gt;, a game engine is a software-development environment designed for people to build video games. There is an entire &lt;a href="https://en.wikipedia.org/wiki/List_of_game_engines" rel="noopener noreferrer"&gt;list of game engines&lt;/a&gt;, which isn't complete, and choosing which one to use for your game is such an endeavour that &lt;a href="https://www.youtube.com/watch?v=ibK3Ds7nDyk" rel="noopener noreferrer"&gt;many&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=2tZK75R2K2c" rel="noopener noreferrer"&gt;have&lt;/a&gt; &lt;a href="https://www.linkedin.com/pulse/how-choose-game-engine-yann-kronberg/" rel="noopener noreferrer"&gt;entire&lt;/a&gt; &lt;a href="https://www.technobyte.org/which-game-engine-should-you-choose/" rel="noopener noreferrer"&gt;articles&lt;/a&gt; &lt;a href="https://blackshellmedia.com/2016/09/29/6-crucial-questions-ask-choosing-game-engine/" rel="noopener noreferrer"&gt;or&lt;/a&gt; &lt;a href="https://www.youtube.com/watch?v=Tnci1hO0prc" rel="noopener noreferrer"&gt;video&lt;/a&gt; &lt;a href="http://mightyfingers.com/blog/11-steps-for-choosing-the-best-game-engine/" rel="noopener noreferrer"&gt;about it&lt;/a&gt;. In my opinion, if you're building a game, from scratch, and you have the time, potential and choice, you only need to ask yourself the following question:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do I ever want to go multiplayer? Pick &lt;a href="https://www.unrealengine.com/en-US/" rel="noopener noreferrer"&gt;Unreal Engine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Do I want to build a First-Person Shooter (single- or multiplayer)? Pick &lt;a href="https://www.unrealengine.com/en-US/" rel="noopener noreferrer"&gt;Unreal Engine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, pick &lt;a href="https://unity.com/" rel="noopener noreferrer"&gt;Unity&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm basing this on the hours and hours of &lt;a href="https://gdconf.com/" rel="noopener noreferrer"&gt;GDC&lt;/a&gt; talks, and job listings! There are many more interesting engines, but if you need something which other people will &lt;em&gt;trust&lt;/em&gt; and &lt;em&gt;be able to work with, quickly&lt;/em&gt;, you probably need to pick one of these two.&lt;/p&gt;

&lt;p&gt;If you're a one-person shop, and building for the web, there is a &lt;a href="https://github.com/collections/javascript-game-engines" rel="noopener noreferrer"&gt;collection of javascript game engines&lt;/a&gt;, including well-known options such as &lt;a href="https://www.yoyogames.com/gamemaker" rel="noopener noreferrer"&gt;GameMaker Studio (2)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;However&lt;/em&gt;, since this series is building a Tetris clone using &lt;em&gt;react&lt;/em&gt;, that is &lt;strong&gt;exactly&lt;/strong&gt; what I'll use. Ask yourself: is React the right tool for the job? Meh, probably not (because there are &lt;em&gt;better&lt;/em&gt; tools. Just because you can make something work, doesn't mean it was the right choice). Does that matter? It depends on the people you work with and the willingness of working around abstractions and challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Toolchain
&lt;/h2&gt;

&lt;p&gt;Since &lt;code&gt;react&lt;/code&gt; is supposed to be used for this project, it is likely that this project will be built as a JavaScript application. JavaScript projects (and libraries) tend to have a (sub)set of tools, which I refer to as the "toolchain".&lt;/p&gt;

&lt;h3&gt;
  
  
  Package management
&lt;/h3&gt;

&lt;p&gt;A package manager has its function it the name: it manages packages. JavaScript modules, as listed in your package &lt;em&gt;manifest&lt;/em&gt; (the collection of packages that the project depends on, for example listing an URL or a name, and version or version-range) are dependencies for your project. The current popular ones include &lt;a href="https://yarnpkg.com/en/" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt; and &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You might ask: "But don't I always need a package manager?" The answer to that is a short &lt;strong&gt;no&lt;/strong&gt;. You can also opt to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Including all your dependencies locally, for example by &lt;em&gt;vendoring&lt;/em&gt; (the act of storing dependencies locally to the project) them. This means you &lt;em&gt;always&lt;/em&gt; have a working copy, without the need for the interwebs.&lt;/li&gt;
&lt;li&gt;Use a runtime that doesn't use packages in the traditional sense, such as &lt;a href="https://deno.land/" rel="noopener noreferrer"&gt;deno&lt;/a&gt;, but also using &lt;a href="https://unpkg.com/" rel="noopener noreferrer"&gt;unpkg&lt;/a&gt;, which makes your HTML file the &lt;em&gt;dependency manifest&lt;/em&gt; and &lt;em&gt;manager&lt;/em&gt; in one.&lt;/li&gt;
&lt;li&gt;Use system packages such as &lt;code&gt;.deb&lt;/code&gt;ian packages, and manage dependencies using a system tool such as &lt;code&gt;make&lt;/code&gt; and a Makefile. This technically still uses a &lt;em&gt;package manager&lt;/em&gt;, but not in the same way as the &lt;code&gt;Yarn&lt;/code&gt; or &lt;code&gt;npm&lt;/code&gt; options.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 I'm choosing &lt;code&gt;Yarn&lt;/code&gt; with the package manifest inside &lt;code&gt;package.json&lt;/code&gt;. I think there are many valid reasons to pick any of the options above. I've used most of them myself, including now defunct tools such as &lt;a href="https://bower.io/" rel="noopener noreferrer"&gt;Bower&lt;/a&gt;. It often doesn't matter, and the decision should be made in line with company policies or project team alignment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Bundler
&lt;/h3&gt;

&lt;p&gt;A bundler in the JavaScript eco-system is not to be confused with the &lt;em&gt;package manager&lt;/em&gt; &lt;a href="https://bundler.io" rel="noopener noreferrer"&gt;bundler&lt;/a&gt; from the Ruby eco-system. In the JavaScript eco-system, it usually takes care of the following set of feature, or a sub-set thereof:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collecting all the assets in your project (JS, HTML, files, images, CSS)&lt;/li&gt;
&lt;li&gt;stripping out unused assets (think tree-shaking, dead code/import elimination)&lt;/li&gt;
&lt;li&gt;applying transformations (transpilation e.g. Babel, post processing e.g. PostCSS)&lt;/li&gt;
&lt;li&gt;outputting code bundles (chunks, code splitting, cache-friendly output)&lt;/li&gt;
&lt;li&gt;error logging (more friendly)&lt;/li&gt;
&lt;li&gt;hot module replacement (automatically updating modules / assets during development)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the tools I've used in the past and still use are &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt;, &lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;Parcel&lt;/a&gt;, &lt;a href="https://rollupjs.org/guide/en/" rel="noopener noreferrer"&gt;Rollup&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/microbundle" rel="noopener noreferrer"&gt;microbundle&lt;/a&gt;, &lt;a href="http://browserify.org/" rel="noopener noreferrer"&gt;Browserify&lt;/a&gt; and &lt;a href="https://brunch.io/" rel="noopener noreferrer"&gt;Brunch&lt;/a&gt;. The same &lt;em&gt;can be achieved&lt;/em&gt; using a task runner such as &lt;a href="https://gruntjs.com/" rel="noopener noreferrer"&gt;Grunt&lt;/a&gt; or using &lt;a href="https://gulpjs.com/" rel="noopener noreferrer"&gt;Gulp&lt;/a&gt;, but in my experience, those tend to get out of hand fast.&lt;/p&gt;

&lt;p&gt;The choice here, again, doesn't &lt;em&gt;really&lt;/em&gt; matter. I think they all have their strengths and weaknesses, and you should pick whichever you feel comfortable with. If you foresee you'll need to customise a lot, some will be favourable over others. If your team knows one of them better than the others, that will probably be favourable. In general: &lt;strong&gt;a great bundler is replaceable&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 I'm not choosing anything yet! I'll let the rest of the toolchain dictate what bundler I want to go with. If done right, it won't be &lt;em&gt;that&lt;/em&gt; costly to replace the bundler later. Perhaps I won't need &lt;em&gt;any&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Compiler
&lt;/h3&gt;

&lt;p&gt;Technically, babel is mostly a &lt;em&gt;transpiler&lt;/em&gt;, as it compiles code to the same level of abstraction (think JavaScript ESNext to JavaScript ES3). A &lt;em&gt;compiler&lt;/em&gt; generally compiles code to a lower level of abstraction (think Java to JVM / ByteCode, TypeScript to JavaScript). That said, &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; lists itself as a compiler, which it also is as it can remove TypeScript token from TypeScript code, yielding valid JavaScript&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 Since I want some type-safety, and I'm better at using &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; (which does come with a &lt;em&gt;compiler&lt;/em&gt; which also &lt;em&gt;transpiles&lt;/em&gt;) than &lt;a href="https://flow.org/" rel="noopener noreferrer"&gt;Flow&lt;/a&gt; (which is technically a static type checker and not a &lt;em&gt;compiler&lt;/em&gt; or &lt;em&gt;transpiler&lt;/em&gt;), I'm choosing TypeScript for &lt;em&gt;compilation&lt;/em&gt; to type-check and then use &lt;code&gt;babel&lt;/code&gt; to actually compile and then transpile the files to JavaScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Linting and Styleguides
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Lint_(software)" rel="noopener noreferrer"&gt;WikiPedia&lt;/a&gt;, Lint, or a linter, is a tool that analyses source code to flag programming errors, bugs, stylistic errors, and suspicious constructs. Since I'll be using &lt;code&gt;TypeScript&lt;/code&gt;, I'm at least looking for a code-linter.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 &lt;a href="https://palantir.github.io/tslint/" rel="noopener noreferrer"&gt;TSLint&lt;/a&gt; has been &lt;a href="https://medium.com/palantir/tslint-in-2019-1a144c2317a9" rel="noopener noreferrer"&gt;deprecated&lt;/a&gt;, as Microsoft has rolled out an amazing toolset which enables &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; to support Typescript, called &lt;a href="https://typescript-eslint.io/" rel="noopener noreferrer"&gt;&lt;code&gt;typescript-eslint&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also think that it's good practise to pick a coding style guide (e.g. do you use semicolons or not) and apply that to the project. Towards this goal, I'll use &lt;code&gt;prettier&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing libraries
&lt;/h3&gt;

&lt;p&gt;Alright, this one is also not groundbreaking. Whilst there are a lot of options here, such as &lt;a href="https://mochajs.org/" rel="noopener noreferrer"&gt;mocha&lt;/a&gt;, &lt;a href="https://jasmine.github.io/" rel="noopener noreferrer"&gt;jasmine&lt;/a&gt;, &lt;a href="https://github.com/substack/tape" rel="noopener noreferrer"&gt;tape&lt;/a&gt;, or one of my favourites &lt;a href="https://github.com/avajs/ava" rel="noopener noreferrer"&gt;AVA&lt;/a&gt;, I'll use &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;jest&lt;/a&gt;. I personally think it has all the great features I love from AVA, but because Facebook uses it internally, there is quite a bit of &lt;em&gt;React tooling&lt;/em&gt; that hooks perfectly into &lt;code&gt;jest&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Base Library
&lt;/h3&gt;

&lt;p&gt;There are currently multiple options when you want to develop in "react":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;react&lt;/code&gt;: &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;https://reactjs.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;preact&lt;/code&gt;: &lt;a href="https://preactjs.com/" rel="noopener noreferrer"&gt;https://preactjs.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;react-native-web&lt;/code&gt;: &lt;a href="https://github.com/necolas/react-native-web" rel="noopener noreferrer"&gt;https://github.com/necolas/react-native-web&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 Without going to deep into detail, since this series is focused on writing a game using &lt;code&gt;react&lt;/code&gt;, that's what I'll use; if there is a lot of ask by the end of the series, I'll write one about how to move from &lt;code&gt;react&lt;/code&gt; to &lt;code&gt;preact&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Bootstrap
&lt;/h3&gt;

&lt;p&gt;If you've read the &lt;a href="https://reactjs.org/docs/create-a-new-react-app.html" rel="noopener noreferrer"&gt;react docs&lt;/a&gt;, you might know that there are several "toolchains" out there. They are mostly wrappers providing a single Command-Line Interface (CLI) and come bundled with all the dependencies (tools), as listed above in the various categories. The React team primarily recommends a few solutions, and I tend to agree with them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you’re learning React or creating a new single-page app, use &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you’re building a server-rendered website with Node.js, try &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you’re building a static content-oriented website, try &lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you’re building a component library or integrating with an existing codebase, try &lt;a href="https://neutrinojs.org/" rel="noopener noreferrer"&gt;Neutrino&lt;/a&gt;, &lt;a href="https://github.com/insin/nwb" rel="noopener noreferrer"&gt;nwb&lt;/a&gt;, &lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;Parcel&lt;/a&gt; or &lt;a href="https://github.com/jaredpalmer/razzle" rel="noopener noreferrer"&gt;Razzle&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd like to throw &lt;a href="https://react-static.js.org" rel="noopener noreferrer"&gt;&lt;code&gt;react-static&lt;/code&gt;&lt;/a&gt; in the mix as well as an alternative to &lt;code&gt;next.js&lt;/code&gt; and &lt;code&gt;gatsby&lt;/code&gt;, which allows you to build super fast static content sites, hydrated with a react-app, without the requirement of using &lt;code&gt;GraphQL&lt;/code&gt; or a server.&lt;/p&gt;

&lt;p&gt;This is a very important decision, because if you choose to use a bootstrapped project with one of the toolchains above, you'll be &lt;em&gt;somewhat tied&lt;/em&gt; to their technologies, choice of configuration and general ideas. Most of the tools allow you to &lt;em&gt;eject&lt;/em&gt; (to stop using the built-in defaults), but you'll still have to to a lot of work to move away.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 The project (Tetris clone) is probably completely feasible without a complete bootstrapped toolchain. That's why I've chosen &lt;em&gt;not&lt;/em&gt; to use one of the bootstrapping toolchains. Often I run into &lt;em&gt;meh&lt;/em&gt; behaviour when I need to add something that it currently doesn't support correctly out of the box, when I try to upgrade dependencies or anything similar. If I end up needing it, I can always add it later!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Initialisation of the project
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create the directory for this new project&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;tetreact

&lt;span class="c"&gt;# Move into that directory&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;tetreact

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
yarn add react react-dom

&lt;span class="c"&gt;# Install development dependencies (explanation below)&lt;/span&gt;
yarn add typescript core-js@3 eslint eslint-config-prettier eslint-plugin-import &lt;span class="nt"&gt;-D&lt;/span&gt;
yarn add eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks &lt;span class="nt"&gt;-D&lt;/span&gt;
yarn add jest babel-jest prettier @babel/cli @babel/core @babel/preset-env &lt;span class="nt"&gt;-D&lt;/span&gt;
yarn add @babel/preset-react @babel/preset-typescript @typescript-eslint/eslint-plugin &lt;span class="nt"&gt;-D&lt;/span&gt;
yarn add @typescript-eslint/parser @testing-library/react @testing-library/jest-dom &lt;span class="nt"&gt;-D&lt;/span&gt;
yarn add @types/jest @types/react @types/react-dom &lt;span class="nt"&gt;-D&lt;/span&gt;

&lt;span class="c"&gt;# Make this a git repository&lt;/span&gt;
git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is why the following packages are being installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt; are runtime packages for react,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;typescript&lt;/code&gt;: used to type-check the &lt;code&gt;ts&lt;/code&gt; and &lt;code&gt;tsx&lt;/code&gt; files,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;core-js&lt;/code&gt;: a library that polyfills features. There is an older, version (&lt;code&gt;@2&lt;/code&gt;) and a newer version (&lt;code&gt;@3&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint&lt;/code&gt;: the core package for the linter,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-config-prettier&lt;/code&gt;: turns off conflicting, stylistic rules that are handled by prettier,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-import&lt;/code&gt;: adds rules and linting of &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;export&lt;/code&gt; statements,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&gt;: adds accessibility rules on JSX elements,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-react&lt;/code&gt;: adds React specific linting rules,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt;: adds React Hooks specific linting rules,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jest&lt;/code&gt;: the testing framework,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;babel-jest&lt;/code&gt;: makes it possible to run the test code &lt;em&gt;through babel&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/cli&lt;/code&gt;: allows me to run babel as a standalone command from the command line,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/core&lt;/code&gt;: the core package for Babel,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-env&lt;/code&gt;: preset to determine which transformations need to be applied on the code, based on a list of browsers,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-react&lt;/code&gt;: preset that allows transpilation of JSX and ensures React's functional component's property &lt;code&gt;displayName&lt;/code&gt; is correctly set,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-typescript&lt;/code&gt;: allows stripping TypeScript type tokens from files, leaving behind valid JavaScript,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@typescript-eslint/eslint-plugin&lt;/code&gt;: adds a lot of rules for linting TypeScript,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@typescript-eslint/parser&lt;/code&gt;: allows &lt;code&gt;eslint&lt;/code&gt; to use the TypeScript ESLint parser (which knows about type tokens),&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@testing-library/react&lt;/code&gt;: adds officially recommended testing library, for react,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@testing-library/jest-dom&lt;/code&gt;: adds special matchers for &lt;code&gt;jest&lt;/code&gt; and the DOM,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@types/*&lt;/code&gt;: type definitions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might think: "jee, that's a lot of dependencies", and yep, it's quite a few. However, when using something like &lt;code&gt;create-react-app&lt;/code&gt;, you are installing &lt;em&gt;the same if not more&lt;/em&gt; dependencies, as these are dependencies of the &lt;code&gt;react-scripts&lt;/code&gt; project you'll be depending on. I've spent quite some time on getting this list to where it is, but feel free to make your own changes and/or additions.&lt;/p&gt;

&lt;p&gt;Normally I would add these dependencies as I go, but I already did all the steps listed below, so I collected all the dependencies and listed them in two single commands for you to copy and paste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up &lt;code&gt;typescript&lt;/code&gt; correctly
&lt;/h2&gt;

&lt;p&gt;The following is to setup &lt;code&gt;typescript&lt;/code&gt;. The dependencies added for this are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;typescript&lt;/code&gt;: provides the &lt;code&gt;tsc&lt;/code&gt; typescript compiler and allows you to have a project version, different from a version e.g. bundled with your IDE or text editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the &lt;code&gt;tsc --init&lt;/code&gt; command in order to create the &lt;code&gt;tsconfig.json&lt;/code&gt; with the default settings.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now I need to make a few changes, all of which are explained below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-  // "incremental": true,
&lt;/span&gt;&lt;span class="gi"&gt;+  "incremental": true
&lt;/span&gt;&lt;span class="gd"&gt;-  // "target": "es5",
&lt;/span&gt;&lt;span class="gi"&gt;+  "target": "esnext",
&lt;/span&gt;&lt;span class="gd"&gt;-  // "jsx": "preserve",
&lt;/span&gt;&lt;span class="gi"&gt;+  "jsx": "preserve",
&lt;/span&gt;&lt;span class="gd"&gt;-  // "noEmit": true,
&lt;/span&gt;&lt;span class="gi"&gt;+  "noEmit": true,
&lt;/span&gt;&lt;span class="gd"&gt;-  // "isolatedModules": true,
&lt;/span&gt;&lt;span class="gi"&gt;+  "isolatedModules": true,
&lt;/span&gt;&lt;span class="gd"&gt;-  // "moduleResolution": "node",
&lt;/span&gt;&lt;span class="gi"&gt;+  "moduleResolution": "node",
&lt;/span&gt;&lt;span class="gd"&gt;-  // "allowSyntheticDefaultImports": true,
&lt;/span&gt;&lt;span class="gi"&gt;+  "allowSyntheticDefaultImports": true,
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember, the goal is to have &lt;code&gt;tsc&lt;/code&gt; type-check the codebase. That means there doesn't need to be an output, hence &lt;code&gt;noEmit&lt;/code&gt;. Furthermore, it doesn't need to spend time transpiling to an older JavaScript, because &lt;code&gt;babel&lt;/code&gt; will take care of that, which means it can have an &lt;code&gt;esnext&lt;/code&gt; target. For the same reason, &lt;code&gt;jsx&lt;/code&gt; is set to &lt;code&gt;preserve&lt;/code&gt; and &lt;strong&gt;not&lt;/strong&gt; &lt;code&gt;react&lt;/code&gt;. Babel will take care of that. Then there are a few options that make interoptability with other packages easier. Finally, &lt;code&gt;isolatedModules&lt;/code&gt; is required for the TypeScript over Babel functionality to work correctly.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;code&gt;package.json&lt;/code&gt; needs to get the &lt;code&gt;"scripts"&lt;/code&gt; key with a command that runs the type-checking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+  "scripts": {
+    "lint:types": "yarn tsc"
+  }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;yarn lint:types&lt;/code&gt; should yield the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error TS18003: No inputs were found in config file 'path/to/tetreact/tsconfig.json'. Specified
'include' paths were '["**/*"]' and 'exclude' paths were '[]'.


Found 1 error.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the correct error. There is nothing to compile! Let's add that:&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="nb"&gt;mkdir &lt;/span&gt;src
&lt;span class="nb"&gt;touch &lt;/span&gt;src/App.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;yarn lint:types&lt;/code&gt; should yield the following errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules/@types/babel__template/index.d.ts:16:28 - error TS2583: Cannot find name 'Set'. Do
you need to change your target library? Try changing the `lib` compiler option to es2015 or later.

16     placeholderWhitelist?: Set&amp;lt;string&amp;gt;;
                              ~~~

node_modules/@types/react/index.d.ts:377:23 - error TS2583: Cannot find name 'Set'. Do you need
to change your target library? Try changing the `lib` compiler option to es2015 or later.

377         interactions: Set&amp;lt;SchedulerInteraction&amp;gt;,
                          ~~~

src/App.tsx:1:1 - error TS1208: All files must be modules when the '--isolatedModules' flag is
provided.

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

&lt;/div&gt;



&lt;p&gt;Let's start at the first two. These give an explicit option to fix the error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-  // "lib": [],
&lt;/span&gt;&lt;span class="gi"&gt;+  "lib": ["dom", "es2015"],
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is very similar to setting the correct &lt;code&gt;env&lt;/code&gt; in your &lt;code&gt;.eslintrc&lt;/code&gt; configuration file: I need to tell TypeScript that I'm in a browser environment (&lt;code&gt;dom&lt;/code&gt;) and that it should be able to access those constructs that have been introduced in &lt;code&gt;es2015&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The final error is because of the &lt;code&gt;--isolatedModules&lt;/code&gt; flag. When running the compiler with this flag/option, each file &lt;em&gt;expects&lt;/em&gt; to be its own, free-standing module. A file is &lt;em&gt;only&lt;/em&gt; a module if it &lt;code&gt;import&lt;/code&gt;s or &lt;code&gt;export&lt;/code&gt;s something. The reason for this flag isn't apparent: It's listed on the &lt;a href="https://babeljs.io/docs/en/babel-plugin-transform-typescript" rel="noopener noreferrer"&gt;documentation of &lt;code&gt;@babel/plugin-transform-typescript&lt;/code&gt;&lt;/a&gt; as one of the caveats of "compiling" TypeScript using Babel. I have advanced knowledge here, but it would become clear in the next step.&lt;/p&gt;

&lt;p&gt;I update the &lt;code&gt;src/App.tsx&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;export&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="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello world&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, &lt;code&gt;tsc&lt;/code&gt; does &lt;em&gt;not complain&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up &lt;code&gt;babel&lt;/code&gt; correctly
&lt;/h2&gt;

&lt;p&gt;Next up is making sure that &lt;code&gt;babel&lt;/code&gt; "compiles" the TypeScript code to JavaScript, applies transformations and hooks into the various plugins that I've installed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;core-js@3&lt;/code&gt;: a library that polyfills features. There is an older, version (&lt;code&gt;@2&lt;/code&gt;) and a newer version (&lt;code&gt;@3&lt;/code&gt;); it uses used by &lt;code&gt;@babel/preset-env&lt;/code&gt; in conjunction with a &lt;code&gt;browerlist&lt;/code&gt; configuration,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/cli&lt;/code&gt;: allows me to run babel as a standalone command from the command line,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/core&lt;/code&gt;: the core package for Babel,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-env&lt;/code&gt;: preset to determine which transformations need to be applied on the code, based on a list of browsers,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-react&lt;/code&gt;: preset that allows transpilation of JSX and ensures React's functional component's property &lt;code&gt;displayName&lt;/code&gt; is correctly set,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@babel/preset-typescript&lt;/code&gt;: allows stripping TypeScript type tokens from files, leaving behind valid JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Babel currently, at moment of writing, does not have an &lt;code&gt;--init&lt;/code&gt; command, but setting it up is not very complicated, albeit it takes some effort to get all the presets and plugins correctly listed. Since this is a &lt;em&gt;project&lt;/em&gt;, per &lt;a href="https://babeljs.io/docs/en/configuration#what-s-your-use-case" rel="noopener noreferrer"&gt;the babel documentation&lt;/a&gt;, the best way for this project is to create a &lt;code&gt;JSON&lt;/code&gt; configuration, called &lt;code&gt;.babelrc&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .babelrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The contents are as follows, which I collected by taking the documentation of the three &lt;code&gt;@babel/preset-*&lt;/code&gt; plugins and applying them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"presets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-env"&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;"targets"&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;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"current"&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;"useBuiltIns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"corejs"&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-typescript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-react"&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;"ignore"&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;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="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;It's also a good idea to explicitly define the &lt;code&gt;browserlists&lt;/code&gt; key/configuration, even though since I'm building a cross-env cross-browser game, the setting can stay on &lt;code&gt;defaults&lt;/code&gt;. In order to do that, and in order to be abel to call &lt;code&gt;babel&lt;/code&gt; using &lt;code&gt;@babel/cli&lt;/code&gt;, in &lt;code&gt;package.json&lt;/code&gt;, I added the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   {
     "scripts": {
&lt;span class="gi"&gt;+      "build": "yarn babel src --out-dir dist --extensions \".ts,.tsx\"",
+      "watch": "yarn build --watch",
&lt;/span&gt;       "lint:types": "yarn tsc"
     },
     "dependencies": {
&lt;span class="err"&gt;
&lt;/span&gt;  ...
&lt;span class="err"&gt;
&lt;/span&gt;       "typescript": "^3.5.3"
     },
&lt;span class="gi"&gt;+    "browserslist": [
+      "defaults"
+    ]
&lt;/span&gt;   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want a different target, make sure to follow the &lt;a href="https://github.com/browserslist/browserslist#best-practices" rel="noopener noreferrer"&gt;Browserlist best practices&lt;/a&gt;. You can also use a configuration file; pick whichever you like.&lt;/p&gt;

&lt;p&gt;Let's see if this works!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn build
yarn run v1.16.0
warning package.json: No license field
&lt;span class="nv"&gt;$ &lt;/span&gt;babel src &lt;span class="nt"&gt;--out-dir&lt;/span&gt; dist &lt;span class="nt"&gt;--extensions&lt;/span&gt; &lt;span class="s2"&gt;".ts,.tsx"&lt;/span&gt;
Successfully compiled 1 file with Babel.
Done &lt;span class="k"&gt;in &lt;/span&gt;1.67s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;dist&lt;/code&gt; I can now find &lt;code&gt;App.js&lt;/code&gt;, which does not have any type information. It should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__esModule&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;_react&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_interopRequireDefault&lt;/span&gt;&lt;span class="p"&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="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;function&lt;/span&gt; &lt;span class="nf"&gt;_interopRequireDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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;obj&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__esModule&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="p"&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_react&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things to notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It added &lt;code&gt;"use strict";&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It is using the &lt;code&gt;interopRequireDefault&lt;/code&gt; to require &lt;code&gt;react&lt;/code&gt;'s default export&lt;/li&gt;
&lt;li&gt;It transpiled &lt;code&gt;JSX&lt;/code&gt; to use &lt;code&gt;_react.default.createElement&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These three things would only happen if Babel is configured correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up &lt;code&gt;eslint&lt;/code&gt; correctly
&lt;/h2&gt;

&lt;p&gt;Next step is making sure that the TypeScript code can be linted!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;eslint&lt;/code&gt;: the core package for the linter,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-config-prettier&lt;/code&gt;: turns off conflicting, stylistic rules that are handled by prettier,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-import&lt;/code&gt;: adds rules and linting of &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;export&lt;/code&gt; statements,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&gt;: adds accessibility rules on JSX elements,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-react&lt;/code&gt;: adds React specific linting rules,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt;: adds React Hooks specific linting rules,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@typescript-eslint/eslint-plugin&lt;/code&gt;: adds a lot of rules for linting TypeScript,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@typescript-eslint/parser&lt;/code&gt;: allows &lt;code&gt;eslint&lt;/code&gt; to use the TypeScript ESLint parser (which knows about type tokens).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;eslint&lt;/code&gt; core package comes with a CLI tool to initialise (and run) &lt;code&gt;eslint&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn eslint --init

? How would you like to use ESLint? To check syntax and find problems
? What type of modules does your project use? JavaScript modules (import/export)
? Which framework does your project use? React
? Where does your code run? Browser
? What format do you want your config file to be in? JSON

Successfully created .eslintrc.json file in path/to/tetreact
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on your configuration, and depending if you call &lt;code&gt;yarn eslint&lt;/code&gt; (execute &lt;code&gt;eslint&lt;/code&gt; from the local &lt;code&gt;node_modules&lt;/code&gt;) or plain &lt;code&gt;eslint&lt;/code&gt; (which might call the "globally" installed &lt;code&gt;eslint&lt;/code&gt;), the following message &lt;em&gt;may&lt;/em&gt; appear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The config that you've selected requires the following dependencies:

eslint-plugin-react@latest

? Would you like to install them now with npm? No
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I choose &lt;code&gt;"No"&lt;/code&gt; because on one hand, it's already installed under &lt;code&gt;devDependencies&lt;/code&gt; and on the other hand, it will try to use &lt;code&gt;npm&lt;/code&gt; to install it if I say &lt;code&gt;"yes"&lt;/code&gt; (at moment of writing), which is something I don't want (as I am using &lt;code&gt;yarn&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;As for the options: I personally like the &lt;code&gt;.json&lt;/code&gt; file, because it restricts me from solving something using &lt;code&gt;JavaScript&lt;/code&gt;, which makes the barrier to do something "hackly" a bit higher. I basically guard myself from trying to do something that is not supported out of the box. Your mileage may vary, but I like to use my dependencies with standard configuration, because it makes it easier to search for solutions &lt;em&gt;and&lt;/em&gt; ask for support!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🛑 If you run into an error that looks like this:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ESLint couldn't find the plugin "eslint-plugin-react". This can happen for a
couple different reasons:
...
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Even though it &lt;em&gt;is&lt;/em&gt; installed locally, remove &lt;code&gt;eslint&lt;/code&gt; from the global packages:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn global remove eslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;If you're using an IDE with &lt;code&gt;eslint&lt;/code&gt; integration set-up, chances are that both &lt;code&gt;App.js&lt;/code&gt; (in the &lt;code&gt;dist&lt;/code&gt; folder) ánd &lt;code&gt;App.tsx&lt;/code&gt; (in the &lt;code&gt;src&lt;/code&gt; folder) light up with errors. &lt;strong&gt;This is to be expected&lt;/strong&gt;. It doesn't automagically configure &lt;code&gt;.eslintrc.json&lt;/code&gt; with all the plugins from your &lt;code&gt;devDependencies&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In order to get all the configurtion in, I edit the generated &lt;code&gt;.eslintrc.json&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, I mark the configuration as the &lt;code&gt;root&lt;/code&gt; configuration. This prohibits any &lt;code&gt;eslint&lt;/code&gt; configuration somewhere up the tree to apply rules to this project.&lt;/li&gt;
&lt;li&gt;Next, I update the &lt;code&gt;parserOptions&lt;/code&gt; and tell it to use the &lt;code&gt;@typescript-eslint/parser&lt;/code&gt; parser. My &lt;a href="https://dev.to/xpbytes/writing-a-code-analyzer-in-typescript-5ec3"&gt;article&lt;/a&gt; on &lt;a href="https://dev.to/xpbytes/writing-a-code-analyzer-in-typescript-5ec3"&gt;writing a TypeScript code Analyzer&lt;/a&gt; goes into a bit more detail on what the different &lt;code&gt;@typescript-eslint/*&lt;/code&gt; packages are and do.&lt;/li&gt;
&lt;li&gt;Finally, there are all the &lt;code&gt;extends&lt;/code&gt;. These take preset configurations that I want to apply to this configuration. The &lt;code&gt;@typescript-eslint/*&lt;/code&gt; and &lt;code&gt;prettier/*&lt;/code&gt; modules have documentation that explains &lt;em&gt;in what order&lt;/em&gt; these should be placed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   {
&lt;span class="gi"&gt;+    "root": true,
+    "parser": "@typescript-eslint/parser",
&lt;/span&gt;     "parserOptions": {
&lt;span class="gi"&gt;+      "project": "./tsconfig.json",
+      "ecmaFeatures": {
+        "jsx": true
+      },
&lt;/span&gt;       "ecmaVersion": 2018,
       "sourceType": "module"
     },
     "env": {
       "browser": true,
       "es6": true
     },
&lt;span class="gd"&gt;-    "extends": "eslint:recommended"
&lt;/span&gt;&lt;span class="gi"&gt;+    "extends": [
+      "eslint:recommended",
+      "plugin:@typescript-eslint/eslint-recommended",
+      "plugin:@typescript-eslint/recommended"
+      "plugin:react/recommended",
+      "prettier",
+      "prettier/@typescript-eslint",
+      "prettier/babel",
+      "prettier/react"
+    ],
&lt;/span&gt;     "globals": {
       "Atomics": "readonly",
       "SharedArrayBuffer": "readonly"
     },
     "plugins": [
&lt;span class="gd"&gt;-      "react",
&lt;/span&gt;&lt;span class="gi"&gt;+      "@typescript-eslint",
+      "react-hooks",
&lt;/span&gt;     ],
     "rules": {
     },
&lt;span class="gi"&gt;+    "settings": {
+      "react": {
+        "version": "detect"
+      }
+    }
&lt;/span&gt;   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;rules&lt;/code&gt; are currently still empty, I'll get to that. First, let's test the configuration!&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the &lt;code&gt;eslint&lt;/code&gt; configuration
&lt;/h3&gt;

&lt;p&gt;I change &lt;code&gt;src/App.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+  function Header() {
+    return &amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;
+  }
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;   export function App(): JSX.Element {
&lt;span class="gd"&gt;-    return &amp;lt;div&amp;gt;Hello World!&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+    return &amp;lt;Header /&amp;gt;
&lt;/span&gt;   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add a new &lt;code&gt;scripts&lt;/code&gt; entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   "scripts" {
     "build": "yarn babel src --out-dir dist --extensions \".ts,.tsx\"",
      "watch": "yarn build --watch",
&lt;span class="gi"&gt;+     "lint": "yarn eslint src/**/*",
&lt;/span&gt;      "lint:types": "yarn tsc"
   },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I run it!&lt;br&gt;
&lt;/p&gt;

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

$ eslint src/**/*

path/to/tetreact/src/App.tsx
  3:1  warning  Missing return type on function  @typescript-eslint/explicit-function-return-type

✖ 1 problem (0 errors, 1 warning)

Done in 4.01s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Woopdiedo. A warning from the &lt;code&gt;@typescript-eslint&lt;/code&gt; plugin! This is exactly what I expect to see, so I can now move on fine-tuning the &lt;code&gt;"rules"&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fine-tuning the rules
&lt;/h3&gt;

&lt;p&gt;Normally I fine-tune the &lt;code&gt;"rules"&lt;/code&gt; as I develop a library or a project, or I use a set of rules that is pre-determined by a project lead. In the &lt;a href="https://github.com/exercism/javascript-analyzer" rel="noopener noreferrer"&gt;exercism/javascript-analyzer respository&lt;/a&gt;, I've &lt;a href="https://github.com/exercism/javascript-analyzer/blob/b32e6dc67842c4edad6f75e9b8909bf5d2ac6926/docs/linting.md" rel="noopener noreferrer"&gt;added a document&lt;/a&gt; about the rules and why I chose them to be like this. The results are as listed below, which include the two &lt;code&gt;react-hooks&lt;/code&gt; rules at the bottom.&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;"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;"@typescript-eslint/explicit-function-return-type"&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;"warn"&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;"allowExpressions"&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;"allowTypedFunctionExpressions"&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;"allowHigherOrderFunctions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/explicit-member-accessibility"&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;"warn"&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;"accessibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no-public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"overrides"&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;"accessors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"explicit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"constructors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no-public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"methods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"explicit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"explicit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"parameterProperties"&lt;/span&gt;&lt;span class="p"&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;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/indent"&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;"error"&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;"@typescript-eslint/no-non-null-assertion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/no-parameter-properties"&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;"warn"&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;"allows"&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;"private"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"protected"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"private readonly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"protected readonly"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public readonly"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/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;"off"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@typescript-eslint/no-use-before-define"&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;"error"&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;"functions"&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;"typedefs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react-hooks/rules-of-hooks"&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;"react-hooks/exhaustive-deps"&lt;/span&gt;&lt;span class="p"&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="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;As I write more code, this ruleset may change, but for now this should suffice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up &lt;code&gt;jest&lt;/code&gt; correctly
&lt;/h2&gt;

&lt;p&gt;Next up is making sure the code is testable.&lt;/p&gt;

&lt;p&gt;I personally &lt;em&gt;don't&lt;/em&gt; like to co-locate my test files next to my source files, but rather put all the tests in a separate directory. However this isn't better or preferred, just different. You can do whichever you like. If you co-locate the tests, make sure that your tests end with &lt;code&gt;.test.ts&lt;/code&gt; or &lt;code&gt;.test.tsx&lt;/code&gt;, and if you don't, the &lt;em&gt;default&lt;/em&gt; folder is &lt;code&gt;__tests__&lt;/code&gt;. You can change these in the, soon to be, generated &lt;code&gt;jest.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The dependencies that matter are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jest&lt;/code&gt;: the testing framework,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;babel-jest&lt;/code&gt;: makes it possible to run the test code &lt;em&gt;through babel&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@testing-library/react&lt;/code&gt;: adds officially recommended testing library, for react,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@testing-library/jest-dom&lt;/code&gt;: adds special matchers for &lt;code&gt;jest&lt;/code&gt; and the DOM,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just like some of the other tools, &lt;code&gt;jest&lt;/code&gt; comes with a CLI and an option that allows you to &lt;em&gt;generate&lt;/em&gt; the configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn jest --init

√ Would you like to use Jest when running "test" script in "package.json"? ... yes
√ Choose the test environment that will be used for testing » jsdom (browser-like)
√ Do you want Jest to add coverage reports? ... yes
√ Automatically clear mock calls and instances between every test? ... no
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds the &lt;code&gt;test&lt;/code&gt; script to &lt;code&gt;"scripts"&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt; and adds a &lt;code&gt;jest.config.js&lt;/code&gt; file with defaults to the root directory.&lt;br&gt;
The contents of the configuration file are all set correctly (given the answers as listed above), with the important ones being (you can go in and confirm):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;coverageDirectory&lt;/code&gt; should be set to &lt;code&gt;"coverage"&lt;/code&gt;, because I want coverage reports,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;testEnvironment&lt;/code&gt; should not be set or set to &lt;code&gt;"jest-environment-jsdom"&lt;/code&gt;, because I don't want to &lt;em&gt;have&lt;/em&gt; to run in a browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;babel-jest&lt;/code&gt; package is &lt;em&gt;automagically&lt;/em&gt; supported, out-of-the-box, without needing to set-up anything else. Since Babel is already configured correctly to "compile" the source code, and the test code has the same properties, no steps need to be taken in order to make the tests be "compiled" as well.&lt;/p&gt;

&lt;p&gt;Then I want to integrate with the &lt;code&gt;@testing-library/react&lt;/code&gt; library, which provides a cleanup script that makes sure the &lt;code&gt;React&lt;/code&gt; application state and environment is reset (cleaned-up) after each test. Instead of including this in every test, it can be setup via the &lt;code&gt;jest.config.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-  // setupFilesAfterEnv: []
&lt;/span&gt;&lt;span class="gi"&gt;+  setupFilesAfterEnv: [
+    '@testing-library/react/cleanup-after-each'
+  ],
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use the default folder name for my tests:&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="nb"&gt;mkdir &lt;/span&gt;__tests__
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now I create a smoke test &lt;code&gt;__tests__/App.tsx&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App renders heading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Hi/&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&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;Finally I run the tests using the &lt;code&gt;"scripts"&lt;/code&gt; command that was added by &lt;code&gt;yarn jest --init&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

$ jest
 FAIL  __tests__/App.tsx
  × App renders heading (29ms)

  ● App renders heading

    expect(received).toBeTruthy()

    Received: null

      14 |   );
      15 |
    &amp;gt; 16 |   expect(queryByText(/Hi/)).toBeTruthy();
         |                             ^
      17 | });
      18 |

      at Object.toBeTruthy (__tests__/App.tsx:16:29)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        4.361s
Ran all test suites.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ah. I'm rendering &lt;code&gt;Hello World&lt;/code&gt;, and not &lt;code&gt;Hi&lt;/code&gt;. So now I change the regular expression to test for &lt;code&gt;Hello World&lt;/code&gt; instead, and run the tests again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ jest
 PASS  __tests__/App.tsx
  √ App renders heading (21ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.184s
Ran all test suites.
Done in 6.10s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enabling &lt;code&gt;jest-dom&lt;/code&gt; extensions
&lt;/h3&gt;

&lt;p&gt;You might have noticed that there is another &lt;code&gt;@testing-library&lt;/code&gt; dependency. I want to use the &lt;code&gt;'@testing-library/jest-dom/extend-expect'&lt;/code&gt; visibility check &lt;code&gt;toBeVisible&lt;/code&gt;, instead of only testing if it exists via &lt;code&gt;toBeTruthy&lt;/code&gt;. I order to integrate with that package, I make the following change to the &lt;code&gt;jest.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   setupFilesAfterEnv: [
     '@testing-library/react/cleanup-after-each',
&lt;span class="gi"&gt;+    '@testing-library/jest-dom/extend-expect',
&lt;/span&gt;   ],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This change makes the extension (new matchers, including &lt;code&gt;.toBeVisible&lt;/code&gt;) available to all the tests.&lt;/p&gt;

&lt;p&gt;I update the test to use these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   import React from 'react'
   import { render } from '@testing-library/react'
   import { App } from '../src/App'
&lt;span class="err"&gt;
&lt;/span&gt;   it('App renders heading', () =&amp;gt; {
     const { container, queryByText } = render(
       &amp;lt;App /&amp;gt;,
     );
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;-    expect(queryByText(/Hello World/)).toBeTruthy()
&lt;/span&gt;&lt;span class="gi"&gt;+    expect(queryByText(/Hello World/)).toBeVisible()
&lt;/span&gt;   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the tests works, but my IDE gives an error on the &lt;code&gt;toBeVisible&lt;/code&gt; matcher. This is because TypeScript doesn't quite know that the &lt;code&gt;expect&lt;/code&gt; matchers have been extended. It's not good at inferring new types from &lt;em&gt;dynamically executed code&lt;/em&gt;. Since there is no &lt;em&gt;cross-file&lt;/em&gt; information between the &lt;code&gt;jest&lt;/code&gt; configuration and this test, I can't expect that to be magically picked up. Fortunately, there are various ways to solve this, for example, but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;import '@testing-library/jest-dom/extend-expect'&lt;/code&gt; to each test file. This extends the &lt;code&gt;expect()&lt;/code&gt; Matchers to include those provided by the library,&lt;/li&gt;
&lt;li&gt;Make sure &lt;code&gt;typescript&lt;/code&gt; knows this is always included (which is true, given the &lt;code&gt;jest.config.js&lt;/code&gt; changes).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to get the "always included" experience, I add a new file &lt;code&gt;declarations.d.ts&lt;/code&gt; and add a &lt;em&gt;triple-slash directive&lt;/em&gt;. I generally stay clear of these directives, and even have an &lt;code&gt;eslint&lt;/code&gt; rule to disallow them, but in my experience, tooling is best when you run into something like this issue and use them. This might not be true if you follow this post some time in the future. You can do whatever works, perhaps an &lt;code&gt;import&lt;/code&gt; suffices:&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="nb"&gt;touch &lt;/span&gt;__tests__/declarations.d.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* eslint-disable @typescript-eslint/no-triple-slash-reference */&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;reference types="@testing-library/jest-dom/extend-expect" /&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does is tell TypeScript that for the current directory subtree (&lt;code&gt;__tests__&lt;/code&gt;), it should always add the package' types as defined by the directive. I can now also see that the error in &lt;code&gt;__tests__/App.tsx&lt;/code&gt; has been resolved and that it recognises &lt;code&gt;.toBeVisible&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting a coverage report
&lt;/h3&gt;

&lt;p&gt;There are no new dependencies required for a coverage report as &lt;code&gt;jest&lt;/code&gt; comes bundled with built-in coverage.&lt;/p&gt;

&lt;p&gt;In order to test if the &lt;code&gt;coverage&lt;/code&gt; is working &lt;em&gt;correctly&lt;/em&gt;, I first change the &lt;code&gt;App.tsx&lt;/code&gt; src file to include a branch:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;headingText&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="k"&gt;export&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="nx"&gt;headingText&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headingText&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;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;headingText&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;h1&lt;/span&gt;&lt;span class="p"&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, the app renders &lt;code&gt;null&lt;/code&gt; unless a &lt;code&gt;headingText&lt;/code&gt; is given. I also have to change the test to pass in &lt;code&gt;"Hello World"&lt;/code&gt; as the heading text, or the test will&lt;br&gt;
fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-  &amp;lt;App /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+  &amp;lt;App headingText="Hello World" /&amp;gt;,
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I run the test suite with coverage enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--coverage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs the tests and they are &lt;em&gt;passing&lt;/em&gt;; it also outputs the following table summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |    66.67 |       50 |      100 |    66.67 |                   |
 App.tsx  |    66.67 |       50 |      100 |    66.67 |                 9 |
----------|----------|----------|----------|----------|-------------------|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Line 9&lt;/strong&gt; is inside a conditional branch (for when &lt;code&gt;headerText === undefined&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be tested by explicitly adding a test.&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App renders nothing without headingText&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeNull&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 generally don't like to test that things are &lt;em&gt;not&lt;/em&gt; there, because often you have to make a few assumptions that are fragile at best (and therefore break easily), but just to test if &lt;code&gt;jest&lt;/code&gt; has been set-up correctly, this is fine, since I'll throw away these lines later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ jest --coverage
 PASS  __tests__/App.tsx
  √ App renders heading (46ms)
  √ App renders nothing without headingText (1ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 App.tsx  |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.911s
Ran all test suites.
Done in 6.78s.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up &lt;code&gt;prettier&lt;/code&gt; correctly
&lt;/h2&gt;

&lt;p&gt;Finally, I can focus on setting up the (automatic) code formatter! I really like &lt;code&gt;prettier&lt;/code&gt; for the simple reason that it removes the need of discussing a lot of style choices. I &lt;em&gt;don't&lt;/em&gt; think it always or even often generates &lt;strong&gt;pretty&lt;/strong&gt; code, but that's okay. As their library improves, so does the output, and it's trivial to re-format all the code once they do.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;eslint-config-prettier&lt;/code&gt;: turns off style rules that are in conflict with prettier. You can see the various &lt;code&gt;prettier/*&lt;/code&gt; lines in the &lt;code&gt;eslint&lt;/code&gt; configuration above. This has already been set-up.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;prettier&lt;/code&gt;: the core package, including the CLI tools to run prettier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prettier has already been added to the &lt;code&gt;eslint&lt;/code&gt; configuration, so that part can be skipped.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;prettier&lt;/code&gt; CLI doesn't have an &lt;code&gt;--init&lt;/code&gt; option at the moment of writing, so I create the configuration file manually:&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="nb"&gt;touch&lt;/span&gt; .prettierrc.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've chosen to loosly follow the &lt;code&gt;StandardJS&lt;/code&gt; style, but it really doesn't matter. Pick a style and stick with it.&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;"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;"es5"&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;"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;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;"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;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;"jsxSingleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also want to be able to run these as a script, so I add the following three &lt;code&gt;"scripts"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   "lint:types": "yarn tsc",
&lt;span class="gi"&gt;+  "lint:format": "yarn format --check",
+  "format": "yarn prettier \"{src,__{tests}__}/**/*.{ts,tsx}\"",
+  "format:fix": "yarn format --write",
&lt;/span&gt;   "test": "yarn jest"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Automatically formatting
&lt;/h3&gt;

&lt;p&gt;Since &lt;code&gt;prettier&lt;/code&gt; has been added as plugin to &lt;code&gt;eslint&lt;/code&gt;, it is already correctly integrated with &lt;code&gt;eslint&lt;/code&gt;. However, you might want code to be formatted &lt;em&gt;on save&lt;/em&gt;. The &lt;a href="https://prettier.io/docs/en/editors.html" rel="noopener noreferrer"&gt;prettier documentation&lt;/a&gt; lists a lot of IDEs and allow you to turn on formatting on save.&lt;/p&gt;

&lt;p&gt;In general, I'm not a fan of running prettier &lt;em&gt;on commit&lt;/em&gt;, because it slows down my commits, occasionally breaks things and I think it shouldn't be a concern of the commit to format the code. That said, I do think it's a good idea to add a check in the continuous integration (CI) to test the format of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that's it! The project is now in a pretty good state to start writing code. Yes, it took quite a bit to get here and a lot of the configuration setup above is exactly why tools such as &lt;code&gt;create-react-app&lt;/code&gt; or even the &lt;code&gt;parcel&lt;/code&gt; bundler exist. Note that I haven't actually dealt with some of the things that &lt;code&gt;parcel&lt;/code&gt; and &lt;code&gt;webpack&lt;/code&gt; deal with, such as importing images or other file types; I don't think I'll need it, and therefore I didn't add that.&lt;/p&gt;

&lt;p&gt;A few things are left to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set-up CI,&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;"name"&lt;/code&gt; and "license"` fields,&lt;/li&gt;
&lt;li&gt;Add the &lt;em&gt;servability&lt;/em&gt; i.e. add the HTML file that we can see in a browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next time I will &lt;em&gt;actually&lt;/em&gt; write some game code, and perhaps the things just listed, but for now, this is all I give you.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F74bosly3ryp7snoz4xt4.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F74bosly3ryp7snoz4xt4.jpg" title="Photo by Reginar (https://unsplash.com/@reginar) on Unsplash (https://unsplash.com/)" alt="Photo of "&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Tetris: Building a game using JavaScript</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Fri, 05 Jul 2019 15:53:27 +0000</pubDate>
      <link>https://dev.to/sleeplessbyte/tetris-building-a-game-using-javascript-3j6f</link>
      <guid>https://dev.to/sleeplessbyte/tetris-building-a-game-using-javascript-3j6f</guid>
      <description>&lt;p&gt;I've always been a fan of retro, arcade and retro arcade games, mostly because their limitations often  resulted in very creative game mechanics that were easy to learn and difficult to master. Mark Brown from &lt;a href="https://www.youtube.com/watch?v=7daTGyVZ60I"&gt;Game Maker's Toolkit&lt;/a&gt; has done &lt;a href="https://www.youtube.com/watch?v=7daTGyVZ60I"&gt;an excellent video&lt;/a&gt; about "versatile verbs", in a number of excellent games, which I recommend you to watch. Older games were less versatile, but as they were written mostly for &lt;em&gt;arcade machines&lt;/em&gt;, which usually had a very limited set of inputs, those games utilise the few buttons they had in various ways.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🎮 In this series I'll show you all the steps to build a Tetris clone, abiding by the &lt;a href="https://tetris.fandom.com/wiki/Tetris_Guideline"&gt;Tetris Guideline&lt;/a&gt;, the current specification that &lt;a href="https://tetris.fandom.com/wiki/The_Tetris_Company"&gt;The Tetris Company&lt;/a&gt; enforces for making all new (2001 and later) &lt;em&gt;Tetris&lt;/em&gt; game products alike in form.&lt;/p&gt;

&lt;p&gt;🛑 &lt;em&gt;Tetris&lt;/em&gt; is licensed which means that if you intend to take this series of articles to build your own arcade puzzler, make sure to abide by the law, if you intend to commerically release it. Even if you provide a clone for free, you could still get a cease and desist. &lt;a href="https://www.reddit.com/r/gamedev/comments/5kkk82/law_concerns_when_creating_a_game_inspired_by/"&gt;This reddit thread&lt;/a&gt; is pretty comprehensive how to go about this. Additionally, &lt;a href="https://arstechnica.com/gaming/2012/06/defining-tetris-how-courts-judge-gaming-clones/"&gt;this Ars Technica article&lt;/a&gt; talks in-depth about how courts judge gaming clones using &lt;em&gt;Tetris&lt;/em&gt; and the alleged clone &lt;em&gt;Mino&lt;/em&gt; as an example.&lt;/p&gt;

&lt;p&gt;📚 This series is purely meant as an educational, non-commercial resource. We'll only be using the &lt;em&gt;fandom wiki&lt;/em&gt; as a resource and only use the name Tetris to indicate the &lt;em&gt;type of game&lt;/em&gt; and not the actual company, game(s) or brand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this first article, we'll be looking at the &lt;strong&gt;domain&lt;/strong&gt; of the game, meaning which &lt;strong&gt;nouns&lt;/strong&gt; (object/subjects) and &lt;strong&gt;verbs&lt;/strong&gt; (actions/functions) exist in the game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fxBFaazw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oy2sxfwrpxgokzil3vpz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fxBFaazw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oy2sxfwrpxgokzil3vpz.jpg" alt="Photo titled 'Arcade Dreams', Fowler's Live, Adelaide, Australia" title="Photo by Ben Neale (https://unsplash.com/@ben_neale) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Definitions and Concepts
&lt;/h2&gt;

&lt;p&gt;First, let's look at al the game definitions and concepts, before writing any code. I generally do this step of domain modelling before I write any code, because it will probably help out making the right abstractions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Movement and Buttons
&lt;/h3&gt;

&lt;p&gt;In the classic Tetris, as released in 1984, the number of inputs was basically the same as the version developed for the iPod (Tetris 2006):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a button to move the falling &lt;em&gt;Tetromino&lt;/em&gt; left&lt;/li&gt;
&lt;li&gt;a button to move the falling &lt;em&gt;Tetromino&lt;/em&gt; right&lt;/li&gt;
&lt;li&gt;a button to drop-and-lock the falling &lt;em&gt;Tetromino&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;a button to rotate the &lt;em&gt;Tetromino&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The standard button mapping adds a few more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a button to drop (but not lock) the falling &lt;em&gt;Tetromino&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;a button to rotate the &lt;em&gt;Tetromino&lt;/em&gt; in the other direction (so counter-clockwise vs clockwise)&lt;/li&gt;
&lt;li&gt;a button to use hold&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whilst these actions seem pretty simple by themselves, together with the other game rules, they can act on a wide vocabulary.&lt;/p&gt;

&lt;p&gt;Binding a specific &lt;em&gt;verb&lt;/em&gt; to a button is what we call a &lt;strong&gt;mapping&lt;/strong&gt;. The mapping has standards as defined by the &lt;a href="https://tetris.fandom.com/wiki/Tetris_Guideline"&gt;Tetris Guideline&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Playfield
&lt;/h3&gt;

&lt;p&gt;In the manual for &lt;em&gt;Tetris for NES&lt;/em&gt; (1989) the &lt;strong&gt;playfield&lt;/strong&gt; is defined as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PLAYFIELD: This is where the action is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It makes up the grid on which the &lt;em&gt;Tetrominos&lt;/em&gt; fall and come to rest. In the majority of the games the width is 10 tiles, and the height ranges from 16 through 24 tiles. Aboe the grid, there are 20 rows "hidden", which is called the &lt;em&gt;Vanish Zone&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tetrominos
&lt;/h3&gt;

&lt;p&gt;There are various &lt;em&gt;Tetrominos&lt;/em&gt;: shapes that come dropping down from the top of the playfield. They are defined as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cyan: &lt;em&gt;I&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Yellow: &lt;em&gt;O&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Purple: &lt;em&gt;T&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Green: &lt;em&gt;S&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Red: &lt;em&gt;Z&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Blue: &lt;em&gt;J&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Orange &lt;em&gt;L&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UZY2d30h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/caxwtvm3qp3lz3nzt6xq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UZY2d30h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/caxwtvm3qp3lz3nzt6xq.png" alt="The different variations of Tetrominos" title="All the Tetrominos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They also have defined &lt;em&gt;starting locations&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Middle: &lt;em&gt;I&lt;/em&gt; and &lt;em&gt;O&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Left-Middle: everything else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They should all spawn &lt;em&gt;horizontally&lt;/em&gt;, with &lt;em&gt;J&lt;/em&gt;, &lt;em&gt;L&lt;/em&gt; and &lt;em&gt;T&lt;/em&gt; spawning the flat-side first, and spawn above the visible playfied (inside the &lt;em&gt;Vanish Zone&lt;/em&gt;), but drop one space if there is nothing in its path (becoming visible).&lt;/p&gt;

&lt;h3&gt;
  
  
  Generator
&lt;/h3&gt;

&lt;p&gt;There is a &lt;a href="https://tetris.fandom.com/wiki/Random_Generator"&gt;Random Generator&lt;/a&gt; to generate the pieces that will come down the playfield. The standard implementation is the so called 7-bag random generator, meaning that all seven one-sided tetriminos are drawn, randomly, from a bag, before generating another back.&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://tetris.fandom.com/wiki/TGM_randomizer"&gt;different randomizers&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Holding zone / Hold piece
&lt;/h3&gt;

&lt;p&gt;The player can press a button to send the falling tetrimino to the hold box, and any tetrimino that had been in the hold box moves to the top of the screen and begins falling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ghost piece
&lt;/h3&gt;

&lt;p&gt;The &lt;em&gt;ghost piece&lt;/em&gt; indicates where the &lt;em&gt;Tetromino&lt;/em&gt; will land, if it were dropped, It greatly reduces the number of misdrops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rotation
&lt;/h3&gt;

&lt;p&gt;Rotation of a &lt;em&gt;Tetromino&lt;/em&gt; is actually not straight-forward. The system and specification that deals with this is called the &lt;em&gt;Super Rotation System&lt;/em&gt; (SRS).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5dJhlIbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n5rfghw6x0b7qh1r9vg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5dJhlIbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n5rfghw6x0b7qh1r9vg2.png" alt="All the four rotation states of all the 7 Tetrominos" title="The various rotations when using the SRS."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general, when unobstructed, &lt;em&gt;Tetrominos&lt;/em&gt; rotate as you would except: about a single point. Because this is purely a mathematical &lt;strong&gt;rotation&lt;/strong&gt; without any &lt;strong&gt;translation&lt;/strong&gt;, there are states in which the &lt;em&gt;J&lt;/em&gt;, &lt;em&gt;L&lt;/em&gt;, &lt;em&gt;S&lt;/em&gt;, &lt;em&gt;T&lt;/em&gt; and &lt;em&gt;Z&lt;/em&gt; &lt;em&gt;Tetrominos&lt;/em&gt; "float" above their bounding box.&lt;/p&gt;

&lt;p&gt;However, when obstructed, the game will attempt to "kick" the &lt;em&gt;Tetromino&lt;/em&gt; into an alternative position nearby. The rules for these are described in &lt;a href="https://tetris.fandom.com/wiki/SRS#Wall_Kicks"&gt;the section about Wall Kicks&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Levels
&lt;/h3&gt;

&lt;p&gt;A player levels up by clearing lines (filling them completely), or performing "T-Spins". Higher levels usually have higher drop-speeds and higher score (-multipliers).&lt;/p&gt;

&lt;h3&gt;
  
  
  Scoring
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://tetris.fandom.com/wiki/Scoring#Guideline_scoring_system"&gt;Guideline scoring system&lt;/a&gt; dictates that certain &lt;em&gt;ways&lt;/em&gt; of clearing a line have different scores than &lt;em&gt;other ways&lt;/em&gt;. We won't go into the different combos, b2b, spins and so forth right now, but this will come up as we're implementing the game.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;No code has be written yet. The next steps are figuring out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which models and concerns are there? This will be accomplished by mapping the various nouns from the definitions and concepts above to programming namespaces and function names.&lt;/li&gt;
&lt;li&gt;What toolchain should we use? This will be determined by &lt;em&gt;the needs&lt;/em&gt;. That means deciding on a library/framework (if any), and the style of the output.&lt;/li&gt;
&lt;li&gt;What unique gameplay element(s) do we want to implement? The less Tetris-y the better! Gotta be unique.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔜 The next instalment in this series sets up the entire toolchain! You can find it &lt;a href="https://dev.to/sleeplessbyte/tetris-choosing-the-tools-and-setting-up-the-project-4kh6"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LzbOAyxs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1s39v2nctx1uoa018abs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LzbOAyxs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1s39v2nctx1uoa018abs.jpg" alt="Photo of the Eramus Bridge in Rotterdam, The Netherlands, at night" title="Photo by Harold Wijnholds (https://unsplash.com/@harold) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>showdev</category>
    </item>
    <item>
      <title>JavaScript, Ruby and C are not call by reference</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Thu, 27 Jun 2019 15:14:25 +0000</pubDate>
      <link>https://dev.to/xpbytes/javascript-ruby-and-c-are-not-call-by-reference-23f7</link>
      <guid>https://dev.to/xpbytes/javascript-ruby-and-c-are-not-call-by-reference-23f7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🛑 This article is a response to various articles in the wild which state that JavaScript and Ruby are "Call/Pass by reference" for objects and "Call/Pass by value" for primitives.&lt;/p&gt;

&lt;p&gt;Many of these articles provide a lot of valuable information and this article is not to unequivically say that those articles should not have been written or are useless. Instead, this article attempts to explore the semantic, yet pedantic, meanings and definitions of&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;call by reference&lt;/li&gt;
&lt;li&gt;pass a reference&lt;/li&gt;
&lt;li&gt;reference type&lt;/li&gt;
&lt;li&gt;reference&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, I would like to make a few statements, after which Ill try to explore what these statements actually mean and why I've made them, contrary to &lt;a href="https://medium.com/nodesimplified/javascript-pass-by-value-and-pass-by-reference-in-javascript-fcf10305aa9c" rel="noopener noreferrer"&gt;various&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference" rel="noopener noreferrer"&gt;articles&lt;/a&gt; &lt;a href="https://hackernoon.com/grasp-by-value-and-by-reference-in-javascript-7ed75efa1293" rel="noopener noreferrer"&gt;in&lt;/a&gt; &lt;a href="https://codeburst.io/javascript-passing-by-value-vs-reference-explained-in-plain-english-8d00fd06a47c" rel="noopener noreferrer"&gt;the&lt;/a&gt; &lt;a href="https://snook.ca/archives/javascript/javascript_pass" rel="noopener noreferrer"&gt;wild&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☕ When you see this emoji (☕), I try to give a non-code analogy to help you better understand what's going on. These abstractions are pretty leaky and might not hold up, but they're only meant in the context of the paragraphs that surround them. Take them with a grain of salt.&lt;/p&gt;
&lt;/blockquote&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fm094blzamvm2471dchi9.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fm094blzamvm2471dchi9.jpg" title="Photo by Treddy Chen (https://unsplash.com/@tchen_7993) on Unsplash (https://unsplash.com/)" alt="Black and yellow metal signage beside green grasses during daytime, in Yangmingshan, Taipei, Taiwan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Statements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript is &lt;em&gt;always&lt;/em&gt; call by value&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruby is &lt;em&gt;always&lt;/em&gt; call by value&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C is &lt;em&gt;always&lt;/em&gt; call by value&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The terminology is confusing and perhaps even flawed.&lt;/li&gt;
&lt;li&gt;The terminology &lt;em&gt;&lt;strong&gt;only&lt;/strong&gt; applies to function (procedure) parameters&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pointers&lt;/strong&gt; are an implementation detail and their presence don't say anything about the evaluation of &lt;em&gt;function parameters&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  History and Definitions
&lt;/h2&gt;

&lt;p&gt;I've tried to look up the origins of the terms as mentioned above, and there is quite a bit of literature out there from the earlier programming languages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://academic.oup.com/comjnl/article/6/2/134/364746" rel="noopener noreferrer"&gt;The Main Features of CPL (D. W. Barron et al., 1963)&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Three modes of parameter call are possible; call by value (which is equivalent to the ALGOL call by value), call by substitution (equivalent to ALGOL call by name), and call by reference. In the latter case, the LH value of the actual parameter is handed over; this corresponds to the "call by simple name" suggested by Strachey and Wilkes (1961).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is important to note that here the literature talks about &lt;em&gt;mode of parameter call&lt;/em&gt;. It further distinguishes three &lt;em&gt;modes&lt;/em&gt;: &lt;code&gt;call by value&lt;/code&gt;, &lt;code&gt;call by name&lt;/code&gt; and &lt;code&gt;call by reference&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Further literature gives a good, yet technical, definition of these three and a fourth &lt;em&gt;strategy&lt;/em&gt; (namely &lt;code&gt;copy restore&lt;/code&gt;), as published in the &lt;a href="http://www.cs.colorado.edu/department/publications/reports/docs/CU-CS-016-73.pdf" rel="noopener noreferrer"&gt;Semantic Models of Parameter Passing (Richard E. Fairly, 1973)&lt;/a&gt;. I've quoted 2 of the 4 definitions below, after which I'll break them down and explain what they mean in more visual terms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Call by Value
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;[...] Call by Value parameter requires that the actual parameter be evaluated at the time of the procedure call. The memory register associated with the formal parameter is then initialised to this value, and references to the formal parameter in the procedure body are treated as references to the local memory register in which the initial value of the actual parameter was stored. Due to the fact that a copy of the value associated with the actual parameter is copied into the local memory register, transformations on the parameter value within the procedure body are isolated from the actual parameter value. Because of this isolation of values, Call by value can not be used to communicate calculated values back to the calling program.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Roughly, this means that a parameter is, before the function (&lt;code&gt;procedure&lt;/code&gt;) is called, completely evaluated. The resulting &lt;em&gt;value&lt;/em&gt; (from that evaluation), is then assigned to the identifier inside the function (&lt;code&gt;formal parameter&lt;/code&gt;). In many programming languages this is done by &lt;em&gt;copying&lt;/em&gt; the &lt;em&gt;value&lt;/em&gt; to a second memory address, making the changes inside the function (&lt;code&gt;procedure body&lt;/code&gt;) isolated to that function.&lt;/p&gt;

&lt;p&gt;In other words: the original memory address' contents (the one used to store the evaluated expression before passing it into the function) can not be changed by code inside the function and changes inside the function to &lt;em&gt;the value&lt;/em&gt; are not propagated to the caller.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☕ When you order a coffee and someone asks for your name, they might write it down incorrectly. This doesn't affect &lt;em&gt;your actual name&lt;/em&gt; and the change is only propagated to the cup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Call by Reference
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;[...] In Call by Reference, the address (name) of the actual parameter at the time of the procedure call is passed to the procedure as the value to be associated with the corresponding formal parameter. References to the formal parameter in the procedure body result in indirect addressing references through the formal parameter register to the memory register associated with the actual parameter in the calling procedure. Thus, transformations of formal parameter values are immediately transmitted to the calling procedure, because both the actual parameter and the formal parameter refer to the same register.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Roughly, this means that, just like before, the parameter is evaluated, but, unlike before, the &lt;em&gt;memory address&lt;/em&gt; (&lt;code&gt;address&lt;/code&gt; / &lt;code&gt;name&lt;/code&gt;) is passed to the function (&lt;code&gt;procedure&lt;/code&gt;). Changes made to the parameter inside the function (&lt;code&gt;formal parameter&lt;/code&gt;) are actually made on the memory address and therefore propagate back to the caller.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☕ When you go to a support store for one of your hardware devices and ask for it to be fixed, they might give you a replacement device. This replacement device is still yours, you own it just like before, but it might not be the &lt;em&gt;exact same one&lt;/em&gt; you gave to be fixed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Reference (and value) types
&lt;/h3&gt;

&lt;p&gt;This is not the complete picture. There is one vital part left that causes &lt;em&gt;most of the confusion&lt;/em&gt;. Right now I'll explain what a &lt;strong&gt;reference type&lt;/strong&gt; is, which has &lt;em&gt;nothing&lt;/em&gt; to do with arguments/parameters or function calls.&lt;/p&gt;

&lt;p&gt;Reference types and value types are usually explained in the context of how a programming language stores values inside the memory, which also explains why some languages choose to have both, but this entire concept is worthy of (a series of) articles on its own. The &lt;a href="https://en.wikipedia.org/wiki/Value_type_and_reference_type" rel="noopener noreferrer"&gt;Wikipedia page&lt;/a&gt; is, in my opinion, not very informative, but it does refer to various language specs that do go into technical detail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A data type is a &lt;strong&gt;value type&lt;/strong&gt; if it holds a data value within its own memory space. It means variables of these data types directly contain their values.&lt;/p&gt;

&lt;p&gt;Unlike &lt;em&gt;value types&lt;/em&gt;, a &lt;strong&gt;reference type&lt;/strong&gt; doesn't store its value directly. Instead, it stores the address where the value is being stored.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In short, a &lt;strong&gt;reference type&lt;/strong&gt; is a type that points to a value somewhere in memory whereas a &lt;strong&gt;value type&lt;/strong&gt; is a type that directly points to its value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☕ When you make a payment online, and enter your &lt;em&gt;bank account number details&lt;/em&gt;, for example your card number, the card itself can not be changed. However, the bank account's balance will be affected. You can see your card as a reference to your balance (and multiple cards can all reference the same balance).&lt;/p&gt;

&lt;p&gt;☕ When you pay offline, that is with cash, the money leaves your wallet. Your wallet holds its own value, just like the cash inside your wallet. The value is directly where the wallet/cash is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Show me the code proof
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reference_assignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myRefMaybe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;myRefMaybe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;primitiveValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;someObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;is&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;changed?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;reference_assignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;primitiveValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;primitiveValue&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; 1&lt;/span&gt;

&lt;span class="nf"&gt;reference_assignment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; { is: 'changed?' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As shown above, &lt;code&gt;someObject&lt;/code&gt; has not been changed, because it was not a &lt;code&gt;reference&lt;/code&gt; to &lt;code&gt;someObject&lt;/code&gt;. In terms of the definitions before: it was not the memory&lt;br&gt;
address of &lt;code&gt;someObject&lt;/code&gt; that was passed, but a &lt;em&gt;copy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A language that does support &lt;code&gt;pass by reference&lt;/code&gt; is PHP, but it requires &lt;a href="https://www.php.net/manual/en/language.references.pass.php" rel="noopener noreferrer"&gt;special syntax&lt;/a&gt; to change from &lt;em&gt;the default of passing by value&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;change_reference_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$actually_a_reference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$actually_a_reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$actually_a_reference&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;change_reference_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; $value equals 42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tried to keep the same sort of semantic as the JS code.&lt;/p&gt;

&lt;p&gt;As you can see, the PHP example &lt;em&gt;actually&lt;/em&gt; changes the value the input argument &lt;em&gt;refers&lt;/em&gt; to. This is because the &lt;em&gt;memory address&lt;/em&gt; of &lt;code&gt;$value&lt;/code&gt; can be accessed by the parameter &lt;code&gt;$actually_a_reference&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's wrong with the nomenclature?
&lt;/h2&gt;

&lt;p&gt;Reference types and "boxed values" make this more confusing and also why I believe that the nomenclature is perhaps flawed.&lt;/p&gt;

&lt;p&gt;The term &lt;code&gt;call-by-value&lt;/code&gt; is problematic. In JavaScript and Ruby, the &lt;strong&gt;value&lt;/strong&gt; that is passed is a &lt;strong&gt;reference&lt;/strong&gt;. That means that, indeed, the reference to the boxed primitive is copied, and therefore changing a primitive inside a function doesn't affect the primitive on the outside. That also means that, indeed, the reference to a &lt;em&gt;reference type&lt;/em&gt;, such as an &lt;code&gt;Array&lt;/code&gt; or &lt;code&gt;Object&lt;/code&gt;, is copied and passed as the value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because reference types refer to their value, copying a reference type makes the copy &lt;em&gt;still&lt;/em&gt; refer to that value. This is also what you experience as &lt;em&gt;shallow copy&lt;/em&gt; instead of &lt;em&gt;deep copy/clone&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whoah. Okay. Here is an example that explores &lt;em&gt;both these concepts&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;appendOne&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;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;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;replaceWithFive&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;span class="p"&gt;{&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="mi"&gt;5&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;first&lt;/span&gt; &lt;span class="o"&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;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="nf"&gt;appendOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;first&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; [1]&lt;/span&gt;

&lt;span class="nf"&gt;replaceWithFive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;second&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; []&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first example it outputs &lt;code&gt;[1]&lt;/code&gt;, because the &lt;code&gt;push&lt;/code&gt; method modifies the object on which it is called (the object is referenced from the name &lt;code&gt;list&lt;/code&gt;). This propagates because the &lt;code&gt;list&lt;/code&gt; argument still refers to the original object &lt;code&gt;first&lt;/code&gt; (its reference was copied and passed as a value. &lt;code&gt;list&lt;/code&gt; points to that copy, but points to the same data in memory, because &lt;code&gt;Object&lt;/code&gt; is a reference type).&lt;/p&gt;

&lt;p&gt;In the second example it outputs &lt;code&gt;[]&lt;/code&gt; because the re-assignment doesn't propagate to the caller. In the end it is not re-assigning the &lt;em&gt;original reference&lt;/em&gt; but only a copy.&lt;/p&gt;

&lt;p&gt;Here is another way to write this down. 👉🏽 indicates a reference to a different location in memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;first_array&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="nx"&gt;second_array&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="nx"&gt;first&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;👉🏽&lt;/span&gt; &lt;span class="nx"&gt;first_array&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;👉🏽&lt;/span&gt; &lt;span class="nx"&gt;first_array&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;👉🏽&lt;/span&gt; &lt;span class="nx"&gt;first_array&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="c1"&gt;// =&amp;gt; (👉🏽 first_array) was changed&lt;/span&gt;

&lt;span class="nx"&gt;second&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;👉🏽&lt;/span&gt; &lt;span class="nx"&gt;second_array&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;👉🏽&lt;/span&gt; &lt;span class="nx"&gt;second_array&lt;/span&gt;
&lt;span class="nx"&gt;replace_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;👉🏽&lt;/span&gt; &lt;span class="nx"&gt;replace_array&lt;/span&gt;

&lt;span class="c1"&gt;// =&amp;gt; (👉🏽 second_array) was not changed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What about pointers?
&lt;/h3&gt;

&lt;p&gt;C is also always pass by value / call by value, but it allows you to pass a pointer which can simulate pass by reference. Pointers are implementation details, and for example used in C# to enable &lt;em&gt;pass by reference&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In C, however, pointers are reference types! The syntax &lt;code&gt;*pointer&lt;/code&gt; allows you to &lt;em&gt;follow the pointer to its reference&lt;/em&gt;. In the comments in this code I tried to explain what is going on under the hood.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;modifyParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pointerA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pointerB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// passed by value: only the local parameter is modified&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

     &lt;span class="c1"&gt;// passed by value or "reference", check call site to determine which&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pointerA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// passed by value or "reference", check call site to determine which&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pointerB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;first&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;third&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// "first" is passed by value, which is the default&lt;/span&gt;
    &lt;span class="c1"&gt;// "second" is passed by reference by creating a pointer,&lt;/span&gt;
    &lt;span class="c1"&gt;//         the pointer is passed by value, but it is followed when&lt;/span&gt;
    &lt;span class="c1"&gt;//         using *pointerA, and thus this is like passing a reference.&lt;/span&gt;
    &lt;span class="c1"&gt;// "third" is passed by value. However, it's a pointer and that pointer&lt;/span&gt;
    &lt;span class="c1"&gt;//         is followed when using *pointerB, and thus this is like&lt;/span&gt;
    &lt;span class="c1"&gt;//         passing a reference.&lt;/span&gt;
    &lt;span class="n"&gt;modifyParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;third&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// "first" is still 1&lt;/span&gt;
    &lt;span class="c1"&gt;// "second" is now 42&lt;/span&gt;
    &lt;span class="c1"&gt;// "random" is now 42&lt;/span&gt;
    &lt;span class="c1"&gt;// "third" is still a pointer to "random" (unchanged)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Call by sharing?
&lt;/h2&gt;

&lt;p&gt;The lesser used and known term that was coined is &lt;strong&gt;Call by sharing&lt;/strong&gt; which applies to Ruby, JavaScript, Python, Java and so forth. It implies that all values are object, all values are boxed, and they copy a reference when they pass it &lt;em&gt;as value&lt;/em&gt;. Unfortunately, in literature, the usage of this concept is not consistent, which is also why it's probably less known or used.&lt;/p&gt;

&lt;p&gt;For the purpose of this article, call-by-sharing is &lt;code&gt;call by value&lt;/code&gt;, but the value is always a reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In short: It's always pass by value, but the value of the variable is a reference. All primitive-methods return &lt;em&gt;a new value&lt;/em&gt; and thus one can not modify it, all objects and arrays can have methods that modified their value, and thus one &lt;em&gt;can&lt;/em&gt; modify it.&lt;/p&gt;

&lt;p&gt;You can &lt;strong&gt;not&lt;/strong&gt; affect the memory address of the &lt;em&gt;parameter&lt;/em&gt; directly in the languages that use &lt;code&gt;call-by-value&lt;/code&gt;, but you may affect what the parameter refers to. That is, you may affect the memory the parameter points to.&lt;/p&gt;

&lt;p&gt;The statement &lt;em&gt;Primitive Data Types are passed By Value and Objects are passed By Reference.&lt;/em&gt; is &lt;strong&gt;incorrect&lt;/strong&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4o5eorvii8hbl4gyduzc.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F4o5eorvii8hbl4gyduzc.jpg" title="Photo by Boudewijn Huysmans (&amp;lt;br&amp;gt;
https://unsplash.com/@boudewijn_huysmans) on Unsplash (https://unsplash.com/)" alt="Photo of the Centrale Bibliotheek in Rotterdam, The Netherlands: an industrial looking building with metallic walls and various yellow pipes on the side."&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ruby</category>
      <category>computerscience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>TypeScript types you should know about</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Tue, 18 Jun 2019 09:36:57 +0000</pubDate>
      <link>https://dev.to/xpbytes/typescript-types-you-should-know-about-3pc5</link>
      <guid>https://dev.to/xpbytes/typescript-types-you-should-know-about-3pc5</guid>
      <description>&lt;p&gt;In my daily work with TypeScript, there are a lot of utility types and standard&lt;br&gt;
types I use across most if not all projects. This article contains the following subjects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Types in &lt;code&gt;type-fest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Other types (custom, built-in or &lt;code&gt;utility-types&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Common patterns

&lt;ul&gt;
&lt;li&gt;Overloaded type guards&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;const&lt;/code&gt; arrays and union type&lt;/li&gt;
&lt;li&gt;Custom errors&lt;/li&gt;
&lt;li&gt;Setting &lt;code&gt;this&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UDJeCbii--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/p9wzwyyiaocpv0r6czhz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UDJeCbii--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/p9wzwyyiaocpv0r6czhz.jpg" alt="A photo of a lot open books, nicely aligned, taken at FIKA Cafe, Toronto, Canada" title="Photo by Patrick Tomasso (https://unsplash.com/@impatrickt) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://github.com/sindresorhus/type-fest"&gt;&lt;code&gt;type-fest&lt;/code&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A collection of essential TypeScript types.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;npm&lt;/code&gt; package contains quite a few that are not (yet) built-in. I sometimes use this package (and import from there) and sometimes copy these to an ambient declarations file in my project.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;SafeOmit&amp;lt;T, K&amp;gt;&lt;/code&gt; &lt;a href="https://github.com/sindresorhus/type-fest/blob/master/source/"&gt;🌐&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Create a type from an object type without certain keys.&lt;/p&gt;

&lt;p&gt;The use-case is a safe(r) version than the built-in &lt;code&gt;Omit&lt;/code&gt;, which doesn't check&lt;br&gt;
the keys &lt;code&gt;K&lt;/code&gt; against &lt;code&gt;T&lt;/code&gt;, but instead check them against &lt;code&gt;any&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SafeOmit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Exclude&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ExecutionOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dry&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&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;type&lt;/span&gt; &lt;span class="nx"&gt;ExecutionFlags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SafeOmit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ExecutionOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; {&lt;/span&gt;
&lt;span class="c1"&gt;//  debug: boolean;&lt;/span&gt;
&lt;span class="c1"&gt;//  dry?: boolean | undefined;&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;ReadonlyDeep&amp;lt;T&amp;gt;&lt;/code&gt; &lt;a href="https://github.com/sindresorhus/type-fest/blob/master/source/readonly-deep.d.ts"&gt;🌐&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Convert &lt;code&gt;object&lt;/code&gt;s, &lt;code&gt;Map&lt;/code&gt;s, &lt;code&gt;Set&lt;/code&gt;s, and &lt;code&gt;Array&lt;/code&gt;s and all of their properties/elements into immutable structures recursively.&lt;/p&gt;

&lt;p&gt;My use-case is primarily when I'm imported JSON, or dealing with &lt;a href="//./writing-an-analyzer-typescript/"&gt;Abstract Syntax Trees&lt;/a&gt;. These need to be completely immutable (until they're cloned) and this enforces that. The built-in &lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt; only works shallowly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&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;ReadonlyDeep&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;type-fest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dataJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data.json&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyDeep&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;dataJson&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;dataJson&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&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="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;//=&amp;gt; error TS2339: Property 'push' does not exist on type 'readonly string[]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;RequireAtLeastOnce&amp;lt;T, K&amp;gt;&lt;/code&gt; &lt;a href="https://github.com/sindresorhus/type-fest/blob/master/source/require-at-least-one.d.ts"&gt;🌐&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Create a type that requires at least one of the given properties. The remaining&lt;br&gt;
properties are kept as is.&lt;/p&gt;

&lt;p&gt;My use-case is primarily when I have to make sure one of the known interface methods is present (usually api, service, transform/conversion style objects), but the rest of the type consists of properties and members that are always available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&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;RequireAtLeastOne&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;type-fest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Responder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;json&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequireAtLeastOne&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Responder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&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="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"message": "ok"}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;Merge&amp;lt;A, B&amp;gt;&lt;/code&gt; &lt;a href="https://github.com/sindresorhus/type-fest/blob/master/source/merge.d.ts"&gt;🌐&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Merge two types into a new type. Keys of the second type overrides keys of the&lt;br&gt;
first type.&lt;/p&gt;

&lt;p&gt;My use-case is primarily when I want to use &lt;code&gt;Object.assign&lt;/code&gt; instead of using destructuring/spread to build my merged object. In the example below, you can see that the default for &lt;code&gt;Object.assign&lt;/code&gt; produces an incorrect type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Stringy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bar&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="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NotStri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="na"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stringy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Stringy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&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;notstri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotStri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stringy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notstri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;//       infers Object.assign&amp;lt;Stringy, NotStri&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;result1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; string &amp;amp; number&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Merge&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;V&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;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Extract&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;V&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;result2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Merge&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Stringy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NotStri&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stringy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notstri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;result2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; number&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result3&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;stringy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;notstri&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;Mutable&amp;lt;T&amp;gt;&lt;/code&gt; &lt;a href="https://github.com/sindresorhus/type-fest/blob/master/source/mutable.d.ts"&gt;🌐&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Convert an object with &lt;code&gt;readonly&lt;/code&gt; properties into a mutable object. Inverse of&lt;br&gt;
&lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I personally use this &lt;em&gt;very sparingly&lt;/em&gt; as I tend to &lt;code&gt;Object.freeze&lt;/code&gt; those variables that are "truly" &lt;code&gt;Readonly&lt;/code&gt;. As &lt;code&gt;Required&amp;lt;T&amp;gt;&lt;/code&gt; is the inverse of &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Mutable&amp;lt;T&amp;gt;&lt;/code&gt; is the inverse of &lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&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;Mutable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;type-fest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mutableFoo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Mutable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Foo&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="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;mutableFoo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Other types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;WithFoo&amp;lt;T&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Whenever I have some data &lt;code&gt;T&lt;/code&gt; and modify it so that it has more data, I generally use a wrapping type, so that it's easy to &lt;em&gt;compose&lt;/em&gt; the type as I go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MyType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WithFoo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyType&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;first&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;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;second&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;dataWithFoo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WithFoo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c1"&gt;// The inverse uses SafeOmit&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WithoutFoo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  AtLeastOne
&lt;/h3&gt;

&lt;p&gt;Sometimes I want to ensure that an array has &lt;em&gt;at least one item&lt;/em&gt;. There are type libraries that actually define a &lt;em&gt;whole lot&lt;/em&gt; more than just this simple alias, but that's out of the scope for this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AtLeastOne&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;PromiseType&amp;lt;T&amp;gt;&lt;/code&gt; &lt;a href="https://github.com/piotrwitek/utility-types#promisetypet"&gt;🌐&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;One of the more interesting unwrappers. This gives the inner type &lt;code&gt;T&lt;/code&gt; of a &lt;code&gt;Promise&amp;lt;T&amp;gt;&lt;/code&gt; type. Usefull when something will unwrap the type, or you want to work outside of the context of promises or construct a new promise type (e.g. &lt;code&gt;Promise&amp;lt;WithLabel&amp;lt;PromiseType&amp;lt;Original&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&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;PromiseType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utility-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PromiseType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;ReturnType&amp;lt;T&amp;gt;&lt;/code&gt; (built-in)
&lt;/h3&gt;

&lt;p&gt;Obtain the return type of a function type.&lt;/p&gt;

&lt;p&gt;This is one of the more powerful inferred types I use all the type. Instead of&lt;br&gt;
duplicating a type expectation over and over, if I know a function is guaranteed to call (or expected to call) a function &lt;code&gt;foo&lt;/code&gt;, and I return the result, I give it the return type &lt;code&gt;ReturnType&amp;lt;typeof foo&amp;gt;&lt;/code&gt;, which forwards the return type from the function declaration of &lt;code&gt;foo&lt;/code&gt; to the current function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;T10&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; string&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;T11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; void&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FooResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; Promise&amp;lt;number&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;InstanceType&amp;lt;T&amp;gt;&lt;/code&gt; (built-in)
&lt;/h3&gt;

&lt;p&gt;Obtain the instance type of a constructor function type.&lt;/p&gt;

&lt;p&gt;I use this if I have a constructor type (a type that is constructible), but I need to work with the &lt;code&gt;ReturnType&amp;lt;T&amp;gt;&lt;/code&gt; of said constructor. More or less the inverse of &lt;code&gt;ConstructorType&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;T20&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; C&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;ConstructorType&amp;lt;T&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Matches a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes"&gt;&lt;code&gt;class&lt;/code&gt; constructor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I use this when I have a type (&lt;code&gt;T&lt;/code&gt;) and I create a factory that generates these, or when I need the constructor &lt;em&gt;type&lt;/em&gt;, given an instance type. More or less the inverse of &lt;code&gt;InstanceType&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ConstructorType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;arguments_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Common patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overloaded type guards
&lt;/h3&gt;

&lt;p&gt;I often have custom type guard in order to easily narrow a very broad type. The issue with a broad type is that you only have access to the &lt;em&gt;intersection&lt;/em&gt; until you check for presence or narrow it.&lt;/p&gt;

&lt;p&gt;Sometimes you want to check more than just a broad type, and don't want the typeguard to assign &lt;em&gt;never&lt;/em&gt; if it doesn't match some narrowing predicate. See the example below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&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;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&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;@typescript-eslint/typescript-estree&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Aliases for these types, so they are easy to access&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BinaryExpression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BinaryExpression&lt;/span&gt;

&lt;span class="c1"&gt;// Store all the possible values for the operator property&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BinaryOperator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BinaryExpression&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;operator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;// Define a special type that narrows the operator&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BinaryExpressionWithOperator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;BinaryOperator&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;BinaryExpression&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;// Generic overload that doesn't test for operator&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isBinaryExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;BinaryExpression&lt;/span&gt;
&lt;span class="c1"&gt;// Special overload that only matches if the opertor matches&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isBinaryExpression&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;BinaryOperator&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;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;BinaryExpressionWithOperator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Implementation that allows both arguments&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isBinaryExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operator&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;node&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;BinaryExpression&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;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BinaryExpression&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;operator&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;generic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BinaryExpression&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="cm"&gt;/*...*/&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; TSESTree.ArrayExpression&lt;/span&gt;
&lt;span class="c1"&gt;//    | TSESTree.ArrayPattern&lt;/span&gt;
&lt;span class="c1"&gt;//    | TSESTree.ArrowFunctionExpression&lt;/span&gt;
&lt;span class="c1"&gt;//    | TSESTree.AssignmentExpression&lt;/span&gt;
&lt;span class="c1"&gt;//    | TSESTree.AssignmentPattern&lt;/span&gt;
&lt;span class="c1"&gt;//    | TSESTree.AwaitExpression&lt;/span&gt;
&lt;span class="c1"&gt;//    | ... 150 more ...&lt;/span&gt;
&lt;span class="c1"&gt;//    | TSESTree.YieldExpression&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;isBinaryExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;generic&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// typeof generic is now&lt;/span&gt;
  &lt;span class="c1"&gt;// =&amp;gt; { type: 'BinaryExpression', operator: BinaryOperator, left: ..., }&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// typeof generic is now anything except for&lt;/span&gt;
  &lt;span class="c1"&gt;// ~&amp;gt; { type: 'BinaryExpression' }&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;isBinaryExpression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;generic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// typeof generic is now&lt;/span&gt;
  &lt;span class="c1"&gt;// =&amp;gt; { type: 'BinaryExpression', operator: '+', left: ..., }&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// typeof generic is still Node&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;const&lt;/code&gt; arrays and &lt;code&gt;OneOf&amp;lt;const Array&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Often you have a distinct set of values you want to allow. Since TypeScript 3.4&lt;br&gt;
there is no need to do weird transformations using helper functions.&lt;/p&gt;

&lt;p&gt;The example below has a set of options in &lt;code&gt;A&lt;/code&gt; and defines the union type &lt;code&gt;OneOfA&lt;/code&gt; which is one of the options of &lt;code&gt;A&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;OneOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;A&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="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;OneOfA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;OneOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; 'foo' | 'bar' | 'baz'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;indexOf&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;OneOfA&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&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="c1"&gt;// never returns -1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Custom errors
&lt;/h3&gt;

&lt;p&gt;As per TypeScript 2.1, transpilation of built-ins &lt;a href="https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work"&gt;is weird&lt;/a&gt;. If you don't need to support IE10 or lower, the following pattern works well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;EarlyFinalization&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Early finalization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Doesn't work on IE10-&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EarlyFinalization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Adds proper stacktrace&lt;/span&gt;
    &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;captureStackTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting &lt;code&gt;this&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There are (at least) &lt;em&gt;two&lt;/em&gt; ways to tell TypeScript what the current contextual &lt;code&gt;this&lt;/code&gt; value of a function is. The first one is adding a parameter &lt;code&gt;this&lt;/code&gt; to your function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Traverser&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;walker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Traverser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="c1"&gt;// no error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This can be very helpful if you're declaring functions outside the scope of a &lt;code&gt;class&lt;/code&gt; or similar, but you know what the &lt;code&gt;this&lt;/code&gt; value will be bound to.&lt;/p&gt;

&lt;p&gt;The second method actually allows you to define it &lt;em&gt;outside&lt;/em&gt; of the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;HelperContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;logError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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;helperFunctions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;ThisType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HelperContext&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="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error: Something went wrong!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// TypeScript successfully recognizes that "logError" is a part of "this".&lt;/span&gt;

      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="c1"&gt;// TS2339: Property 'update' does not exist on HelperContext.&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;This can be very helpful if you're binding a collection of functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;TypeScript has a lot of gems 💎 and even moreso in userland. Make sure that you check the built-in types, &lt;code&gt;type-fest&lt;/code&gt; and your own collection of snippets, before you resort to &lt;code&gt;as unknown as X&lt;/code&gt; or &lt;code&gt;: any&lt;/code&gt;. A lot of the times there really is a proper way to do thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wGggZipw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/96restcss1m07ljvl67q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wGggZipw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/96restcss1m07ljvl67q.jpg" alt="A photo of yellow and gray, cube shaped houses, at Rotterdam, The Netherlands" title="Photo by Nicole Baster (https://unsplash.com/@nicolebaster) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Writing a code analyzer in TypeScript (from scratch)</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Mon, 10 Jun 2019 23:29:45 +0000</pubDate>
      <link>https://dev.to/xpbytes/writing-a-code-analyzer-in-typescript-5ec3</link>
      <guid>https://dev.to/xpbytes/writing-a-code-analyzer-in-typescript-5ec3</guid>
      <description>&lt;p&gt;&lt;a href="https://exercism.io" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt; is an online platform designed to help you improve your coding skills through practice and mentorship.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://exercism.io" rel="noopener noreferrer"&gt;Exercism&lt;/a&gt; provides you with thousands of exercises spread across numerous language tracks. Once you start a language track you are presented with a core set of exercises to complete. Each one is a fun and interesting challenge designed to teach you a little more about the features of a language.&lt;/p&gt;

&lt;p&gt;At the moment of writing, I'm a maintainer of the &lt;a href="https://exercism.io/tracks/javascript" rel="noopener noreferrer"&gt;JavaScript&lt;/a&gt; and &lt;a href="https://exercism.io/tracks/typescript" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; track and &lt;a href="https://exercism.io/blog/track-anatomy-project" rel="noopener noreferrer"&gt;recently&lt;/a&gt; we've been working on automating a part of the experience.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article will &lt;strong&gt;introduce&lt;/strong&gt; you to AST parsing and walking using &lt;strong&gt;ESTree&lt;/strong&gt; compatible tools. It specifically looks at certain token types, most commonly found in &lt;em&gt;JavaScript&lt;/em&gt; and &lt;em&gt;TypeScript&lt;/em&gt; code.&lt;/p&gt;

&lt;p&gt;It teaches you how to &lt;strong&gt;explore&lt;/strong&gt; these trees yourself and refers to &lt;strong&gt;code samples&lt;/strong&gt; and actual production implementations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When reading this article, think about your own JavaScript and TypeScript code. Once you understand how the browser (and tooling, like &lt;a href="https://github.com/eslint/eslint" rel="noopener noreferrer"&gt;&lt;code&gt;eslint&lt;/code&gt;&lt;/a&gt;) parses your code, you might better understand how the language is defined and constructed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🚧 The links to &lt;em&gt;GitHub&lt;/em&gt; are all &lt;code&gt;master&lt;/code&gt; links, meaning the contents may change between writing this article and you clicking them. However, in order to make sure the code samples make sense, the analyzer repository links refer to a specific commit (&lt;code&gt;9ff332b&lt;/code&gt;). This means that the code you see might not be the same as what is used today.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Table of Contents&lt;/li&gt;
&lt;li&gt;
📝 The exercise

&lt;ul&gt;
&lt;li&gt;JavaScript implementation&lt;/li&gt;
&lt;li&gt;TypeScript implementation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

💯 Optimal solutions

&lt;ul&gt;
&lt;li&gt;JavaScript solution&lt;/li&gt;
&lt;li&gt;TypeScript solution&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

👩🏽‍💻 Analysing the code

&lt;ul&gt;
&lt;li&gt;💬 Abstract Syntax Trees&lt;/li&gt;
&lt;li&gt;🏃🏽‍💨 Running the parser&lt;/li&gt;
&lt;li&gt;🔎 Finding the main entrypoint&lt;/li&gt;
&lt;li&gt;🔎 Finding the top-level constant&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

The algorithm

&lt;ul&gt;
&lt;li&gt;Properties of objects&lt;/li&gt;
&lt;li&gt;"Executing" a property&lt;/li&gt;
&lt;li&gt;Matching the identifiers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

✅ Automated Mentoring

&lt;ul&gt;
&lt;li&gt;📦 Testing exports&lt;/li&gt;
&lt;li&gt;Inline exports&lt;/li&gt;
&lt;li&gt;Specifier exports&lt;/li&gt;
&lt;li&gt;CommonJS exports&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;🔀 Testing varations&lt;/li&gt;

&lt;li&gt;

Walking TypeScript Trees

&lt;ul&gt;
&lt;li&gt;🔑 Visitor Keys&lt;/li&gt;
&lt;li&gt;📖 Type annotations&lt;/li&gt;
&lt;li&gt;Class properties&lt;/li&gt;
&lt;li&gt;↩ Return types&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;li&gt;

Reference

&lt;ul&gt;
&lt;li&gt;Analyzer reference&lt;/li&gt;
&lt;li&gt;Exercism repositories&lt;/li&gt;
&lt;li&gt;Packages&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbq292ll5t7s7m0o0rtwd.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbq292ll5t7s7m0o0rtwd.jpg" title="Photo by Zoltan Tasi (https://unsplash.com/@zoltantasi) on Unsplash (https://unsplash.com/)" alt="Photo called 'Feel the freedom' in Dungeness, United Kingdom, displaying a red Volkswagen Samba parked near brown house."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 The exercise
&lt;/h2&gt;

&lt;p&gt;For this article, I'm going to write the analyzer for the &lt;a href="https://github.com/exercism/problem-specifications/blob/master/exercises/gigasecond" rel="noopener noreferrer"&gt;&lt;code&gt;gigasecond&lt;/code&gt;&lt;/a&gt; exercise, for both the TypeScript ánd JavaScript track. The description is a mere two lines:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Given a moment, determine the moment that would be after a gigasecond has passed.&lt;/p&gt;

&lt;p&gt;A gigasecond is &lt;code&gt;10^9&lt;/code&gt; (1,000,000,000) seconds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href="https://github.com/exercism/problem-specifications/blob/master/exercises/gigasecond/canonical-data.json" rel="noopener noreferrer"&gt;canonical data&lt;/a&gt; hints at the code I need to write, but luckily the exercise is implemented in both the &lt;a href="https://github.com/exercism/javascript/blob/master/exercises/gigasecond/gigasecond.spec.js" rel="noopener noreferrer"&gt;JavaScript&lt;/a&gt; and &lt;a href="https://github.com/exercism/typescript/blob/master/exercises/gigasecond/gigasecond.test.ts" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; tracks.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript implementation
&lt;/h3&gt;

&lt;p&gt;The JavaScript implementation expects us to write a named export &lt;code&gt;gigasecond&lt;/code&gt; which returns a &lt;code&gt;Date&lt;/code&gt; that is a gigasecond past the input &lt;code&gt;Date&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Test case from the JavaScript track&lt;/span&gt;
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tells a gigasecond anniversary since midnight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;gigasecond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&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;expectedDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2047&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gs&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expectedDate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TypeScript implementation
&lt;/h3&gt;

&lt;p&gt;The TypeScript implementation expects us to write a default export &lt;code&gt;Gigasecond&lt;/code&gt; which is a class that has a &lt;code&gt;date()&lt;/code&gt; function which returns a &lt;code&gt;Date&lt;/code&gt; that is a gigasecond past the constructor &lt;code&gt;Date&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Test case from the TypeScript track&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tells a gigasecond anniversary since midnight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Gigasecond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&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;expectedDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2047&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expectedDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  💯 Optimal solutions
&lt;/h2&gt;

&lt;p&gt;Before tackling how to write an analyzer for these two implementations, I first have to establish what the optimal solutions are. If I know the intended code result, I can try to recognise that and work from there.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript solution
&lt;/h3&gt;

&lt;p&gt;The implementation in JavaScript is straightforward. It uses the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date" rel="noopener noreferrer"&gt;&lt;code&gt;Date&lt;/code&gt;&lt;/a&gt; constructor together with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime" rel="noopener noreferrer"&gt;&lt;code&gt;Date#getTime&lt;/code&gt;&lt;/a&gt; and a constant to generate a the appropriate result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;gigasecond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&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;It is vital to note the peculiarities here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimal is extracting the &lt;code&gt;GIGASECOND_IN_MS&lt;/code&gt; value as a top-level constant&lt;/li&gt;
&lt;li&gt;The constant's value (&lt;code&gt;(10 ** 9) * 1000&lt;/code&gt;) can optimally be written in many equally valid forms. Writing the number out, however, is deemed a smell. All the following &lt;strong&gt;SHOULD&lt;/strong&gt; be recognised as optimal:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;10 ** 12&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1e9 * 1e3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;1e12&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Math.pow(10, 9) * 1000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Math.pow(10, 12)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueof" rel="noopener noreferrer"&gt;&lt;code&gt;Date#valueOf&lt;/code&gt;&lt;/a&gt; is &lt;em&gt;not&lt;/em&gt; optimal. It is marked as "This method is usually called internally by JavaScript and not explicitly in code.", even though it's functionally equivalent.&lt;/li&gt;

&lt;li&gt;Finally, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse" rel="noopener noreferrer"&gt;&lt;code&gt;Date.parse(date)&lt;/code&gt;&lt;/a&gt; is not a good candidate as it's supposed to work with strings only. The reason it returns the same value as &lt;code&gt;getTime&lt;/code&gt; when given a date, is because that date is coerced to a string and then parsed.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  TypeScript solution
&lt;/h3&gt;

&lt;p&gt;The TypeScript implementation expects a &lt;code&gt;class&lt;/code&gt; as &lt;code&gt;default export&lt;/code&gt;, and has a method &lt;code&gt;date()&lt;/code&gt;. The algorithm is &lt;em&gt;exactly&lt;/em&gt; the same as in the JavaScript solution, but it requires type annotations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gigasecond&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;futureDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Readonly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Readonly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Date&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;futureDate&lt;/span&gt; &lt;span class="o"&gt;=&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;freeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Readonly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Date&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;futureDate&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;Apart from the variations and rules as described earlier for JavaScript, the calculation may be done &lt;em&gt;either&lt;/em&gt; in the &lt;code&gt;constructor&lt;/code&gt; (as shown above) &lt;em&gt;or&lt;/em&gt; in the &lt;code&gt;date&lt;/code&gt; function. In that last case, it will look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gigasecond&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&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="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Date&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;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  👩🏽‍💻 Analysing the code
&lt;/h2&gt;

&lt;p&gt;Now it's time to actually write the analyzer. We'll focus on the JavaScript implementation first. Because there are already JavaScript analyzers running in the wild and that work is open source, this example will use the utilities and base class from the &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils" rel="noopener noreferrer"&gt;&lt;code&gt;javascript-analyzer&lt;/code&gt;&lt;/a&gt; repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  💬 Abstract Syntax Trees
&lt;/h3&gt;

&lt;p&gt;The JavaScript Analyzer will be working the &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" rel="noopener noreferrer"&gt;Abstract Syntax Tree (AST)&lt;/a&gt; of the code solutions. There are &lt;a href="https://www.metaborg.org/en/latest/" rel="noopener noreferrer"&gt;other&lt;/a&gt; ways to write an  analyzer, but for the sake of this article, AST parsing is the way to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @typescript-eslint/parser @typescript-eslint/typescript-estree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/typescript-eslint/typescript-eslint" rel="noopener noreferrer"&gt;TypeScript ESLint team&lt;/a&gt; has built a great parser that outputs an &lt;a href="https://github.com/estree/estree" rel="noopener noreferrer"&gt;ESTree&lt;/a&gt;, a specced format of tokens and information about the input code. It can work with both &lt;code&gt;JavaScript&lt;/code&gt; and &lt;code&gt;TypeScript&lt;/code&gt; and is therefore great for our use case. I prefer working with this type of tree, because of the spec which allows for interoptability with other tools.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;parser&lt;/code&gt; deals with the eslint configuration and then invokes the &lt;code&gt;typescript-estree&lt;/code&gt; package which &lt;em&gt;compiles the code using TypeScript&lt;/em&gt; and transforms the result to match the &lt;a href="https://github.com/estree/estree" rel="noopener noreferrer"&gt;ESTree&lt;/a&gt;. You can head on over to &lt;a href="https://astexplorer.net/" rel="noopener noreferrer"&gt;AST Explorer&lt;/a&gt; and try this out yourself by pasting the example code from above into the input field and selecting &lt;code&gt;@typescript-eslint/parser&lt;/code&gt;. &lt;strong&gt;⚠ Note&lt;/strong&gt;: The version of the parser here is usually not up-to-date with the latest parser.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You might wonder: Why not use the &lt;a href="https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API" rel="noopener noreferrer"&gt;TypeScript Compiler Api&lt;/a&gt;? It has AST parsing built-in the TypeScript language. It also exposes a lot of helper functions (like &lt;code&gt;isIdentifer&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The reason is that the &lt;em&gt;output&lt;/em&gt; is &lt;strong&gt;not&lt;/strong&gt; in the ESTree spec format, which means that you won't be able to use &lt;em&gt;other&lt;/em&gt; tools with it. In fact, the TypeScript-ESTree package, actually uses the compiler under the hood but then transforms it to the spec, which means no lock-in. You're not bound by changes in the compiler.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🏃🏽‍💨 Running the parser
&lt;/h3&gt;

&lt;p&gt;Now that the packages are in place, let's parse the input code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TSESTreeOptions&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;@typescript-eslint/typescript-estree&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;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTreeOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; Program({ body: [...], sourceType: "module", tokens: [...] })&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us the same output as you see in &lt;a href="https://astexplorer.net/" rel="noopener noreferrer"&gt;AST Explorer&lt;/a&gt;, with at the root a &lt;code&gt;Program&lt;/code&gt; and its &lt;code&gt;body&lt;/code&gt;. We won't need the other fields, but &lt;code&gt;tokens&lt;/code&gt; is interesting. It lists the parsed tokens from the source, as it was building the tree.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 You can find this in &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/parsers/AstParser.ts" rel="noopener noreferrer"&gt;&lt;code&gt;parsers/AstParser.ts&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🔎 Finding the main entrypoint
&lt;/h3&gt;

&lt;p&gt;We're looking for a function called &lt;code&gt;gigasecond&lt;/code&gt;. We know the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It &lt;em&gt;must&lt;/em&gt; be &lt;code&gt;export&lt;/code&gt;ed&lt;/li&gt;
&lt;li&gt;Its name &lt;em&gt;must&lt;/em&gt; be &lt;code&gt;gigasecond&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The input code &lt;em&gt;declares a function&lt;/em&gt;, like in the optimal solution above, so the tree holds a &lt;code&gt;FunctionDeclaration&lt;/code&gt; with an &lt;code&gt;Identifier&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;gigasecond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FunctionDeclaration&lt;/span&gt;&lt;span class="dl"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gigasecond&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// The body is a block { ... }&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BlockStatement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is something it can search for. The most common way to &lt;em&gt;search&lt;/em&gt; in an AST is by &lt;em&gt;walking&lt;/em&gt; that tree. You start at some node (usually the root / program) and visit each item.&lt;/p&gt;

&lt;p&gt;We know that our parsed &lt;code&gt;EStree&lt;/code&gt; is &lt;strong&gt;compatible with &lt;a href="https://github.com/eslint/eslint" rel="noopener noreferrer"&gt;&lt;code&gt;eslint&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; and that &lt;a href="https://github.com/eslint/eslint" rel="noopener noreferrer"&gt;&lt;code&gt;eslint&lt;/code&gt;&lt;/a&gt;, just like &lt;a href="https://github.com/prettier/prettier" rel="noopener noreferrer"&gt;&lt;code&gt;prettier&lt;/code&gt;&lt;/a&gt; can recognise (and transform) code.&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;# Not a dev dependency!&lt;/span&gt;
yarn add eslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;TSESTree&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;@typescript-eslint/typescript-estree&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;traverse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eslint/lib/util/traverser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When writing this code, TypeScript will complain that there are no types for this library, which is unfortunately still true at moment of writing. However, you can &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/declarations.d.ts" rel="noopener noreferrer"&gt;copy this &lt;code&gt;declarations.d.ts&lt;/code&gt;&lt;/a&gt; I wrote in order to get type completion.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;enter&lt;/code&gt; method will be called for &lt;em&gt;each node&lt;/em&gt; in the program. Inside the &lt;code&gt;enter&lt;/code&gt; block, your in the "TraverserContext" which exposes two methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;this.skip()&lt;/code&gt;: skips the node from further traversal, meaning it will not   visit any other keys (and therefore children) of the current node;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;this.break()&lt;/code&gt;: completely stop traversing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finding the entrypoint is now straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;TSESTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&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;@typescript-eslint/typescript-estree&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionDeclaration&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;

&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="c1"&gt;// function name() {}&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FunctionDeclaration&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;node&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;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;node&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gigasecond&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;break&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="nx"&gt;entry&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; FunctionDeclaration({&lt;/span&gt;
&lt;span class="c1"&gt;//      id: { type: "Identifier", name: "gigasecond" }, ...&lt;/span&gt;
&lt;span class="c1"&gt;//    })&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately the walker above &lt;em&gt;only&lt;/em&gt; finds &lt;code&gt;FunctionDeclaration&lt;/code&gt; and fails on equivalent code usign an &lt;code&gt;ArrowFunctionExpression&lt;/code&gt; or &lt;code&gt;FunctionExpression&lt;/code&gt;. More on that later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 You can find this in &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/extract_main_method.ts" rel="noopener noreferrer"&gt;&lt;code&gt;analyzers/utils/extract_main_method.ts&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🔎 Finding the top-level constant
&lt;/h3&gt;

&lt;p&gt;The code finds the first of the two components. Now it also needs to find the second. A top-level &lt;code&gt;const&lt;/code&gt;, but the name is not known.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VariableDeclaration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;declarations&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VariableDeclarator&lt;/span&gt;&lt;span class="dl"&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="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&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;GIGASECOND_IN_MS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BinaryExpression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Left is another BinaryExpression with **&lt;/span&gt;
        &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;// Right is a Literal&lt;/span&gt;
        &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;const&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing here is &lt;em&gt;particularly&lt;/em&gt; helpful. Given the variations of data it needs to accept, I can't rely on &lt;code&gt;init&lt;/code&gt; being a certain type. The name is also not fixed as it's not &lt;code&gt;export&lt;/code&gt;ed and therefore not tested.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;However&lt;/em&gt;, there are a few constraints that will help here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It must be a top-level constant&lt;/li&gt;
&lt;li&gt;It can &lt;em&gt;not&lt;/em&gt; be named &lt;code&gt;gigasecond&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In an optimal solution, there is really only &lt;em&gt;one&lt;/em&gt; top-level constant that is not the &lt;code&gt;entry&lt;/code&gt;,
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FoundConst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VariableDeclaration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kind&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VariableDeclarator&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bigNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FoundConst&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;

&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="c1"&gt;// const NAME = ...&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VariableDeclaration&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;declaration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;declaration&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;declaration&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;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;declaration&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gigasecond&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;declaration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;bigNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;declaration&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;// This doesn't declare a variable, so skip the node&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&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;Later, I can check &lt;code&gt;bigNumber['kind']&lt;/code&gt; and make sure it's &lt;code&gt;const&lt;/code&gt;, or otherwise attach a message that &lt;code&gt;const&lt;/code&gt; is preferred.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💎 You can find this in &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/find_top_level_constants.ts" rel="noopener noreferrer"&gt;&lt;code&gt;analyzers/utils/find_top_level_constants.ts&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The algorithm
&lt;/h2&gt;

&lt;p&gt;Now that I found the &lt;code&gt;entry&lt;/code&gt; point, I can figure out what the name of the argument is (&lt;code&gt;date&lt;/code&gt;). Because I also know the top-level constant, I know what the constant name is &lt;code&gt;GIGASECOND_IN_MS&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing too fancy here. It's a &lt;code&gt;new&lt;/code&gt; expression with an expression as the first argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NewExpression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;callee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NewExpression&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;

&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="c1"&gt;// new Date(...)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NewExpression&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;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Identifier&lt;/span&gt;
          &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;newDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;// This doesn't declare a variable, so skip the node&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&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;blockquote&gt;
&lt;p&gt;💎 You can find this in &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/find_new_expression.ts" rel="noopener noreferrer"&gt;&lt;code&gt;analyzers/utils/find_new_expression.ts&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The inner expression is of type &lt;code&gt;BinaryExpression&lt;/code&gt;. In EStree compatible output, and operator with &lt;em&gt;two&lt;/em&gt; components (such as &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;) is a binary expression, whereas those with &lt;em&gt;one&lt;/em&gt; component (such as &lt;code&gt;~&lt;/code&gt; and &lt;code&gt;!&lt;/code&gt;) are unary expressions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;GIGASECOND_IN_MS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BinaryExpression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CallExpression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;callee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MemberExpression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getTime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GIGASECOND_IN_MS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quite a few things we've already seen and also a few new types. Let's look at those.&lt;/p&gt;

&lt;h3&gt;
  
  
  Properties of objects
&lt;/h3&gt;

&lt;p&gt;When the parser encounters a object property accessor (&lt;code&gt;object.property&lt;/code&gt;), it is parsed as a &lt;code&gt;MemberExpression&lt;/code&gt;. Depending on the way of writing, the property is either an &lt;code&gt;Identifier&lt;/code&gt; or a &lt;code&gt;Literal&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTime&lt;/span&gt;
&lt;span class="c1"&gt;// ^       ^&lt;/span&gt;
&lt;span class="c1"&gt;// object  property&lt;/span&gt;
&lt;span class="c1"&gt;// |       |&lt;/span&gt;
&lt;span class="c1"&gt;// |       identifier (name = getTime)&lt;/span&gt;
&lt;span class="c1"&gt;// identifier (name = date)&lt;/span&gt;

&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;// ^       ^&lt;/span&gt;
&lt;span class="c1"&gt;// object  property&lt;/span&gt;
&lt;span class="c1"&gt;// |       |&lt;/span&gt;
&lt;span class="c1"&gt;// |       literal (value = getTime)&lt;/span&gt;
&lt;span class="c1"&gt;// identifier (name = date)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  "Executing" a property
&lt;/h3&gt;

&lt;p&gt;If there are parentheses behind the &lt;code&gt;MemberExpression&lt;/code&gt;, the entire expression is parsed as a child of a &lt;code&gt;CallExpression&lt;/code&gt;. This is also the case for parentheses following an &lt;em&gt;indentifier&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// ---------| ^ |&lt;/span&gt;
&lt;span class="c1"&gt;// ^        | argument(s) of call expression&lt;/span&gt;
&lt;span class="c1"&gt;// member expression&lt;/span&gt;
&lt;span class="c1"&gt;//              |&lt;/span&gt;
&lt;span class="c1"&gt;// -------------|&lt;/span&gt;
&lt;span class="c1"&gt;// call expression&lt;/span&gt;

&lt;span class="nf"&gt;gigasecond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;INPUT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// ------|   ^   |&lt;/span&gt;
&lt;span class="c1"&gt;// ^     | argument of call expression&lt;/span&gt;
&lt;span class="c1"&gt;// identifier    |&lt;/span&gt;
&lt;span class="c1"&gt;//               |&lt;/span&gt;
&lt;span class="c1"&gt;// --------------|&lt;/span&gt;
&lt;span class="c1"&gt;// call expression&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Matching the identifiers
&lt;/h3&gt;

&lt;p&gt;There are two identifiers provided by the source code that I need to find and match against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the gigasecond first argument (used in &lt;code&gt;arg.getTime()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;the top-level constant (used in &lt;code&gt;time + CONSTANT&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;argumentName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entry&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="nx"&gt;name&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; "gigasecond"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;constantName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bigNumber&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="nx"&gt;name&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; "GIGASECOND_IN_MS"&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;optimalExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;// NOTE: passing in the newDate as root, so this is a subtree traversal!&lt;/span&gt;
&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSESTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="c1"&gt;// new Date(x.z() + y)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BinaryExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;break&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;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;optimalExpression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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="c1"&gt;// This allows the order to be reversed&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;constSide&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;leftType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Identifier&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expressionSide&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;leftType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CallExpression&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&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;constSide&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;expressionSide&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// throw new Error("not optimal! this is not x.z() + y")&lt;/span&gt;
          &lt;span class="nx"&gt;optimalExpression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="k"&gt;return&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;constSide&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;constantName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;optimalExpression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="k"&gt;return&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;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;expressionSide&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callee&lt;/span&gt;
        &lt;span class="nx"&gt;optimalExpression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Identifier&lt;/span&gt;
          &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;argumentName&lt;/span&gt;
          &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;
            &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Identifier&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AST_NODE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Literal&lt;/span&gt;
            &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;property&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;

      &lt;span class="k"&gt;break&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;blockquote&gt;
&lt;p&gt;💎 You can find this in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/find_member_call.ts" rel="noopener noreferrer"&gt;&lt;code&gt;analyzers/utils/find_member_call.ts&lt;/code&gt;&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/is_binary_expression.ts" rel="noopener noreferrer"&gt;&lt;code&gt;analyzers/utils/is_binary_expression.ts&lt;/code&gt;&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/is_identifier.ts" rel="noopener noreferrer"&gt;&lt;code&gt;analyzers/utils/is_identifier.ts&lt;/code&gt;&lt;/a&gt;, and&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/is_literal.ts" rel="noopener noreferrer"&gt;&lt;code&gt;analyzers/utils/is_literal.ts&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ✅ Automated Mentoring
&lt;/h2&gt;

&lt;p&gt;When all these pieces are put together, it is the analyzer for gigasecond. There are a few more things to check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the &lt;code&gt;bigNumber.kind&lt;/code&gt; equal to &lt;code&gt;"const"&lt;/code&gt;? If not, add a comment&lt;/li&gt;
&lt;li&gt;Is the value of &lt;code&gt;GIGASECOND_IN_MS&lt;/code&gt; using one of the comprehensions? If not, add a comment.&lt;/li&gt;
&lt;li&gt;Is there only &lt;em&gt;one&lt;/em&gt; argument to &lt;code&gt;gigasecond&lt;/code&gt;? Make sure it's not a &lt;code&gt;...splat&lt;/code&gt; argument, and that it has no &lt;code&gt;value = "default"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;gigasecond&lt;/code&gt; actually exported? Is the &lt;code&gt;export&lt;/code&gt; inline? if not, add a comment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the first one was mentioned (&lt;code&gt;kind&lt;/code&gt; equality check) and the second one is very similar to the &lt;em&gt;inner&lt;/em&gt; expression of the &lt;code&gt;new Date(...)&lt;/code&gt; call, I've left out how to implement these. You can check the &lt;a href="https://github.com/exercism/javascript-analyzer/tree/40116841771cc3aeb6d3fbe645495be0a3a405a5/src/analyzers/gigasecond" rel="noopener noreferrer"&gt;gigasecond analyzer source code&lt;/a&gt; if you need some inspiration. The third one is testing the &lt;code&gt;entry&lt;/code&gt; for &lt;code&gt;parameters&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As for &lt;code&gt;export&lt;/code&gt;s, these are handled by &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/extract_export.ts" rel="noopener noreferrer"&gt;&lt;code&gt;💎 extract_export&lt;/code&gt;&lt;/a&gt;, but I'll show you the gist of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  📦 Testing exports
&lt;/h3&gt;

&lt;p&gt;Exports in &lt;code&gt;JavaScript&lt;/code&gt; and &lt;code&gt;TypeScript&lt;/code&gt; basically come in three types. Those using a core language feature (read: use a keyword) are the easiest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InlineClass&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;defaultSpecifier&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;specifier&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;specifier&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;renamed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;default&lt;/code&gt; &lt;code&gt;export&lt;/code&gt; have their own token type &lt;code&gt;ExportDefaultDeclaration&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ExportDefaultDeclaration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;declaration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those without a &lt;code&gt;default&lt;/code&gt; modifier are of type &lt;code&gt;ExportNamedDeclaration&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ExportNamedDeclaration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;declaration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;declaration&lt;/code&gt; property is where it gets slightly tricky. The inline &lt;code&gt;export&lt;/code&gt; statements, regardless if they're default or not, are followed by the same token types as if they did not have the &lt;code&gt;export&lt;/code&gt; keyword similarly to how writing parentheses wraps an expression in a &lt;code&gt;CallExpression&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Inline exports
&lt;/h4&gt;

&lt;p&gt;This means that the first example is a &lt;code&gt;VariableDeclaration&lt;/code&gt; with a single &lt;code&gt;VariableDeclaractor&lt;/code&gt;: the &lt;code&gt;id&lt;/code&gt; is an &lt;code&gt;Identifier&lt;/code&gt; with &lt;code&gt;name = "inline"&lt;/code&gt; and the &lt;code&gt;init&lt;/code&gt; is an &lt;code&gt;ObjectExpression&lt;/code&gt;. Similarly the second example is a &lt;code&gt;ClassDeclaration&lt;/code&gt; with as &lt;code&gt;id&lt;/code&gt; an &lt;code&gt;Identifier&lt;/code&gt; with &lt;code&gt;name = "InlineClass"&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Specifier exports
&lt;/h4&gt;

&lt;p&gt;The third has a &lt;code&gt;declaration&lt;/code&gt; of type &lt;code&gt;Identifier&lt;/code&gt; with &lt;code&gt;name = "defaultSpecifier"&lt;/code&gt;. This is similar to &lt;code&gt;inline&lt;/code&gt; exports.&lt;/p&gt;

&lt;p&gt;The fourth and fifth however, &lt;em&gt;do &lt;strong&gt;not&lt;/strong&gt; have a &lt;code&gt;declaration&lt;/code&gt;&lt;/em&gt; property. Instead, they have a &lt;code&gt;specifiers&lt;/code&gt; property with, in this case, one item:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ExportSpecifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;specifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nl"&gt;exported&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&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;specifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// or "renamed"&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;Use the &lt;code&gt;local&lt;/code&gt; property to determine &lt;em&gt;what&lt;/em&gt; is exported (what the internal name is) and the &lt;code&gt;exported&lt;/code&gt; property how it's &lt;em&gt;imported&lt;/em&gt; (what the exported name is). &lt;/p&gt;

&lt;h4&gt;
  
  
  CommonJS exports
&lt;/h4&gt;

&lt;p&gt;Finally there are those exports that don't use a keyword but instead use the (as far as I'm concerned) defunct &lt;code&gt;module.exports&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;singleExport&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;specifier&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultExport&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renamed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;specifier&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since these don't use keywords, they're interpreted as &lt;code&gt;ExpressionStatement&lt;/code&gt;s, as they're &lt;code&gt;AssignmentExpression&lt;/code&gt;s. Here is a quick overview table of the important properties and representations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;expression&lt;/th&gt;
&lt;th&gt;type&lt;/th&gt;
&lt;th&gt;prop&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;module.exports.renamed = specifier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AssignmentExpression&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;operator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"="&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Identifier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;right&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"specifier"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MemberExpression&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;left&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;🔽 module.exports.renamed 🔽&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;module.exports.renamed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MemberExpression&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Identifier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;property&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"renamed"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MemberExpression&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;🔽 module.exports 🔽&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;module.exports&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MemberExpression&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Identifier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;property&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"exports"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Identifier&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"module"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is also the variant of using the &lt;code&gt;object['accessor']&lt;/code&gt;, where &lt;code&gt;accessor&lt;/code&gt; is not an &lt;code&gt;Identifier&lt;/code&gt; but a &lt;code&gt;Literal&lt;/code&gt;, but otherwise that is the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔀 Testing varations
&lt;/h2&gt;

&lt;p&gt;As mentioned before, there are many ways to write functions in JavaScript and TypeScript. In the &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils" rel="noopener noreferrer"&gt;source code&lt;/a&gt; for the analyzer there is a utility method &lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/extract_main_method.ts" rel="noopener noreferrer"&gt;&lt;code&gt;💎 extract_main_method&lt;/code&gt;&lt;/a&gt;. It can detect the following variations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="c1"&gt;// FunctionDeclaration&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&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="c1"&gt;// ArrowFunctionExpression&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="c1"&gt;// FunctionExpression&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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="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="c1"&gt;// ExportDefaultDeclaration + ObjectExpression + (Arrow)FunctionExpression&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the TypeScript specific variants (but they work on both)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// MethodDefinition + FunctionExpression&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;name&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;static&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ClassProperty + (Arrow)FunctionExpression&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Walking TypeScript Trees
&lt;/h2&gt;

&lt;p&gt;As you've noticed, all we did so far is checking the JavaScript code and shown how that is parsed and walked. In order to adapt the solution so that TypeScript code can be parsed with it, there is &lt;em&gt;one&lt;/em&gt; thing to change in the walker and a few extra properties to test for.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔑 Visitor Keys
&lt;/h3&gt;

&lt;p&gt;When the &lt;code&gt;traverser&lt;/code&gt; is walking the tree, it decides which nodes to "walk 🚶🏽‍" based on a set of keys called &lt;code&gt;visitor keys&lt;/code&gt;. Since &lt;code&gt;TypeScript&lt;/code&gt; is a &lt;em&gt;superset&lt;/em&gt; of &lt;code&gt;JavaScript&lt;/code&gt; it has the same keys and then some.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;visitorKeys&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;@typescript-eslint/parser/dist/visitor-keys&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="nx"&gt;visitorKeys&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look at the &lt;a href="https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/src/visitor-keys.ts" rel="noopener noreferrer"&gt;source of that file&lt;/a&gt;, you'll see that it actually imports the &lt;a href="https://github.com/eslint/eslint-visitor-keys" rel="noopener noreferrer"&gt;&lt;code&gt;eslint&lt;/code&gt; visitor keys&lt;/a&gt; (in order to visit all the JavaScript keys) and adds the specific TypeScript keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  📖 Type annotations
&lt;/h3&gt;

&lt;p&gt;These are interesting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gigasecond&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ClassDeclaration&lt;/span&gt;&lt;span class="dl"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Gigasecond&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// everything inside the class { body }&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ClassBody&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// a constructor is a regular method definition...&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MethodDefinition&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&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;constructor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FunctionExpression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="cm"&gt;/*...*/&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
          &lt;span class="na"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/*...*/&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nl"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;static&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// (typescript static keyword)&lt;/span&gt;
        &lt;span class="c1"&gt;// ... but with a special kind&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above has no special properties over the JavaScript equivalent, but that's because there &lt;em&gt;are no type annotations in the source&lt;/em&gt; except for in the &lt;code&gt;params&lt;/code&gt; of the &lt;code&gt;constructor&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// : ...&lt;/span&gt;
  &lt;span class="nx"&gt;typeAnnotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeAnnotation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;typeAnnotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Readonly&lt;/span&gt;
      &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeReference&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&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;Readonly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="c1"&gt;// &amp;lt;...&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;typeParameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeParameterInstantiation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Each type between the &amp;lt; brackets &amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;params&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeReference&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&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;Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few key observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The type annotation has its own visitor key &lt;code&gt;typeAnnotation&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;All the TypeScript nodes start with &lt;code&gt;TS&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;A generic type is just a &lt;code&gt;TSTypeReference&lt;/code&gt; with both a &lt;code&gt;typeName&lt;/code&gt; and one or multiple &lt;code&gt;typeParameters&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Stripping types is &lt;em&gt;almost&lt;/em&gt; as easy as removing the &lt;code&gt;typeAnnotation&lt;/code&gt; keys, which is &lt;em&gt;almost&lt;/em&gt; exactly what &lt;a href="https://babeljs.io/docs/en/babel-preset-typescript" rel="noopener noreferrer"&gt;babel's &lt;code&gt;preset-typescript&lt;/code&gt;&lt;/a&gt; does.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Class properties
&lt;/h3&gt;

&lt;p&gt;In TypeScript you can annotate class properties with keywords such as &lt;code&gt;private&lt;/code&gt; and &lt;code&gt;readonly&lt;/code&gt;. Additionally, they can have a type (which is &lt;code&gt;Date&lt;/code&gt; in this example).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gigasecond&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;futureDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&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 javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ClassProperty&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;futureDate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;// static keyword&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// readonly keyword&lt;/span&gt;
  &lt;span class="nx"&gt;accessibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;private&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// private, protected, public keywords&lt;/span&gt;
  &lt;span class="nx"&gt;typeAnnotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeAnnotation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;typeAnnotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeReference&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The TypeScript keywords &lt;code&gt;private&lt;/code&gt; and &lt;code&gt;readonly&lt;/code&gt; modify the &lt;em&gt;&lt;code&gt;ClassProperty&lt;/code&gt;&lt;/em&gt; directly, but the type is again on &lt;code&gt;typeAnnotation&lt;/code&gt;. If the type annotation is left out the source code (read: implicit &lt;code&gt;any&lt;/code&gt;), the &lt;code&gt;typeAnnotation&lt;/code&gt; key is not present on the AST.&lt;/p&gt;

&lt;h3&gt;
  
  
  ↩ Return types
&lt;/h3&gt;

&lt;p&gt;The final type we'll look at for now are function &lt;code&gt;return&lt;/code&gt; types. Most other type annotations are just variations on this and the ones mentioned before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gigasecond&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;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 javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MethodDefinition&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;"&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="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FunctionExpression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/*...*/&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="nx"&gt;returnType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeAnnotation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;typeAnnotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TSTypeReference&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identifier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// static keyword&lt;/span&gt;
  &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you might have noticed, the &lt;code&gt;typeAnnotation&lt;/code&gt; is &lt;strong&gt;not&lt;/strong&gt; on the &lt;code&gt;MethodDefinition&lt;/code&gt;. That is because a method definition on a class is actually binding a function expression &lt;code&gt;(): Date { ... }&lt;/code&gt; to the identifier &lt;code&gt;date&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the &lt;code&gt;FunctionExpression&lt;/code&gt; you can find the previously not encountered type annotation &lt;code&gt;returnType&lt;/code&gt;. Its structure is the same as &lt;code&gt;typeAnnotation&lt;/code&gt;s for &lt;code&gt;ClassProperty&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Interpreting code as an Abstract Syntax Tree and seeking out certain properties is a lot of tree walking; because there is a specification for the format of the output of certain AST Parsers, you can write tooling yourself.&lt;/p&gt;

&lt;p&gt;The contents of this article, in a different format, is being used to automatically approve the &lt;code&gt;gigasecond&lt;/code&gt; exercise, given that the student has provided an exact &lt;em&gt;variation&lt;/em&gt; of the optimal solution. There is enough surface to hook into the findings of the analyzer to provide meaningfull commentary, should the student not have provided an optimal solution.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffm0tv2c3j8ij5ur2ejf9.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffm0tv2c3j8ij5ur2ejf9.jpg" title="Photo by Miles Vanderlooven (https://unsplash.com/@mylesuk) on Unsplash (https://unsplash.com/)" alt="Photo of Erasmusbrug, Rotterdam, The Netherlands, displaying gray concrete bridge near buildings."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date" rel="noopener noreferrer"&gt;Date&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime" rel="noopener noreferrer"&gt;Date&lt;code&gt;#getTime&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse" rel="noopener noreferrer"&gt;Date&lt;code&gt;.parse&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/valueof" rel="noopener noreferrer"&gt;Date&lt;code&gt;#valueOf&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Analyzer reference
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/parsers/AstParser.ts" rel="noopener noreferrer"&gt;AstParser&lt;code&gt;#parse&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/extract_export.ts" rel="noopener noreferrer"&gt;&lt;code&gt;extractExport&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/extract_main_method.ts" rel="noopener noreferrer"&gt;&lt;code&gt;extractMainMethod&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/find_member_call.ts" rel="noopener noreferrer"&gt;&lt;code&gt;findMemberCall&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/find_new_expression.ts" rel="noopener noreferrer"&gt;&lt;code&gt;findNewExpression&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/find_top_level_constants.ts" rel="noopener noreferrer"&gt;&lt;code&gt;findTopLevelConstants&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/is_binary_expression.ts" rel="noopener noreferrer"&gt;&lt;code&gt;isBinaryExpression&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/is_identifier.ts" rel="noopener noreferrer"&gt;&lt;code&gt;isIdentifier&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils/is_literal.ts" rel="noopener noreferrer"&gt;&lt;code&gt;isLiteral&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exercism repositories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/exercism/problem-specifications/blob/master/exercises/gigasecond" rel="noopener noreferrer"&gt;&lt;code&gt;problem-specifications/gigasecond&lt;/code&gt;&lt;/a&gt; | &lt;a href="https://github.com/exercism/problem-specifications/blob/master/exercises/gigasecond/canonical-data.json" rel="noopener noreferrer"&gt;canonical-data&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript/blob/master/exercises/gigasecond/gigasecond.spec.js" rel="noopener noreferrer"&gt;&lt;code&gt;javascript/gigasecond&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/typescript/blob/master/exercises/gigasecond/gigasecond.test.ts" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/gigasecond&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/tree/40116841771cc3aeb6d3fbe645495be0a3a405a5/src/analyzers/gigasecond" rel="noopener noreferrer"&gt;&lt;code&gt;javascript-analyzer/gigasecond&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/exercism/javascript-analyzer/blob/9ff332bb365bdb84c53e7b14064479ae13876fac/src/analyzers/utils" rel="noopener noreferrer"&gt;&lt;code&gt;javascript-analyzer&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Packages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/typescript-eslint/typescript-eslint" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/parser&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/typescript-eslint/typescript-eslint" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/typescript-estree&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prettier/prettier" rel="noopener noreferrer"&gt;&lt;code&gt;prettier&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/eslint/eslint" rel="noopener noreferrer"&gt;&lt;code&gt;eslint&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/eslint/eslint-visitor-keys" rel="noopener noreferrer"&gt;&lt;code&gt;eslint-visitor-keys&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>showdev</category>
      <category>opensource</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Control flow in reduce/inject (ruby)</title>
      <dc:creator>Derk-Jan Karrenbeld</dc:creator>
      <pubDate>Mon, 03 Jun 2019 23:29:49 +0000</pubDate>
      <link>https://dev.to/xpbytes/control-flow-in-reduce-inject-ruby-25b4</link>
      <guid>https://dev.to/xpbytes/control-flow-in-reduce-inject-ruby-25b4</guid>
      <description>&lt;p&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; (&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-inject"&gt;&lt;code&gt;inject&lt;/code&gt;&lt;/a&gt;) is one of the most powerful&lt;br&gt;
methods that exists on the &lt;a href="https://ruby-doc.org/core/Enumerable.html"&gt;Enumerable&lt;/a&gt; module, meaning that the&lt;br&gt;
methods are available on any instances of any class that includes this module,&lt;br&gt;
including &lt;a href="https://ruby-doc.org/core/Array.html"&gt;Array&lt;/a&gt;, &lt;a href="https://ruby-doc.org/core/Hash.html"&gt;Hash&lt;/a&gt;, &lt;a href="https://ruby-doc.org/stdlib/libdoc/set/rdoc/Set.html"&gt;Set&lt;/a&gt; and&lt;br&gt;
&lt;a href="https://ruby-doc.org/core/Range.html"&gt;Range&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; can be used in a &lt;a href="https://en.wikipedia.org/wiki/MapReduce"&gt;MapReduce&lt;/a&gt; process,&lt;br&gt;
often is the base for comprehensions and is a great way to group values or&lt;br&gt;
calculate a single value (&lt;em&gt;reducing a set of values to a single value&lt;/em&gt;) given a&lt;br&gt;
set of values.&lt;/p&gt;

&lt;p&gt;This article quickly shows you how to skip values / conditionally return values&lt;br&gt;
during a &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; iteration and how to break early / return a&lt;br&gt;
different value and stop iteration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DWl4tjEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6h5h6rrr3zuvh7sudfni.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DWl4tjEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6h5h6rrr3zuvh7sudfni.jpg" alt="Bridge In The Mist in Stockholm, Sweden" title="Photo by Anders Jildén (https://unsplash.com/@andersjilden) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap 💬
&lt;/h2&gt;

&lt;p&gt;From the documentation, given an instance &lt;code&gt;enum&lt;/code&gt; (an &lt;strong&gt;Enumerable&lt;/strong&gt;) calling&lt;br&gt;
&lt;code&gt;enum.reduce&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Combines all elements of &amp;lt;i&amp;gt;enum&amp;lt;/i&amp;gt; by applying a binary&lt;/span&gt;
&lt;span class="c1"&gt;# operation, specified by a block or a symbol that names a&lt;/span&gt;
&lt;span class="c1"&gt;# method or operator.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;An example of using &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; would be write a function that sums&lt;br&gt;
all the elements in a collection:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;##&lt;/span&gt;
&lt;span class="c1"&gt;# Sums each item in the enumerable (naive)&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# @param [Enumerable] enum the enumeration of items to sum&lt;/span&gt;
&lt;span class="c1"&gt;# @return [Numeric] the sum&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;sum&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;##&lt;/span&gt;
&lt;span class="c1"&gt;# Sums each item in the enumerable (reduce block)&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Each iteration the result of the block is the passed in previous_result.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# @param [Enumerable] enum the enumeration of items to sum&lt;/span&gt;
&lt;span class="c1"&gt;# @return [Numeric] the sum&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;previous_result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;previous_result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;##&lt;/span&gt;
&lt;span class="c1"&gt;# Sums each item in the enumerable (reduce method)&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Each iteration the :+ symbol is sent as a message to the current result with&lt;/span&gt;
&lt;span class="c1"&gt;# the next value as argument. The result is the new current result.&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# @param [Enumerable] enum the enumeration of items to sum&lt;/span&gt;
&lt;span class="c1"&gt;# @return [Numeric] the sum&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;##&lt;/span&gt;
&lt;span class="c1"&gt;# Alias for enum.sum&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; takes an optional initial value, which is used instead of&lt;br&gt;
the first item of the collection, when given.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to control the flow?
&lt;/h2&gt;

&lt;p&gt;When working with &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; you might find yourself in one of two&lt;br&gt;
situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you want to conditionally return a different value for the iteration (which is
used as base value for the next iteration)&lt;/li&gt;
&lt;li&gt;you want to break out early (stop iteration altogether)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  next ⏭
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;next&lt;/code&gt; keyword allows you to return early from a &lt;code&gt;yield&lt;/code&gt; block, which is the&lt;br&gt;
case for any enumeration.&lt;/p&gt;

&lt;p&gt;Let’s say you the sum of a set of numbers, but want &lt;strong&gt;half&lt;/strong&gt; of any &lt;strong&gt;even&lt;/strong&gt;&lt;br&gt;
number, and &lt;strong&gt;double&lt;/strong&gt; of any &lt;strong&gt;odd&lt;/strong&gt; number:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;halfly_even_doubly_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Not too bad. But now another business requirement comes in to skip any number&lt;br&gt;
under 5:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;halfly_even_doubly_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ugh. That’s not very nice ruby code. Using &lt;code&gt;next&lt;/code&gt; it could look like:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;halfly_even_doubly_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;next&lt;/code&gt; works in any enumeration, so if you’re just processing items using&lt;br&gt;
&lt;code&gt;.each&lt;/code&gt; , you can use it too:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;odd?&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# 2&lt;/span&gt;
&lt;span class="c1"&gt;# 4&lt;/span&gt;
&lt;span class="c1"&gt;# 6&lt;/span&gt;
&lt;span class="c1"&gt;# 8&lt;/span&gt;
&lt;span class="c1"&gt;# 10&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 1..10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  break 🛑
&lt;/h3&gt;

&lt;p&gt;Instead of skipping to the next item, you can completely stop iteration of a an&lt;br&gt;
enumerator using &lt;code&gt;break&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we have the same business requirements as before, but we have to return the&lt;br&gt;
number &lt;strong&gt;42&lt;/strong&gt; if the item is &lt;em&gt;exactly 7&lt;/em&gt;, this is what it would look like:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;halfly_even_doubly_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Again, this works in any loop. So if you’re using find to try to &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-find"&gt;&lt;code&gt;find&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
an item in your enumeration and want to &lt;em&gt;change the &lt;code&gt;return&lt;/code&gt; value&lt;/em&gt; of that&lt;br&gt;
&lt;code&gt;find&lt;/code&gt;, you can do so using &lt;code&gt;break&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_my_red_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;color&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'red'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;find_my_red_item&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"umbrella"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;color: &lt;/span&gt;&lt;span class="s2"&gt;"black"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"shoe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;color: &lt;/span&gt;&lt;span class="s2"&gt;"red"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"pen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;color: &lt;/span&gt;&lt;span class="s2"&gt;"blue"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 'shoe'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  StopIteration
&lt;/h3&gt;

&lt;p&gt;You might have heard about or seen &lt;a href="https://ruby-doc.org/core/StopIteration.html"&gt;&lt;code&gt;raise StopIteration&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
It is a special exception that you can use to stop iteration of an enumeration,&lt;br&gt;
as it is caught be &lt;a href="https://ruby-doc.org/core/Kernel.html#method-i-loop"&gt;&lt;code&gt;Kernel#loop&lt;/code&gt;&lt;/a&gt;, but its use-cases are limited as&lt;br&gt;
you should not try to control flow using &lt;code&gt;raise&lt;/code&gt; or &lt;a href="https://ruby-doc.org/core/Kernel.html#method-i-fail"&gt;&lt;code&gt;fail&lt;/code&gt;&lt;/a&gt;. The&lt;br&gt;
&lt;a href="https://airbrake.io/blog/ruby-exception-handling/stopiteration"&gt;airbrake blog&lt;/a&gt; has a &lt;a href="https://airbrake.io/blog/ruby-exception-handling/stopiteration"&gt;good article&lt;/a&gt; about this&lt;br&gt;
use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use reduce
&lt;/h2&gt;

&lt;p&gt;If you need a guideline when to use &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt;, look no further. I&lt;br&gt;
use the four rules to determine if I need to use &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; or&lt;br&gt;
&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-each_with_object"&gt;&lt;code&gt;each_with_object&lt;/code&gt;&lt;/a&gt; or something else.&lt;/p&gt;

&lt;p&gt;I use &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;reducing&lt;/em&gt; a collection of values to a &lt;strong&gt;smaller&lt;/strong&gt; result (e.g. 1 value)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;grouping&lt;/em&gt; a collection of values (use &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-group_by"&gt;&lt;code&gt;group_by&lt;/code&gt;&lt;/a&gt; if possible)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;changing&lt;/em&gt; immutable primitives / value objects (returning a new value)&lt;/li&gt;
&lt;li&gt;you need a &lt;em&gt;new value&lt;/em&gt; (e.g. new &lt;a href="https://ruby-doc.org/core/Array.html"&gt;Array&lt;/a&gt; or &lt;a href="https://ruby-doc.org/core/Hash.html"&gt;Hash&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alternatives 🔀
&lt;/h3&gt;

&lt;p&gt;When the use case does not match the guidelines above, most of the time I&lt;br&gt;
actually need &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-each_with_object"&gt;&lt;code&gt;each_with_object&lt;/code&gt;&lt;/a&gt; which has a similar&lt;br&gt;
signature, but does not build a new value based on the &lt;code&gt;return&lt;/code&gt; value of a block,&lt;br&gt;
but instead iterates the collection with a predefined “object”, making it much&lt;br&gt;
easier to use logic inside the block:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;doubles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;each_with_object&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="c1"&gt;# same as result.push(num * 2)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]&lt;/span&gt;

&lt;span class="n"&gt;doubles_over_ten&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="nf"&gt;each_with_object&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [12, 14, 16, 18, 20]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Use &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-each_with_object"&gt;&lt;code&gt;each_with_object&lt;/code&gt;&lt;/a&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building a new container (e.g. &lt;a href="https://ruby-doc.org/core/Array.html"&gt;Array&lt;/a&gt; or &lt;a href="https://ruby-doc.org/core/Hash.html"&gt;Hash&lt;/a&gt;).
&lt;strong&gt;Note&lt;/strong&gt; that you’re not really &lt;em&gt;reducing&lt;/em&gt; the current collection to a
&lt;em&gt;smaller&lt;/em&gt; result, but instead conditionally or unconditionally &lt;em&gt;map&lt;/em&gt; values.&lt;/li&gt;
&lt;li&gt;you want logic in your block without repeating the result value (because you
&lt;em&gt;must&lt;/em&gt; provide a return value when using &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My use case
&lt;/h2&gt;

&lt;p&gt;The reason I looked into control flow using &lt;code&gt;reduce&lt;/code&gt; is because I was iterating&lt;br&gt;
through a list of value objects that represented a migration path. Without using&lt;br&gt;
&lt;a href="https://ruby-doc.org/core/Enumerator/Lazy.html"&gt;&lt;code&gt;lazy&lt;/code&gt;&lt;/a&gt;, I wanted an elegant way of representing when these&lt;br&gt;
migrations should run, so used semantic versioning. The migrations enumerable is&lt;br&gt;
a sorted list of migrations with a semantic version attached.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;migrated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;migration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;migrated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;migration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;migrated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="n"&gt;migrated&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;current_version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_range?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="n"&gt;migrated&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function &lt;code&gt;in_range?&lt;/code&gt; determines if a migration is executed, based on the&lt;br&gt;
current “input” version, and the semantic version of the migration. This will&lt;br&gt;
execute migrations until the “current” version becomes in-range, at which point&lt;br&gt;
it should execute the final migration and stop.&lt;/p&gt;

&lt;p&gt;The alternatives were less favourable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-take_while"&gt;&lt;code&gt;take_while&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-select"&gt;&lt;code&gt;select&lt;/code&gt;&lt;/a&gt; and friends are able to
&lt;em&gt;filter&lt;/em&gt; the list, but it requires multiple iterations of the migrations
collection (filter, then “execute”);&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-find"&gt;&lt;code&gt;find&lt;/code&gt;&lt;/a&gt; would be a good candidate, but I needed to change the input
so that would require me to have a bookkeeping variable keeping track of
“migrated”. Bookkeeping variables are almost never necessary in Ruby.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h_3a0nUn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rdbjr94rx7rp3ftw3rl0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h_3a0nUn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rdbjr94rx7rp3ftw3rl0.jpg" alt="Photo called &amp;quot;It’s Own Kind of Tranquility&amp;quot;, displaying a series of windmills on either side of a 'water street (canal)' in Alblasserdam, The Netherlands" title="Photo by Vishwas Katti (https://unsplash.com/@vishkatti) on Unsplash (https://unsplash.com/)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Array.html"&gt;Array&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html"&gt;Enumerable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-each_with_object"&gt;Enumerable#&lt;code&gt;each_with_object&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-find"&gt;Enumerable#&lt;code&gt;find&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-group_by"&gt;Enumerable#&lt;code&gt;group_by&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-inject"&gt;Enumerable#&lt;code&gt;inject&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerator/Lazy.html"&gt;Enumerable#&lt;code&gt;lazy&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-reduce"&gt;Enumerable#&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-select"&gt;Enumerable#&lt;code&gt;select&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Enumerable.html#method-i-take_while"&gt;Enumerable#&lt;code&gt;take_while&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Hash.html"&gt;Hash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Kernel.html#method-i-fail"&gt;Kernel#&lt;code&gt;fail&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Kernel.html#method-i-loop"&gt;Kernel#&lt;code&gt;loop&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/Range.html"&gt;Range&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/stdlib/libdoc/set/rdoc/Set.html"&gt;Set&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ruby-doc.org/core/StopIteration.html"&gt;StopIteration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>reduce</category>
      <category>controlflow</category>
      <category>mapreduce</category>
    </item>
  </channel>
</rss>
