<?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: Peter Hozák</title>
    <description>The latest articles on DEV Community by Peter Hozák (@aprillion).</description>
    <link>https://dev.to/aprillion</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%2F497909%2Fca7cd684-0035-46f7-9da9-edde4ace608a.jpeg</url>
      <title>DEV Community: Peter Hozák</title>
      <link>https://dev.to/aprillion</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aprillion"/>
    <language>en</language>
    <item>
      <title>Self-Join in Sheets, SQL, Python, and JavaScript</title>
      <dc:creator>Peter Hozák</dc:creator>
      <pubDate>Sat, 23 Jul 2022 13:27:36 +0000</pubDate>
      <link>https://dev.to/aprillion/self-join-in-sheets-sql-python-and-javascript-2km4</link>
      <guid>https://dev.to/aprillion/self-join-in-sheets-sql-python-and-javascript-2km4</guid>
      <description>&lt;p&gt;Let's start with a self-referencing data table &lt;code&gt;employees&lt;/code&gt;:&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="n"&gt;id&lt;/span&gt;  &lt;span class="n"&gt;name&lt;/span&gt;                 &lt;span class="n"&gt;manager_id&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="n"&gt;Djan&lt;/span&gt; &lt;span class="n"&gt;Seriy&lt;/span&gt; &lt;span class="n"&gt;Anaplian&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;   &lt;span class="n"&gt;Fal&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;Ngeestra&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;   &lt;span class="n"&gt;Turminder&lt;/span&gt; &lt;span class="n"&gt;Xuss&lt;/span&gt;       &lt;span class="mi"&gt;1&lt;/span&gt;           &lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;  &lt;span class="n"&gt;Djan&lt;/span&gt; &lt;span class="n"&gt;Seriy&lt;/span&gt; &lt;span class="n"&gt;Anaplian&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;   &lt;span class="n"&gt;Jase&lt;/span&gt;                 &lt;span class="mi"&gt;2&lt;/span&gt;           &lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;  &lt;span class="n"&gt;Fal&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;Ngeestra&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can we get the other record?&lt;/p&gt;

&lt;h2&gt;
  
  
  Sheets
&lt;/h2&gt;

&lt;p&gt;As with so many questions in Excel, Numbers, Calc, or Sheets, let's solve it by adding a column with an &lt;a href="https://www.excel-easy.com/examples/index-match.html" rel="noopener noreferrer"&gt;INDEX and MATCH&lt;/a&gt; formula:&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="cp"&gt;# 1. find row number of the matching record
&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&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="cp"&gt;# 2. get value from the other record
&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&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="cp"&gt;# 3. handle errors
&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;iferror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;C2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&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="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can try out the example in &lt;a href="https://docs.google.com/spreadsheets/d/1mfHKy5uThKXGpv6Lu1-00elDaA3ZBQvGK1Ngq6D2FDM" rel="noopener noreferrer"&gt;Sheets&lt;/a&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqgyc6gd0skkg4ofvdbn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqgyc6gd0skkg4ofvdbn.jpg" alt="google sheets with INDEX and MATCH formula for self-join employees table" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  SQL
&lt;/h2&gt;

&lt;p&gt;In virtually all database query languages, joins to a table itself work exactly like &lt;a href="https://www.postgresql.org/docs/current/tutorial-join.html" rel="noopener noreferrer"&gt;joins between tables&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;manager&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;manager_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try out in &lt;a href="http://sqlfiddle.com/#!17/53a00/3" rel="noopener noreferrer"&gt;SQL Fiddle&lt;/a&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a5uqjo280jsokil6wvz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8a5uqjo280jsokil6wvz.jpg" alt="left join in sql" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Python
&lt;/h2&gt;

&lt;p&gt;To represent the &lt;a href="https://www.geeksforgeeks.org/normal-forms-in-dbms/" rel="noopener noreferrer"&gt;"normal form"&lt;/a&gt; of our data in Python, let's choose a dictionary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;employees&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="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Djan Seriy Anaplian&lt;/span&gt;&lt;span class="sh"&gt;'&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="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Fal &lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s"&gt;Ngeestra&lt;/span&gt;&lt;span class="sh"&gt;'&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="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Turminder Xuss&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;manager_id&lt;/span&gt;&lt;span class="sh"&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;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Jase&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;manager_id&lt;/span&gt;&lt;span class="sh"&gt;'&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to change it to a list of nested dictionaries, replacing each &lt;code&gt;manager_id&lt;/code&gt; pointer with a live &lt;code&gt;manager&lt;/code&gt; object, to give ourselves the most freedom to explore. Using imperative procedural code style with a &lt;a href="https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions" rel="noopener noreferrer"&gt;walrus operator :=&lt;/a&gt; and &lt;a href="https://docs.python.org/3/library/stdtypes.html#dict.pop" rel="noopener noreferrer"&gt;dict.pop()&lt;/a&gt;, that might look like following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;em&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;manager_id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;em&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;manager_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;em&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;manager&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;manager_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;employees&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;short&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Anaplian&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;employees&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;short&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Fal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example lives on &lt;a href="https://replit.com/@Aprillion/self-join#main.py" rel="noopener noreferrer"&gt;Repl.it&lt;/a&gt;. Will it work for a deeper management hierarchy? Would it break for a cyclical structure?&lt;/p&gt;

