<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Max Burson</title>
        <link>https://maxburson.com</link>
        <description>undefined</description>
        <lastBuildDate>Sun, 31 Jan 2021 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>Copyright (c) Maxwell Burson.
All rights reserved.
</copyright>
        <item>
            <title><![CDATA[TypeScript Discriminated Unions: Problems and Solutions]]></title>
            <link>https://maxburson.com/posts/discriminated-unions-problems-and-solutions</link>
            <guid>discriminated-unions-problems-and-solutions</guid>
            <pubDate>Sun, 31 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Solutions to problems with TypeScript's discriminated unions]]></description>
            <content:encoded><![CDATA[<p>Disclaimer: Following solutions create new problems, including more types and sometimes more JavaScript.</p>
<h2>Problem: Union properties don't narrow</h2>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token keyword">declare</span> <span class="token keyword">function</span> <span class="token generic-function"><span class="token function">assertType</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">interface</span> <span class="token class-name">Circle</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'circle'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">interface</span> <span class="token class-name">Square</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'square'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">interface</span> <span class="token class-name">House<span class="token operator">&lt;</span>TDoor<span class="token operator">></span></span> <span class="token punctuation">{</span>
  door<span class="token operator">:</span> TDoor<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">declare</span> <span class="token keyword">const</span> house<span class="token operator">:</span> House<span class="token operator">&lt;</span>Circle <span class="token operator">|</span> Square<span class="token operator">></span><span class="token punctuation">;</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>house<span class="token punctuation">.</span>door<span class="token punctuation">.</span>kind <span class="token operator">===</span> <span class="token string">'circle'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// Argument of type 'House&lt;Circle | Square>' is not assignable to parameter of</span>
  <span class="token comment">// type 'House&lt;Circle>'.</span>
  <span class="token comment">//                        👇👇👇</span>
  <span class="token generic-function"><span class="token function">assertType</span><span class="token generic class-name"><span class="token operator">&lt;</span>House<span class="token operator">&lt;</span>Circle<span class="token operator">>></span></span></span><span class="token punctuation">(</span>house<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h3>Solution 1: Narrow the property by itself, then reconstruct</h3>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token keyword">declare</span> <span class="token keyword">const</span> house<span class="token operator">:</span> House<span class="token operator">&lt;</span>Circle <span class="token operator">|</span> Square<span class="token operator">></span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token punctuation">{</span> door <span class="token punctuation">}</span> <span class="token operator">=</span> house<span class="token punctuation">;</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span>door<span class="token punctuation">.</span>kind <span class="token operator">===</span> <span class="token string">'circle'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token generic-function"><span class="token function">assertType</span><span class="token generic class-name"><span class="token operator">&lt;</span>House<span class="token operator">&lt;</span>Circle<span class="token operator">>></span></span></span><span class="token punctuation">(</span><span class="token punctuation">{</span> door <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h3>Solution 2: Union property to union the whole thing</h3>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token keyword">declare</span> <span class="token keyword">function</span> <span class="token generic-function"><span class="token function">assertType</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">type</span> <span class="token class-name">Shape</span> <span class="token operator">=</span> Circle <span class="token operator">|</span> Square<span class="token punctuation">;</span>

<span class="token keyword">interface</span> <span class="token class-name">House<span class="token operator">&lt;</span>TDoor <span class="token keyword">extends</span> Shape <span class="token operator">=</span> Shape<span class="token operator">></span></span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> TDoor<span class="token punctuation">[</span><span class="token string">'kind'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  door<span class="token operator">:</span> TDoor<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">declare</span> <span class="token keyword">const</span> house<span class="token operator">:</span> House<span class="token operator">&lt;</span>Circle<span class="token operator">></span> <span class="token operator">|</span> House<span class="token operator">&lt;</span>Square<span class="token operator">></span><span class="token punctuation">;</span>

<span class="token comment">// Still does not work</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>house<span class="token punctuation">.</span>door<span class="token punctuation">.</span>kind <span class="token operator">===</span> <span class="token string">'circle'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// Argument of type 'House&lt;Circle> | House&lt;Square>' is not assignable to parameter of</span>
  <span class="token comment">// type 'House&lt;Circle>'.</span>
  <span class="token comment">//                        👇👇👇</span>
  <span class="token generic-function"><span class="token function">assertType</span><span class="token generic class-name"><span class="token operator">&lt;</span>House<span class="token operator">&lt;</span>Circle<span class="token operator">>></span></span></span><span class="token punctuation">(</span>house<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// Using the new property we added does work though!</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>house<span class="token punctuation">.</span>kind <span class="token operator">===</span> <span class="token string">'circle'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token generic-function"><span class="token function">assertType</span><span class="token generic class-name"><span class="token operator">&lt;</span>House<span class="token operator">&lt;</span>Circle<span class="token operator">>></span></span></span><span class="token punctuation">(</span>house<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<p>Related TypeScript issue: <a href="https://github.com/Microsoft/TypeScript/issues/27272">https://github.com/Microsoft/TypeScript/issues/27272</a></p>
<h2>Problem: Discriminated union definitions are verbose</h2>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token comment">// So verbose! 👎 Too much boilerplate for a one-off use case.</span>

<span class="token keyword">interface</span> <span class="token class-name">Circle</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'circle'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">interface</span> <span class="token class-name">Square</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'square'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">Shape</span> <span class="token operator">=</span> Circle <span class="token operator">|</span> Square<span class="token punctuation">;</span>

<span class="token keyword">const</span> data<span class="token operator">:</span> Shape <span class="token operator">=</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'circle'</span> <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h3>Solution: Skip defining types</h3>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token comment">// More pragmatic</span>

<span class="token keyword">type</span> <span class="token class-name">Shape2</span> <span class="token operator">=</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'circle'</span> <span class="token punctuation">}</span> <span class="token operator">|</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'square'</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> data2<span class="token operator">:</span> Shape2 <span class="token operator">=</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'circle'</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token comment">/* --- */</span>

<span class="token comment">// Most pragmatic! 👍 Don't bother defining the types at all. We'll still get</span>
<span class="token comment">// type errors if we mess up.</span>
<span class="token keyword">const</span> data3 <span class="token operator">=</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'circle'</span> <span class="token keyword">as</span> <span class="token keyword">const</span> <span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h2>Problem: Pulling a property off a union is verbose</h2>
<h3>Solution: Define more propery types to allow direct property access</h3>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token keyword">type</span> <span class="token class-name">Result<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span> <span class="token operator">=</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'ok'</span><span class="token punctuation">;</span> value<span class="token operator">:</span> <span class="token constant">T</span> <span class="token punctuation">}</span> <span class="token operator">|</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'err'</span><span class="token punctuation">;</span> msg<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">declare</span> <span class="token keyword">const</span> result<span class="token operator">:</span> Result<span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">></span><span class="token punctuation">;</span>

<span class="token comment">// So verbose! 🤮 (More of my code looks like this than would ideal)</span>
<span class="token keyword">const</span> value <span class="token operator">=</span> result<span class="token punctuation">.</span>kind <span class="token operator">===</span> <span class="token string">'ok'</span> <span class="token operator">?</span> result<span class="token punctuation">.</span>value <span class="token operator">:</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>

<span class="token comment">/* --- */</span>

<span class="token keyword">type</span> <span class="token class-name">Result2<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span> <span class="token operator">=</span>
  <span class="token operator">|</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'ok'</span><span class="token punctuation">;</span> value<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">;</span> msg<span class="token operator">?</span><span class="token operator">:</span> <span class="token keyword">undefined</span> <span class="token punctuation">}</span>
  <span class="token operator">|</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'err'</span><span class="token punctuation">;</span> value<span class="token operator">?</span><span class="token operator">:</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span> msg<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">declare</span> <span class="token keyword">const</span> result2<span class="token operator">:</span> Result2<span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">></span><span class="token punctuation">;</span>

<span class="token comment">// Much better! 😌</span>
<span class="token keyword">const</span> value2 <span class="token operator">=</span> result2<span class="token punctuation">.</span>value<span class="token punctuation">;</span>

<span class="token keyword">declare</span> <span class="token keyword">const</span> result3<span class="token operator">:</span> Result2<span class="token operator">&lt;</span><span class="token punctuation">{</span> nested<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span><span class="token operator">></span><span class="token punctuation">;</span>

<span class="token comment">// And it works with optional chaining! 🎊</span>
<span class="token keyword">const</span> value3 <span class="token operator">=</span> result3<span class="token punctuation">.</span>value<span class="token operator">?.</span>nested<span class="token punctuation">;</span></code></pre></div>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TypeScript: Discriminated Unions & Polymorphism]]></title>
            <link>https://maxburson.com/posts/discriminated-unions-vs-polymorphism</link>
            <guid>discriminated-unions-vs-polymorphism</guid>
            <pubDate>Sun, 17 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Notes on picking between polymorphism and discriminated unions when writing typescript]]></description>
            <content:encoded><![CDATA[<p>Notes on picking between polymorphism and discriminated unions when writing typescript.</p>
<h2>Discriminated Unions</h2>
<p><a href="">https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html</a></p>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token comment">// In TypeScript, discriminated unions are a union with a "discriminate".</span>
<span class="token comment">// In the below example, "kind" is the discriminate.</span>

<span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name">Animal</span> <span class="token operator">=</span>
  <span class="token operator">|</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'sheep'</span> <span class="token punctuation">}</span>
  <span class="token operator">|</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'cat'</span><span class="token punctuation">,</span> breed<span class="token operator">:</span> <span class="token string">'house'</span> <span class="token operator">|</span> <span class="token string">'wild'</span> <span class="token punctuation">}</span>
  <span class="token operator">|</span> <span class="token punctuation">{</span> kind<span class="token operator">:</span> <span class="token string">'human'</span><span class="token punctuation">,</span> greeting<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">speak</span><span class="token punctuation">(</span>animal<span class="token operator">:</span> Animal<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">switch</span> <span class="token punctuation">(</span>animal<span class="token punctuation">.</span>kind<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">case</span> <span class="token string">'cat'</span><span class="token operator">:</span>
      <span class="token keyword">return</span> animal<span class="token punctuation">.</span>breed <span class="token operator">===</span> <span class="token string">'domestic'</span> <span class="token operator">?</span> <span class="token string">'meow'</span> <span class="token operator">:</span> <span class="token string">'ROAR'</span><span class="token punctuation">;</span>
    <span class="token keyword">case</span> <span class="token string">'sheep'</span><span class="token operator">:</span>
      <span class="token keyword">return</span> <span class="token string">'baa'</span><span class="token punctuation">;</span>
    <span class="token keyword">case</span> <span class="token string">'human'</span><span class="token operator">:</span>
      <span class="token keyword">return</span> animal<span class="token punctuation">.</span>greeting<span class="token punctuation">;</span>
    <span class="token keyword">default</span>
      <span class="token function">assertNever</span><span class="token punctuation">(</span>animal<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<ul>
<li>Simple use cases results in brief code</li>
<li>Natural pattern is to <code class="language-text">switch</code> in consuming code, which can become verbose when there is a large number of functions that access many variants.</li>
<li>Callers of <code class="language-text">speak</code> have full knowledge of the data in each animal.</li>
<li>Caller of <code class="language-text">speak</code> need to import the the type <code class="language-text">Animal</code>, and the function separately.</li>
<li>Logic for each variant lives alongside similar logic for other variants</li>
<li>Naturally organizes functions near their consumers. Because of this:
<ul>
<li><code class="language-text">speak</code> is more likely it will get deleted when it is no longer used.</li>
<li>When code splitting, only required functions are be included <sup><a href="#user-content-fn-1" id="user-content-fnref-1" data-footnote-ref aria-describedby="footnote-label">1</a></sup></li>
</ul>
</li>
<li>Because <code class="language-text">Animal</code> doesn't control its own data, we likely won't be organizing many tests around <code class="language-text">Animal</code>. Instead, many test will be against individual functions, or against callers of those functions.</li>
</ul>
<h3>Possible file layout</h3>
<p><img src="/posts/discriminated-unions-vs-polymorphism/union-file-layout.jpg" alt="Discriminated union possible file layout"></p>
<h2>Polymorphism</h2>
<p><a href="">https://www.typescriptlang.org/docs/handbook/interfaces.html</a></p>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token comment">// Could also be a class</span>
<span class="token keyword">interface</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Sheep</span> <span class="token keyword">implements</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">'baa'</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">createCat</span><span class="token punctuation">(</span>breed<span class="token operator">:</span> <span class="token string">'house'</span> <span class="token operator">|</span> <span class="token string">'wild'</span><span class="token punctuation">)</span><span class="token operator">:</span> Animal <span class="token punctuation">{</span>
	<span class="token keyword">return</span> <span class="token punctuation">{</span>
		breed<span class="token punctuation">,</span>
    <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>breed <span class="token operator">===</span> <span class="token string">'house'</span> <span class="token operator">?</span> <span class="token string">'meow'</span> <span class="token operator">:</span> <span class="token string">'ROAR'</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Human</span> <span class="token keyword">implements</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
	<span class="token function">constructor</span><span class="token punctuation">(</span>
    <span class="token keyword">private</span> greeting<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>greeting<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<ul>
<li>Scales cleanly to large numbers of variants</li>
<li>Callers of speak only need to import <code class="language-text">Animal</code>, or nothing at all.</li>
<li>Information is hidden from callers of speak.</li>
<li><code class="language-text">Animal</code> related logic can be more easily be stubbed out when testing other code.</li>
<li>Logic for each variant lives alongside that variants definition</li>
<li>Naturally organisms logic near type definitions. Because of this:
<ul>
<li>Tests naturally become written around <code class="language-text">Animal</code>, and its functions.</li>
<li>Harder to delete/detect unused code</li>
<li>When code splitting, more unused methods will be included in bundles <sup><a href="#user-content-fn-1" id="user-content-fnref-1-2" data-footnote-ref aria-describedby="footnote-label">1</a></sup></li>
</ul>
</li>
<li>Allows for easy dependency injection</li>
</ul>
<h3>Possible file layout</h3>
<p><img src="/posts/discriminated-unions-vs-polymorphism/polymorphic-file-layout.jpg" alt="Polymorphic possible file layout"></p>
<h2>Polymorphic Discriminated Unions</h2>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token keyword">interface</span> <span class="token class-name">IAnimal</span> <span class="token punctuation">{</span>
	kind<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Sheep</span> <span class="token keyword">implements</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
	kind <span class="token operator">=</span> <span class="token string">'sheep'</span> <span class="token keyword">as</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
  <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">'baa'</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">interface</span> <span class="token class-name">Cat</span> <span class="token keyword">extends</span> <span class="token class-name">IAnimal</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'cat'</span><span class="token punctuation">;</span>
  breed<span class="token operator">:</span> <span class="token string">'house'</span> <span class="token operator">|</span> <span class="token string">'wild'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">createCat</span><span class="token punctuation">(</span>breed<span class="token operator">:</span> Cat<span class="token punctuation">[</span><span class="token string">'breed'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">:</span> Cat <span class="token punctuation">{</span>
	<span class="token keyword">return</span> <span class="token punctuation">{</span>
    kind<span class="token operator">:</span> <span class="token string">'cat'</span><span class="token punctuation">;</span>
		breed<span class="token punctuation">,</span>
    <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>breed <span class="token operator">===</span> <span class="token string">'house'</span> <span class="token operator">?</span> <span class="token string">'meow'</span> <span class="token operator">:</span> <span class="token string">'ROAR'</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Human</span> <span class="token keyword">implements</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'human'</span> <span class="token keyword">as</span> <span class="token keyword">const</span><span class="token punctuation">;</span>
	<span class="token function">constructor</span><span class="token punctuation">(</span>
    <span class="token keyword">private</span> greeting<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token function">speak</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>greeting<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name">Animal</span> <span class="token operator">=</span> Sheep <span class="token operator">|</span> Cat <span class="token operator">|</span> Human<span class="token punctuation">;</span></code></pre></div>
<ul>
<li>Well suited for cases were <em>most</em> logic should live near the type definitions, but we need to get access to concrete data outside of the definitions occasionally.</li>
<li>Most complex. Easiest to make a mess of things with.</li>
</ul>
<p>Notes</p>
<ul>
<li>Both patterns work fine with both mutable and functional styles. Don't sleep on using classes just because you're writing functionally.</li>
</ul>
<section data-footnotes class="footnotes"><h2 class="sr-only" id="footnote-label">Footnotes</h2>
<ol>
<li id="user-content-fn-1">
<p>date-fns being slimmer than moment.js is a great example of this <a href="#user-content-fnref-1" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a> <a href="#user-content-fnref-1-2" data-footnote-backref="" aria-label="Back to reference 1-2" class="data-footnote-backref">↩<sup>2</sup></a></p>
</li>
</ol>
</section>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Gatsby vs Next.js: Blog Starters Showdown ⚔️]]></title>
            <link>https://maxburson.com/posts/gatsby-vs-next-js-blog-starters-showdown</link>
            <guid>gatsby-vs-next-js-blog-starters-showdown</guid>
            <pubDate>Sat, 02 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Yesterday I switched from using Gatsby to generate my blog to Next.js. ... Here I'll narrate my experience with both of them, and pit them against each other in a blog-on-blog showdown!]]></description>
            <content:encoded><![CDATA[<p>Yesterday I switched from using Gatsby to generate my blog to Next.js. I had forked <a href="https://github.com/gatsbyjs/gatsby-starter-blog">Gatsby's blog starter</a>, and just forked Next.js's <a href="https://github.com/vercel/next.js/tree/canary/examples/blog-starter-typescript">blog-starter-typescript</a> example. Here I'll narrate my experience with both of them, and pit them against each other in a blog-on-blog showdown!</p>
<h2>TLDR</h2>
<p>Gatsby's more barebones approach to styling and layout match my taste better than Next.js's more filled-in blog template. Gatsby's plugins make it easy to add functionality, and Next.js doesn't have anything comparable. I'd recommend Gatsby to people picking between the two, but I'm not reverting my switch to Next.js any time soon.</p>
<h2>Gatsby</h2>
<p><a href="https://gatsby-starter-blog-demo.netlify.app/">https://gatsby-starter-blog-demo.netlify.app/</a></p>
<p>It was real easy to get started with Gatsby. I felt comfortable deploying the starter mostly it as-is, and the plugins made it real easy to add functionality. I used the <a href="https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs/?=prismjs">gatsby-remark-prismjs</a> plugin to add syntax highlighting to my code blocks.</p>
<p>The starter wasn't 100% to my liking though. To understand everything in the starter you need to know GraphQL, which I don't. I opted to ignore the query under each page and pray they didn't break.</p>
<p>I also really wanted types, which wasn't included out of the box. I was able to add TypeScript types to the JavaScript code easily enough, but much of the logic is in the plugins and GraphQL, so I didn't end up with much type coverage.</p>
<h2>Next.js</h2>
<p><a href="https://next-blog-starter.now.sh/">https://next-blog-starter.now.sh/</a></p>
<p>Next.js's starter blog needed more tweaks before I was ready to use it. The most glaring issue was that the example wouldn't start.</p>
<div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">next
ready - started server on http://localhost:3000
error - ./styles/index.css (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-6-1!./node_modules/next/dist/compiled/postcss-loader/cjs.js??ref--5-oneOf-6-2!./styles/index.css)
Error: PostCSS plugin postcss-nested requires PostCSS 8.</code></pre></div>
<p>The starter looks to be make for a blog with multiple contributors, meaning I had to delete a bunch of stuff, and it is missing and RSS feed. (Although it does have have <a href="https://github.com/vercel/next.js/blob/85bd4a9ccba6def894f01df3fa9ef2f4e2e05d99/examples/blog-starter-typescript/components/meta.tsx#L34">a link to a RSS feed in its head</a> 🤔)</p>
<p>Adding code block syntax highlighting was a real hassle. Maybe I just don't know what to search for? I Eventually I ended up looking through the source code for <a href="https://www.gatsbyjs.com/plugins/gatsby-remark-prismjs/?=prismjs">gatsby-remark-prismjs</a>, and didn't see anything Gatsby specific. In fact, it's not Gatsby-not-specific enough that <a href="https://github.com/maxburs/blog/blob/ae76c5e772325c513db474e93ef78251377a0825/lib/markdownToHtml.ts">I was able to use it with Next.js</a>! The only price I appear to be paying is a new warning on <code class="language-text">yarn install</code>.</p>
<div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">warning " > gatsby-remark-prismjs@3.10.0" has unmet peer dependency "gatsby@^2.0.0".</code></pre></div>
<p>You think they'd take a pull request to remove the Gatsby dependency? 🤔</p>
<p>Out of the box Tailwind CSS is used for styling. Tailwind had been getting a lot of good press recently, so it seems like a good choice? if I didn't already have styles from the Gatsby version of my blog I likely would have kept it around.</p>
<h2>Pros and Cons</h2>
<h3>Gatsby</h3>
<ul>
<li>👍 Out of the box the template was a good fit for my needs</li>
<li>👍 Rich plugin ecosystem makes it easy to enhance your blog with new functionality</li>
<li>👎 Requires learning GraphQL to take full advantage of its capabilities</li>
<li>👎 No out-of-the-box TypeScript option</li>
<li>🤷‍♂️ <a href="https://github.com/kyleamathews/typography.js/">Typography.js</a> is used for styles out of the box</li>
</ul>
<h3>Next.js</h3>
<ul>
<li>👍 Both JavaScript and TypeScript variations</li>
<li>👎 Doesn't have anything to match Gatsby's rich plugin ecosystem</li>
<li>👍 <a href="https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation">getStaticProps</a> makes it easy to use existing Node knowledge to add data non-javascript stuff built time</li>
<li>👍 <a href="https://www.tailwindapp.com/">Tailwind CSS</a> is used for styles out of the box</li>
<li>👎 I got a build error when starting the example for the first time</li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RTFM More]]></title>
            <link>https://maxburson.com/posts/ftfm-more</link>
            <guid>ftfm-more</guid>
            <pubDate>Sat, 07 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Read Stack Overflow less, and your language or library’s docs more]]></description>
            <content:encoded><![CDATA[<p>TLDR: Read Stack Overflow less, and your language or library’s docs more.</p>
<h2>Reasons to RTFM</h2>
<ul>
<li>Less likely to be outdated</li>
<li>Less likely to be incorrect</li>
<li>Provides more context</li>
<li>Documentation gets easier to read the more time is spent with it</li>
<li>You’re learning while you’re searching</li>
</ul>
<p>It's easy to get in a habit of immediately looking up ready-made solutions; never slowing down to more deeply understand our problems, and our tools. Not only can ready-made solutions create shallow knowledge, total time spend can be longer if few people have had the same problem, or if we're not knowledgeable enough to know what to look for.</p>
<p>Stack Overflow is still great, but it’s not the first resource I would reach for.</p>
<h2>More great reading material</h2>
<ul>
<li>Source code: Will make you a better developer</li>
<li>Patch notes: May have better information on the latest features than the docs</li>
<li>Repo issues: The best way to find solutions to project/library specific problems</li>
</ul>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Making the switch => object Pattern Work in TypeScript]]></title>
            <link>https://maxburson.com/posts/switch-object-pattern-with-typescript</link>
            <guid>switch-object-pattern-with-typescript</guid>
            <pubDate>Tue, 08 Oct 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[Where I come to terms with TypeScript not being perfect]]></description>
            <content:encoded><![CDATA[<h2>The switch => object pattern is great</h2>
<p>I'm a huge fan of the JavaScript pattern where one replaces a switch:</p>
<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">handle</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">switch</span> <span class="token punctuation">(</span>event<span class="token punctuation">.</span>kind<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">case</span> <span class="token string">'goblins_are_coming'</span><span class="token operator">:</span>
      <span class="token function">repelMonsters</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">case</span> <span class="token string">'family_is_coming'</span><span class="token operator">:</span>
      <span class="token function">stockFridge</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<p>with an object:</p>
<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token keyword">const</span> eventHandlers <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">goblins_are_coming</span><span class="token operator">:</span> repelMonsters<span class="token punctuation">,</span>
  <span class="token literal-property property">family_is_coming</span><span class="token operator">:</span> stockFridge<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>The second method really shines when we don't want to specify the kinds of events we are handling in the same file.</p>
<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token keyword">import</span> familyEventHandlers <span class="token keyword">from</span> <span class="token string">'./familyEventHandlers'</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">const</span> eventHandlers <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">goblins_are_coming</span><span class="token operator">:</span> repelMonsters<span class="token punctuation">,</span>
  <span class="token operator">...</span>familyEventHandlers<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h2>The pattern doesn't work in TypeScript very well</h2>
<p>Assume this is written above the rest of the TypeScript examples:</p>
<div class="gatsby-highlight" data-language="ts"><pre class="language-ts"><code class="language-ts"><span class="token keyword">interface</span> <span class="token class-name">GoblinEvent</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'goblins_are_coming'</span><span class="token punctuation">;</span>
  smell<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">interface</span> <span class="token class-name">FamilyEvent</span> <span class="token punctuation">{</span>
  kind<span class="token operator">:</span> <span class="token string">'family_is_coming'</span><span class="token punctuation">;</span>
  notice<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">OurEvent</span> <span class="token operator">=</span> GoblinEvent <span class="token operator">|</span> FamilyEvent<span class="token punctuation">;</span>

<span class="token keyword">declare</span> <span class="token keyword">const</span> <span class="token function-variable function">repelMonsters</span><span class="token operator">:</span> <span class="token punctuation">(</span>event<span class="token operator">:</span> GoblinEvent<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span><span class="token punctuation">;</span>
<span class="token keyword">declare</span> <span class="token keyword">const</span> <span class="token function-variable function">stockFridge</span><span class="token operator">:</span> <span class="token punctuation">(</span>event<span class="token operator">:</span> FamilyEvent<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span><span class="token punctuation">;</span></code></pre></div>
<p>TypeScript plays fine with the first JavaScript example.</p>
<div class="gatsby-highlight" data-language="ts"><pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token function">handle</span><span class="token punctuation">(</span>event<span class="token operator">:</span> FamilyEvent <span class="token operator">|</span> GoblinEvent<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">switch</span> <span class="token punctuation">(</span>event<span class="token punctuation">.</span>kind<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">case</span> <span class="token string">'goblins_are_coming'</span><span class="token operator">:</span>
      <span class="token function">repelMonsters</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">case</span> <span class="token string">'family_is_coming'</span><span class="token operator">:</span>
      <span class="token function">stockFridge</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<p>But can't make sense of the second one.</p>
<div class="gatsby-highlight" data-language="ts"><pre class="language-ts"><code class="language-ts"><span class="token keyword">const</span> eventHandlers <span class="token operator">=</span> <span class="token punctuation">{</span>
  goblins_are_coming<span class="token operator">:</span> repelMonsters<span class="token punctuation">,</span>
  family_is_coming<span class="token operator">:</span> stockFridge<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">declare</span> <span class="token keyword">const</span> e<span class="token operator">:</span> OurEvent<span class="token punctuation">;</span>

eventHandlers<span class="token punctuation">[</span>e<span class="token punctuation">.</span>kind<span class="token punctuation">]</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>This ☝ produces this 👇 error message.</p>
<div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">Argument of type 'OurEvent' is not assignable to parameter of type 'GoblinEvent &amp; FamilyEvent'.
  Type 'GoblinEvent' is not assignable to type 'GoblinEvent &amp; FamilyEvent'.
    Property 'notice' is missing in type 'GoblinEvent' but required in type 'FamilyEvent'.ts(2345)
</code></pre></div>
<h2>Here's the great (terrible?) hack to make it work</h2>
<div class="gatsby-highlight" data-language="ts"><pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">handle</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">P</span> <span class="token keyword">extends</span> OurEvent<span class="token punctuation">,</span> <span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token constant">P</span><span class="token punctuation">[</span><span class="token string">'kind'</span><span class="token punctuation">]</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>
  payload<span class="token operator">:</span> <span class="token constant">P</span><span class="token punctuation">,</span>
  stuff<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token punctuation">[</span><span class="token constant">K</span> <span class="token keyword">in</span> <span class="token constant">T</span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token punctuation">(</span>arg0<span class="token operator">:</span> <span class="token constant">P</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  stuff<span class="token punctuation">[</span>payload<span class="token punctuation">.</span>kind<span class="token punctuation">]</span><span class="token punctuation">(</span>payload<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">handle</span><span class="token punctuation">(</span>e<span class="token punctuation">,</span> eventHandlers<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>No type errors! 🎊</p>
<p>... but with a catch.</p>
<p>This works because the interface is still generic when accessed. To keep this compiling, the object must preserve it's mapped typings as long as the event is generic.</p>
<p>That is to say, the following produces a type error:</p>
<div class="gatsby-highlight" data-language="ts"><pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">handleWrapper</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">P</span> <span class="token keyword">extends</span> OurEvent<span class="token operator">></span></span></span><span class="token punctuation">(</span>payload<span class="token operator">:</span> <span class="token constant">P</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">handle</span><span class="token punctuation">(</span>payload<span class="token punctuation">,</span> eventHandlers<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>TLDR:</h2>
<p>Check this out:</p>
<div class="gatsby-highlight" data-language="ts"><pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">handle</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">P</span> <span class="token keyword">extends</span> OurEvent<span class="token punctuation">,</span> <span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token constant">P</span><span class="token punctuation">[</span><span class="token string">'kind'</span><span class="token punctuation">]</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>
  payload<span class="token operator">:</span> <span class="token constant">P</span><span class="token punctuation">,</span>
  stuff<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token punctuation">[</span><span class="token constant">K</span> <span class="token keyword">in</span> <span class="token constant">T</span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token punctuation">(</span>arg0<span class="token operator">:</span> <span class="token constant">P</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  stuff<span class="token punctuation">[</span>payload<span class="token punctuation">.</span>kind<span class="token punctuation">]</span><span class="token punctuation">(</span>payload<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cross Component Promises]]></title>
            <link>https://maxburson.com/posts/cross-component-promises</link>
            <guid>cross-component-promises</guid>
            <pubDate>Sat, 31 Mar 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[Async cross component communication can be easily (ish) achieved without breaking component data flow rules]]></description>
            <content:encoded><![CDATA[<p>Promises and async/await are awesome and should be used more often in the front end. I rarely see them getting used for anything besides ajax and that's a shame. I'll provide a short (contrived) example of a problem that can be simplified by using promises.</p>
<div class="gatsby-highlight" data-language="jsx"><pre class="language-jsx"><code class="language-jsx"><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">seriousBusinessLogic</span><span class="token punctuation">(</span><span class="token parameter">pickAColor</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> favorite <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">pickAColor</span><span class="token punctuation">(</span><span class="token string">'Pick your favorite'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
    <span class="token string">'steelblue'</span><span class="token punctuation">,</span>
    <span class="token string">'darkgoldenrod'</span><span class="token punctuation">,</span>
    <span class="token string">'olivedrab'</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> leastFavorite <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">pickAColor</span><span class="token punctuation">(</span>
    <span class="token string">'Please pick your least favorite of these colors'</span><span class="token punctuation">,</span>
    <span class="token punctuation">[</span><span class="token string">'aquamarine'</span><span class="token punctuation">,</span> <span class="token string">'darksalmon'</span><span class="token punctuation">,</span> <span class="token string">'rebeccapurple'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token function">alert</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">You picked </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>favorite<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, and </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>leastFavorite<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<style>
  .codepen {
    max-width: 768px;
    width: 768px;
    min-width: 0px;
    margin-bottom: 1.5em;
    display: block;
  }
</style>
<iframe class="codepen" height="265"  scrolling="no" title="Promises are Great blog post example" src="https://codepen.io/genuine_smiles/embed/rbNOWO?height=265&theme-id=dark&default-tab=result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
  See the Pen <a href='https://codepen.io/genuine_smiles/pen/rbNOWO'>Promises are Great blog post example</a> by Maxwell Burson
  (<a href='https://codepen.io/genuine_smiles'>@genuine_smiles</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>
<p>The most immediate benefit is not splitting the above code into multiple parts. We can keep the dispatching logic and the resulting effects in the same block as they should be; as well as chaining multiple requests together easily and naturally.</p>
<p>Promises also let us keep this business logic hidden inside of a component when we need to call into outside components to get our answer. Suppose this question could be best answered using the ui of an already mounted component, and this was a regular callback that didn't return a promise. The component that needs the question answered would need to set a flag inside of itself and then wait for the answer to come down as a prop. <em>But</em>, other components that ask the same question may also receive the prop, and because the answer is stateful we would need to call another callback to clear the answer prop.</p>
<p>This could all be avoided by moving all this logic and state into a higher component, but, that defeats our original goal of isolation. On the other hand, if the question can be answered by a modal inside of the current class we should likely just do that.</p>
<p>I've used this trick successfully in these situations:</p>
<ul>
<li>The question was being asked a <em>lot</em>. We could just render a modal in the current context whenever we need to and be done with it; but creating a service to answer a frequent question saves a large amount of time.</li>
<li>The question could only be answered by other components. Other components need to be interacted with by the user to get the question answered or other components have state inside of them that we don't want to pass around.</li>
</ul>
]]></content:encoded>
        </item>
    </channel>
</rss>