&lt;p&gt;Let me know if you would like to see other code styles in Python, functional like JS below or &lt;a href="https://en.wikipedia.org/wiki/Functional_reactive_programming" rel="noopener noreferrer"&gt;FRP&lt;/a&gt; like the Sheets above (with &lt;a href="https://pandas.pydata.org/" rel="noopener noreferrer"&gt;Pandas&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript / TypeScript
&lt;/h2&gt;

&lt;p&gt;We can start with the exact same &lt;code&gt;employees&lt;/code&gt; object as in the Python example, but this time we choose a more team-friendly approach inspired by functional programming style that avoids mutation and side effects, because the nested objects might be used in other parts of the project. We also want to avoid too many levels of nesting to keep it simple, so we replace &lt;code&gt;manager_id&lt;/code&gt; with an optional immutable string &lt;code&gt;managerName&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;employeesWithManager&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;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;employees&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;manager_id&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;manager_id&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="na"&gt;managerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;employees&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;manager_id&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="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can play with a TypeScript version on &lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAogtmANgexBaBeKBvAUFKAOwEM4IAuKAZ2ACcBLQgc3yjmJKYloH16ATAPyVCAVzgAjbrgC+uAMbJCNKBAQo0EKpQBKERbX4AeMZO4AaWOtToAfFCx4CBAIyVsJMpQDkAEQBWHFAAytz0IFAAgiRI9BzeMuasBABM7p4UUN4AYsSIUAA63gByXFp0xAlJzlAAzOmkmd4AKqK0cIz83FAAGqJUVN6W7JzcfPyULonJUAAsDV5ZAFLEVBBDbBzEXLwClCnTcgpKKmpINloA6vTAABYAsls7DlAA8hL++sAAdABueaItAAKM4adBUACUrG+7DAQKBHkawyeYwEMghDnsCJmGWqzm+BKBI22qP4UAAZOScDMCMSdsVGpRQRcqABtOmkgC63wyM3RePRUOOymQiAg3xQTBB1k0VGud0eo1oUKAA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;, or run the JavaScript example directly in your browser console:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi11i17xrym9buylmuct.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi11i17xrym9buylmuct.jpg" alt="js example in browser console" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you noticed how we can use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" rel="noopener noreferrer"&gt;spread syntax&lt;/a&gt; in object literal  (&lt;code&gt;{...expr}&lt;/code&gt;) with a more complex expression, not just a variable name? Can you refactor the code to use an explicit variable at that place? Which version is more readable for you and for your project coworkers?&lt;/p&gt;




&lt;p&gt;👋 &lt;em&gt;Hi, I am Peter Hozák, a.k.a. &lt;a href="https://github.com/Aprillion/" rel="noopener noreferrer"&gt;Aprillion&lt;/a&gt;. Do you have any follow-up or similar questions? Let's discuss in the comments below or on &lt;a href="https://twitter.com/aprillion0042" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Quantum Developers</title>
      <dc:creator>Peter Hozák</dc:creator>
      <pubDate>Thu, 20 Jan 2022 17:14:15 +0000</pubDate>
      <link>https://dev.to/aprillion/quantum-developers-5b67</link>
      <guid>https://dev.to/aprillion/quantum-developers-5b67</guid>
      <description>&lt;p&gt;Just like electrons, software developers are impossible to observe without interfering.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://en.wikipedia.org/wiki/Double-slit_experiment" rel="noopener noreferrer"&gt;double-slit experiment&lt;/a&gt;, zapping electrons with microwave radiation changes your results (for historical reasons, we call that zapping process "observation," because the photon-electron interaction on the human scale is called "seeing with your own eyes," but this process is slightly more destructive to the internal state of chill of an electron [this has led to a lot of metaphysical misunderstandings of the beautiful city of Copenhagen {but let's not get there &amp;lt;yet&amp;gt;}]).&lt;/p&gt;

&lt;p&gt;For a long time, humanity believed that the largest beautiful quantum objects were black holes (or rainbows, depending on who you ask), but the last few centuries of corporate fashion has created a completely new phenomenon that's been appreciated infinitely more: &lt;strong&gt;managers trust people for whole 2 weeks at a time without pestering them every 5 minutes: "are we there yet?"&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Before a &lt;a href="https://en.wikipedia.org/wiki/Scrum_(software_development)#Sprint" rel="noopener noreferrer"&gt;Scrum Sprint&lt;/a&gt; was invented, a lot of project managers tracked the tasks by percentage of completion. Centering a DIV was either 50% done or 80% done, but it wasn't acceptable &lt;em&gt;not&lt;/em&gt; to know the exact internal state of every microtask. And as we all know, intellectual workers are a lazy folk who cannot be trusted (yeah yeah, a drive for the efficiency of our glucose consumption is driven by evolution, it's biologically impossible not to be lazy, whatever). What changed?&lt;/p&gt;

&lt;p&gt;As with any improvement in life, &lt;a href="https://en.wikipedia.org/wiki/Empiricism" rel="noopener noreferrer"&gt;empirical evidence&lt;/a&gt; came to the rescue. When asked about minute details, developers are never finished, the results are never perfect. When left alone with a bag of tasks, those tasks get done, somehow and good enough. Over time, managers of the surviving corporations  learned a magic ritual - trust the developers to do as much as possible without checking for progress too often. Sometimes, it takes 2x longer as their original estimate, other times they finish 5x faster. But somehow, when we ask about status of some particular task, the quantum state of that task collapses into a binary state "finished" or "not finished" and the latter state always takes 1 more week to finish - so asking the same question too often will make a task infinite with non-zero probability.&lt;/p&gt;

&lt;p&gt;So here we are. Managers in 2022 trust developers. It happens by a miracle, and the spell can be broken any time they try to micromanage. The good managers just intuitively follow the &lt;em&gt;Aprillion's Law of Quantum Developers&lt;/em&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just like electrons, software developers are impossible to observe without interfering.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;👋 &lt;em&gt;I am Peter, a.k.a. &lt;a href="https://github.com/Aprillion/" rel="noopener noreferrer"&gt;Aprillion&lt;/a&gt;. My strong opinions are held weakly, discussion is open here in the comments or on &lt;a href="https://twitter.com/aprillion0042" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>management</category>
      <category>agile</category>
      <category>jokes</category>
    </item>
    <item>
      <title>Multisort in Sheets, SQL, Python, and JavaScript</title>
      <dc:creator>Peter Hozák</dc:creator>
      <pubDate>Sun, 25 Jul 2021 14:37:55 +0000</pubDate>
      <link>https://dev.to/aprillion/multisort-in-sheets-sql-python-and-javascript-4p</link>
      <guid>https://dev.to/aprillion/multisort-in-sheets-sql-python-and-javascript-4p</guid>
      <description>&lt;p&gt;Sorting a 2D table is straightforward in most software solutions designed for data processing. If you are like me, sorting by single column was easy to remember after discovering the feature for the first time. But sorting by multiple columns can be a headache sometimes, so here are my recipes for some of the most popular tools.&lt;/p&gt;

&lt;p&gt;Let's imagine that following table represents some useful data. We want to sort our records by column A (ascending) first, then for all records with the same value of A, we want to sort those sub-groups by column B (descending):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; A↓  B   C              A↓  B↑  C
 1   1   a              1   3   c
 1   2   b              1   2   b
 1   3   c    -----&amp;gt;    1   1   a
 2   1   d              2   3   f
 2   2   e              2   2   e
 2   3   f              2   1   d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sheets
&lt;/h2&gt;

&lt;p&gt;We can sort by multiple columns in Microsoft Excel by using &lt;code&gt;Data -&amp;gt; Sort&lt;/code&gt; dialog in the ribbon, or in Google Sheets by using &lt;code&gt;Data -&amp;gt; Sort range&lt;/code&gt; in the menu (presumably, OpenOffice Calc and other tools have something similar):&lt;/p&gt;

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

&lt;h2&gt;
  
  
  SQL
&lt;/h2&gt;

&lt;p&gt;Comma separated list of column name expressions is supported in the &lt;code&gt;ORDER BY&lt;/code&gt; clause at least since SQL:1999 (from what I could see in &lt;a href="https://learnsql.com/blog/history-of-sql-standards/" rel="noopener noreferrer"&gt;The History of SQL Standards&lt;/a&gt;). And it's supported by all major implementations (even SQLite). You can try the following &lt;a href="http://sqlfiddle.com/#!17/ad85e/1/0" rel="noopener noreferrer"&gt;example on SQL Fiddle&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;myData&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Python 🐼
&lt;/h2&gt;

&lt;p&gt;Practical (or lazy) people like me use &lt;a href="https://pandas.pydata.org/" rel="noopener noreferrer"&gt;pandas&lt;/a&gt; to organize all their Python data that need multi-column sort, just like in this &lt;a href="https://replit.com/@Aprillion/multisort#main.py" rel="noopener noreferrer"&gt;Replit example&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;B&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JavaScript / TypeScript
&lt;/h2&gt;

&lt;p&gt;While there might be some nice data libraries in the JavaScript world too, let's imagine we receive a JSON data from some API that is an array of objects like &lt;code&gt;[{A: 1, B: 1, C: 'a'}, ...]&lt;/code&gt; and that we don't want to compare all suitable libraries for features, bundle size, and performance. Let's say we want a nice little utility function that accepts some array and SQL-like order criteria, then returns a sorted array, like following:&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="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonLikeData&lt;/span&gt;&lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;asc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;desc&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;Is this even possible? Easy to do? That's what we asked ourselves with &lt;a href="https://twitter.com/kettanaito/" rel="noopener noreferrer"&gt;Artem&lt;/a&gt; while he was implementing &lt;a href="https://github.com/mswjs/data/pull/103/files" rel="noopener noreferrer"&gt;PR#103 in mswjs/data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is a simplified version that you can &lt;a href="https://www.typescriptlang.org/play?target=6#code/GYVwdgxgLglg9mABAZzgJygUwCYB4DSimAHlmNsilGjGAOYB8AFALABQii2AhlNwFyIAgmjTcAnrgBKmCOjz4ANInABrMHADuYBg0XtO8zGgBC4wSLGSZctAuUBybsggPEAH0QPsmFw93sAJSIAN4GiGiYUCBoSADaAHRJPHwAugmoGExM3MoARsEAvAyh4ZzA6IhMcmDIUIgQNFg03IhwwG12xmbBYRycAzV1iHGqmOLKAG7cADYgmKmIhYgA8nkAVrJQCZhg1DC+1U3GMNyBcQAMi84jSl7Orh5ePn6pZYMIwzDIQi5LiNM5pgloVlk4-O9ODAOjlRuNFiU8nDxKlepCBpForFEN9fhBEAB+RAARkQggAtMT0QBfdHQqrcZGLXCIJFjFFo-oDDFRGJIXF-ImUskkmnogD04qIM2QmGU9KgAAtxohuJEiABHECzZQ1WBgeaIKBwRBgEj1RowZqnd60tjvSU4joaeqYvk4RDiKLKVrccis1XqzBa2as8SqmYzBrHFrvN3Yi7hamBdh29hDC3ISYAGRgYwAIrxWssAAbsIQDEwDADC7FJnHrqrrAwATAM8s3OABmQbsNsNgbYPutgaYYfdgbAdglhL7AC2TECGQADjMrUwHAAdMAOJdz7jLphoLRLErHzQrtdQJjizfIADU4sCKftbAziHWqDAuYLRf+ECzH9MELPgMjXCBMCYYk9wPI8T2KRBwjWTZoASYBjznABRPYaEOc8En3Q8mEBeZdTgGYAElyBIIoSjid4AJzPNgKLS5UjiORKOo4hUn0LkAVmeZwlRF8X3TT56kyLBsBA4sUHQaSmE-BAgNk5Q4hCIRBHBVxqWUEITG0l5dNRdhxNqcjMASGY4DoJgpJwWSXyAA" rel="noopener noreferrer"&gt;try in TypeScript Playground&lt;/a&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;sorted&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;orderBy&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;data&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;for &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;criteria&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;orderBy&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;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="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;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;criteria&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAsc&lt;/span&gt; &lt;span class="o"&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;asc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&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;return&lt;/span&gt; &lt;span class="nx"&gt;isAsc&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="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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;b&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;return&lt;/span&gt; &lt;span class="nx"&gt;isAsc&lt;/span&gt; &lt;span class="p"&gt;?&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="mi"&gt;1&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;// else, if they are equal, continue to next criteria&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// if not returned yet, a and b are equal by all criteria&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;p&gt;If you are not familiar with JavaScript &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort" rel="noopener noreferrer"&gt;Array.sort&lt;/a&gt;, it is an in-place method that takes a function as an argument. It calls your comparison function multiple times, each time with 2 elements from the array. It expects a return value of &lt;code&gt;-1&lt;/code&gt; if the first element should be sorted before the second, &lt;code&gt;1&lt;/code&gt; if the first element belongs after the second, and &lt;code&gt;0&lt;/code&gt; if the pre-existing sort order should be preserved (which is needed for a "stable sort"). So we need to iterate over all criteria and return a value as soon as we can determine it... We would need to handle a few more edge cases in practice, but that's all for the core idea how we can approach the multisort implementation in JavaScript.&lt;/p&gt;

&lt;p&gt;See you next time, when I will talk about joining data sets in Sheets, SQL, Python and JavaScript.&lt;/p&gt;




&lt;p&gt;👋 &lt;em&gt;I am Peter, a.k.a. &lt;a href="https://github.com/Aprillion/" rel="noopener noreferrer"&gt;Aprillion&lt;/a&gt;. My strong opinions are held weakly, discussion is open here in the comments or on &lt;a href="https://twitter.com/aprillion0042" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Issues are not tasks</title>
      <dc:creator>Peter Hozák</dc:creator>
      <pubDate>Sun, 06 Jun 2021 14:23:09 +0000</pubDate>
      <link>https://dev.to/aprillion/issues-are-not-tasks-2io9</link>
      <guid>https://dev.to/aprillion/issues-are-not-tasks-2io9</guid>
      <description>&lt;p&gt;JIRA tickets, GitHub issues, Trello cards, Excel todo lists. Our in-brain memories are not enough to plan and track all the tasks in our software projects; we (programmers, testers, product owners, project managers, ...) collectively decided that we need external tools.&lt;/p&gt;

&lt;p&gt;And our tools became so good in collecting ideas that every team on Earth now generates more ideas than they can ever hope to complete. For many of us, we learned to accept this fact of life as an inevitable emergent property in the "machine" for producing complex software (&lt;em&gt;whether or not we hate all of those estimation and prioritization meetings from the core of our souls&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Yet, for many people (especially for programmers motivated by the purpose of a project), ever-growing backlogs are a big source of anxiety and burnout. And the truth is, the more "open" issues there are, the harder it is to organize them. Backlog cleaning sessions and automated tools to close inactive issues are ever more popular.&lt;/p&gt;

&lt;p&gt;However, issues are not tasks. They are a mental tool, to help with our memory and to help with our communication. If we treat them as such, we will have a somewhat easier time deciding how to organize our issue tracking tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if we split "ideas" from "confirmed issues" to another tracking system, will it improve or hinder our memories?&lt;/li&gt;
&lt;li&gt;if we weave our "vision", "goals", "stories", "bugs", and "sub-task" into a big hierarchy of artifacts, will it help or slow down our communication?&lt;/li&gt;
&lt;li&gt;if we close a bunch of tickets or just lower the priority, will it make a bigger mess of duplicates or keep us better organized?&lt;/li&gt;
&lt;li&gt;what should be the title and metadata, what do we need to remember for search, what should pop up from search results, and do we need some reports?&lt;/li&gt;
&lt;li&gt;given that we &lt;a href="https://medium.com/@peter.hozak/assumptions-treacherously-precious-2abe4b2b8f14" rel="noopener noreferrer"&gt;cannot document everything&lt;/a&gt;, what to put into description or comments; what is ephemeral enough for a chat or a coffee break?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The answers will be different in every team, so we can reasonable expect that the tracking tools will be either configurable or niche.&lt;/p&gt;

&lt;p&gt;So, if you feel weighted down by your issue tracking system, remember for your next retrospective:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Issues are a tool for our memory and communication. How can we configure them better?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;👋 &lt;em&gt;I am Peter, a.k.a. &lt;a href="https://github.com/Aprillion/" rel="noopener noreferrer"&gt;Aprillion&lt;/a&gt;. My strong opinions are held weakly, discussion is open here in the comments or on &lt;a href="https://twitter.com/aprillion0042" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Schrödinger's cat explains TypeScript&lt;Generics&gt;</title>
      <dc:creator>Peter Hozák</dc:creator>
      <pubDate>Sat, 27 Mar 2021 14:16:00 +0000</pubDate>
      <link>https://dev.to/aprillion/shrodinger-s-cat-explains-typescript-lt-generics-gt-239p</link>
      <guid>https://dev.to/aprillion/shrodinger-s-cat-explains-typescript-lt-generics-gt-239p</guid>
      <description>&lt;p&gt;In 1935, Erwin complained to Albert about a problem in Quantum Mechanics. The bug report is now known as the &lt;a href="https://en.wikipedia.org/wiki/Schr%C3%B6dinger%27s_cat" rel="noopener noreferrer"&gt;Schrödinger's cat&lt;/a&gt; thought experiment and the fix, to &lt;em&gt;shut up and calculate,&lt;/em&gt; is still deployed in production. Many of those calculations involved matrix multiplication of multidimensional vectors and that took a lot of space on blackboards. Thus, Paul established the &lt;a href="https://en.wikipedia.org/wiki/Bra%E2%80%93ket_notation" rel="noopener noreferrer"&gt;⟨bra|ket⟩&lt;/a&gt; notation to help the cool kids make fewer mistakes.&lt;/p&gt;

&lt;p&gt;In 2013, library authors complained to Jonathan about a problem in TypeScript. They wanted to make their utilities more reusable, without &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any" rel="noopener noreferrer"&gt;&lt;em&gt;any&lt;/em&gt;&lt;/a&gt; compromise. So starting with version &lt;a href="https://www.theregister.com/2013/06/18/typescript_update_0_9/" rel="noopener noreferrer"&gt;0.9&lt;/a&gt;, we can now &lt;em&gt;shut up and &lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" rel="noopener noreferrer"&gt;&amp;lt;Generics&amp;gt;&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Union cats
&lt;/h1&gt;

&lt;p&gt;Let's imagine writing a library, "Quantum Cats," that checks whether a &lt;code&gt;cat&lt;/code&gt; is dead or alive:&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;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&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;checkCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// inferred type: 'dead'|'alive'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkCat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&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;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwghsKBeKBvAzsBBXdAuKAcgBMI5jCAfQuAGwEsA3CQgXwFgAoLgM2wDsAxsHoB7flEEALCIIDW8YAApBCAooCUaLlCgAnCMGx6Jq4ADpMOdFw7dOAegdR6-HhD0HiUUJAIkyCmo6JhYuQXFMfQh0bFpEFGlZBQQlDCwjfCIQ5jYNIA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And for a while, &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types" rel="noopener noreferrer"&gt;union types&lt;/a&gt; will be all that we need.&lt;/p&gt;

&lt;h1&gt;
  
  
  Generic cats
&lt;/h1&gt;

&lt;p&gt;However, our users expect no cats to be harmed in the process of checking! There is not just one type of cats that are all "dead or alive," we need to distinguish different types of cats:&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;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&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;checkCat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&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;return&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// inferred type: 'alive'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkCat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&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;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwghsAPAZWAgrgZwHxQLxQDemawWAXFKhpgL4CwAUEwGboB2AxsAJYD27KJwAWETgGt4SamUxQIAD2AR2AEzkByVRDiqNAHw1wANjwBuEDdgAUTKEISUpKUlmxMAlETtQAThDJfQU4EADoSGiYGZkYAelioHnYWCF9-VShQSEojUwsNJk4BEj8ITHRjYHwhUQkpa2JXTByTc0taDyA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reading the code
&lt;/h2&gt;

&lt;p&gt;Our users are now happy, but we have to explain what we did to our future selves after lunch. As a first step, let's try to read the code above. Everyone might read it differently, and that's fine, here is just an example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we have a type &lt;code&gt;Cat&lt;/code&gt;, that is a generic

&lt;ul&gt;
&lt;li&gt;it takes a parameter, type &lt;code&gt;Status&lt;/code&gt;, which is implicitly &lt;code&gt;unknown&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;value of type &lt;code&gt;Cat&lt;/code&gt; is an object with one property, &lt;code&gt;status&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;type of that property is &lt;code&gt;Status&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;then, we declare a function &lt;code&gt;checkCat&lt;/code&gt;, that has a generic type

&lt;ul&gt;
&lt;li&gt;the function itself takes one parameter, &lt;code&gt;cat&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the function type takes one generic parameter, type &lt;code&gt;Status&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Status&lt;/code&gt; extends a union of 2 types, both are string literals, namely &lt;code&gt;dead&lt;/code&gt; &lt;em&gt;or&lt;/em&gt; &lt;code&gt;alive&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the function parameter &lt;code&gt;cat&lt;/code&gt; has a type, which is an instance of a generic that we get by invoking &lt;code&gt;Cat&lt;/code&gt; with parameter &lt;code&gt;Status&lt;/code&gt; inside the angle brackets

&lt;ul&gt;
&lt;li&gt;note: just like in HTML, we write the angle brackets using less-than and greater-than signs &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;, not the Unicode characters &lt;code&gt;⟨⟩&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;the function contains 1 return statement&lt;/li&gt;

&lt;li&gt;the return expression is &lt;code&gt;cat&lt;/code&gt; dot &lt;code&gt;status&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;the return type is inferred&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;then, we make an assignment to a constant variable &lt;code&gt;result&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;the right-hand side consists of a function call&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;checkCat&lt;/code&gt; is called with one argument, an object literal that has one property, &lt;code&gt;status&lt;/code&gt;, whose value is a string, &lt;code&gt;alive&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;type of the function is inferred from the argument&lt;/li&gt;
&lt;li&gt;type of the new variable is also inferred&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding generics
&lt;/h2&gt;

&lt;p&gt;Now that we can read the code, what to make of it? Let's think of generics as higher order types, a concept similar to &lt;a href="https://redd.one/blog/thinking-in-functions-higher-order-functions" rel="noopener noreferrer"&gt;higher order functions&lt;/a&gt; (when a function returns a function, or if it takes another function as a parameter to call back):&lt;/p&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  A generic is a type that accepts one or more types as parameters and it returns a different type based on those.
&lt;/h4&gt;


&lt;/blockquote&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;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&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;CatAlive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&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;// same as {status: 'alive'}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CatDead&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;// same as {status: 'dead'}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CatUndefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// {status: undefined}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwghsAPAZWAgrgZwHxQLxQDemawWAXFKhpgL4CwAUE6JLAgIIA2AlgG7QC8JAHI4vASNwB6aVExwAttDiYiJGpTESIIho1bRhAEQhwAJlHztR5s+alRZ8pSrXFSFKCLsW9LcCMEAFUAOzsAMx5QiEshBER0cIgomPMZOQ9NKCTI6NjaIA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can restrict what types to allow in the parameters (&lt;code&gt;extends&lt;/code&gt;), and we can provide a default type (&lt;code&gt;&amp;lt;... = default&amp;gt;&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&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;alive&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&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;CatAlive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="c1"&gt;// {status: 'alive'}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CatDead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;// {status: 'dead'}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CatDeadOrAlive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&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;// CatDead | CatAlive&lt;/span&gt;

&lt;span class="c1"&gt;// not possible because of type error:&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CatUndefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwghsAPAZWAgrgZyhAHsCAOwBNsByYiOYsgHzLgBsBLANwjKgF4oGX2yAPm5QA3gFgAUFCiY0wLAC4oqDJikBfKVNCRYCAIL9oPeMCgB6C2LlrlfNhy2Td0MwBEqxEWcQUvQpbWorYKmPaU1GTOrvrAntQA8gBORo4+CH6RNPRMjoFWcQnetHFp7NqShYQA9uZgNZiYzABGjNAtEADGcFjQNQBmULEQyck1yYo64G4IAKokEAPMhBDeppnoi8urxIJAA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can use generics to define function types:&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;function&lt;/span&gt; &lt;span class="nf"&gt;checkCat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&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;Status&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&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;checkCat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&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;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwghsAPAZWAgrgZyhAHsCAOwBNsByYiOYsgHzLgBsBLANwjKgF4oGX2yAPm5QA3gFgAUFCiY0wLAC4oqDJikBfKVIBm6QgGNgzAPaEoBgBYQDAa3jAAjCnlYc+IqV6VqdPmw5BAAopGQMEZQcXNUEpAEplVQVsCWkoACcIBXTzcOAAOjk1TW1JAzM5C2s7BwAmEWjk9wISch8aeiYAoRC0vMiERqxYyTjuYTzC10wgA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; &lt;code&gt;&amp;lt;Status&amp;gt;() =&amp;gt; {}&lt;/code&gt; will not work in &lt;code&gt;*.tsx&lt;/code&gt; files, that is ambiguous with a JSX opening tag, but we can use &lt;code&gt;&amp;lt;Status extends unknown&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can use generic instances inside other generics:&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;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&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;isCatAlive&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Cat&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;|&lt;/span&gt;&lt;span class="kc"&gt;undefined&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="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&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;feedCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&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="c1"&gt;// inferred type: {status: string}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// @ts-expect-error&lt;/span&gt;
&lt;span class="c1"&gt;// Type 'string' is not assignable to type '"alive"'&lt;/span&gt;
&lt;span class="nf"&gt;feedCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&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="nf"&gt;isCatAlive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;feedCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&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;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?ssl=1&amp;amp;ssc=1&amp;amp;pln=21&amp;amp;pc=2#code/C4TwDgpgBAwghsAPAZWAgrgZwHxQLxQDemawWAXFKhpgL4CwAUEwGboB2AxsAJYD27KD0zxgAQQA2PAG4REMKBAAewCOwAmmWAkQkATj3YBzAD4d1EFoYjrs2ABRMoUTgkowmASkqvgQrQoAZNpIAORwUrKhuIROUHoQZHqCvgB0JDT4eAThkRChTAyMbFy8AlAsEDai9r7uOrky+dieRHEJSYKhgLwbgNx7BYxFTAD0w0LslXoJ6lCgkJTEpBRQ+oZGRZwCJC4I+EQZZJiUjVFDjKNQAALAmAC0ypDc91N8eiNjACrg0KGrxqH+KDsPh+OCYTA8IzsOAAIwk0GAfFm3ygoQARBEmmiBpVqghaghPEwmDwWFB7MJRJImgTgJ5WrFGM5ceoar5WhdACjkhSAA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And we can mix and match generics with &lt;a href="https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads" rel="noopener noreferrer"&gt;function overloads&lt;/a&gt; for our wildly reusable JavaScript utilities, even if we only know how to type some of our use cases, we don't have to be purrfect:&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;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="o"&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&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;checkMany&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S1&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;cats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S1&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;S1&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;checkMany&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;S2&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;cats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S1&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;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S2&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;S1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;S2&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;checkMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&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;cats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt;&lt;span class="nx"&gt;s&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;s&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;result1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkMany&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt; &lt;span class="c1"&gt;// inferred type: [string]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkMany&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="c1"&gt;// inferred type: ['d', 'a']&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&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="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&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="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;result3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkMany&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="c1"&gt;// inferred type: string[] 🤷‍♂️&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&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="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&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="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&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="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;&lt;em&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwghsAPAZWAgrgZygXip4AJwEsA7AcwD5coBvTALilQ0wF8BYAKG4DN1SAY2DEA9qSiCAFhEEBrALJxSIFAEZKACkEJGUANrwkyDQF0AlE30nTfAcLETpsxctUmANMwBMWncD1DBHVKLyMUXwsrTx9bLn4hEXFJGXklFW1dJiN9KPwiMnJcu0THFJd0kEyA7IRc8zpuKChCCGB0QiddADoAWzgwTU16Ngacakxzbk4eLkFxAhaITHQAG2A1Gmc0t019eiYAcjhDtgsoAHoLqDJeCEJWgBMoUEgrAhIKOPnSRdaV9beLapVwZfSXa63e5PF7gCBWQ6PQ5eY6HOLNA5QRGHKBwbA-AhsDxNOh6VG4-ELYAzCzcAnAJYA4AAZmBFV24KuN1IdweEGer3h+U+RVMUEAfBuAdl3ALAEgCEyQDwfyTMeS8ZIqUSlWSThS1b9qcSuBitTjVfSaeYgA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Quantum cats
&lt;/h1&gt;

&lt;p&gt;So a few feature requests later, out code might look like this:&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;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bury&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="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;feed&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="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&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;checkCat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S&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;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;probability&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="nx"&gt;Cat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&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;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;probability&lt;/span&gt; &lt;span class="o"&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="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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&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;cat&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;probability&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dead&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bury&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;😿&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;feed&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;😻&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quantumCat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;simulator&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;cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quantumCat&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;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bury&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;multipleWorlds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;simulator&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;statistics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multipleWorlds&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="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="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="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statistics&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;&lt;em&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwghsAPAZWAgrgZygXigcgBMI5D8AffOAGwEsA3CC9AO2IDNaWJCA+XAFBQoqDNggAPYBDbYiJMlAD8UAN6Y0wLAC4RmrABooAI3QAnELoAUASlz8NZrgHMAvkKi7RW8VJmE5GgYmZTUNMS99TCN2CB5rOxwHYCcWNw9ddSjIsXcBdlYAY2BaAHsWKEKACwhCgGt4JGQoSWlZAmJSCio6RnxeK0KEXUaUXhttD1HkXnyikvLKmvrGweHYBERWDi4eXiMwM1LjOGNaOlAlXRZ0AFtjCDMJqc35LsogvtmClmKyiuqtQaCDWwBGCAORxOZwuIFwUAADAA6ACsdlUHlo7CgoKR4R86I8wjMEC0ZgBCA87mEWJxAFkEFUkWY4GxSrdbFBEFBDsdTudaKBCcJiaTzBUshEOgp8EZTBYEvYCIBeDcA-Hv4alQTUkskS-E6AifJgxOKERVJFWAbj2NQI8oVyhooABHdCsrS3RrwyU+XTbCCcbiEPI-P6LTC0W7oagIUpmTkY4T2liOobAeGAlYgl1uu6NGweHXiyoIPFRXA4PA9YL4UKppGxHic3R1+UgWy2gRJx2R6glMDUCAAdVj1AC8IAgmYWSB60cOZPp1YAIwIhEAfVXCJsNiRtzgYCs4Z7MaenYdafxtA0tEK2DwPb7A+HZlHmGZPHQhQgViscEKhSMElMCjYBEn4BMoD-QoAG0gJAgBdeEoNgiBgN7RCVGQuD0KgABqKAl08AiCzFclIP-W0jFUVxIOwAAlWpY0IRBHBcIwbnuR5xgEM9k1KAckWoUpnEPTQrxKW98yAA" rel="noopener noreferrer"&gt;TS Playground&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We introduced some &lt;a href="https://www.typescriptlang.org/docs/handbook/2/conditional-types.html" rel="noopener noreferrer"&gt;conditional types&lt;/a&gt; and &lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html" rel="noopener noreferrer"&gt;type narrowing&lt;/a&gt; to be able to call &lt;code&gt;cat.feed()&lt;/code&gt; without TypeScript errors about the foolishness of feeding potentially dead cats. Hopefully, we can still read the code.&lt;/p&gt;




&lt;p&gt;👋 &lt;em&gt;I am Peter, a.k.a. &lt;a href="https://github.com/Aprillion/" rel="noopener noreferrer"&gt;Aprillion&lt;/a&gt;. I considered transcribing the last code example into English sentences, but that would be worth a separate post (or even a youtube video) if enough people are interested. Please let me know in the comments here or on &lt;a href="https://twitter.com/aprillion0042" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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