<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/rss.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://vladimirzdrazil.com" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Vladimír Zdražil Posts</title>
    <link>https://vladimirzdrazil.com</link>
    <atom:link href="https://vladimirzdrazil.com/index.xml" rel="self" type="application/rss+xml"/>
    <description>Recent posts on vladimirzdrazil.com</description>
    <lastBuildDate>Thu, 30 Nov 2023 08:07:39 +0000</lastBuildDate>
    <language>en</language>
      <item>
        <title>You don’t need that complexity: A fresh look at your project</title>
        <link>https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/</link>
        <description>&lt;p&gt;When you’re working on a project for a long time, you might start to believe that a lot of complexity is needed when it really isn’t. Sometimes, you might even stop noticing it. How can you stop assuming things have to be complex and start finding ways to make your work easier?&lt;/p&gt;
&lt;h2 id=&quot;definitions&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#definitions&quot;&gt;&lt;span&gt;Definitions&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, here are definitions of some terms I’ll be using. Feel free to &lt;a href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#looking-at-complexity-in-a-new-way&quot;&gt;skip them&lt;/a&gt; if you’re already familiar with them.&lt;/p&gt;
&lt;p&gt;The definitions of essence and accidental parts are paraphrased from &lt;cite&gt;&lt;a href=&quot;https://web.archive.org/web/20160910002130/http://worrydream.com/refs/Brooks-NoSilverBullet.pdf&quot;&gt;No Silver Bullet—Essence and Accident in Software Engineering&lt;/a&gt;&lt;/cite&gt; by Frederick P. Brooks, Jr. (1987).&lt;/p&gt;
&lt;h3 id=&quot;software-entity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#software-entity&quot;&gt;&lt;span&gt;Software entity&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The term &lt;q&gt;software entity&lt;/q&gt; refers to any software product or artifact. This could be a full application, a software library, a module, or even a single function or method, depending on the context. It’s an entity in the sense that it exists as a distinct, identifiable object.&lt;/p&gt;
&lt;h3 id=&quot;essence-of-a-software-entity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#essence-of-a-software-entity&quot;&gt;&lt;span&gt;Essence of a software entity&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The essence of a software entity is an abstract construct of interlocking concepts: data sets, relationships among data items, algorithms, and invocations of functions.&lt;/p&gt;
&lt;p&gt;The essence is abstract, in that the construct is the same under many different representations. It is nonetheless highly precise and richly detailed.&lt;/p&gt;
&lt;p&gt;It’s the essence because it’s inherent to the nature of the software entity. It can’t be eliminated or simplified by any technology or technique.&lt;/p&gt;
&lt;h3 id=&quot;accidental-aspect-of-a-software-entity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#accidental-aspect-of-a-software-entity&quot;&gt;&lt;span&gt;Accidental aspect of a software entity&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Accidental aspect of a software entity is the specific representation of the essence and the mapping of it onto machine languages within space and speed constraints. Where essence is an abstract construct, the accidental aspect is a concrete representation.&lt;/p&gt;
&lt;p&gt;It’s accidental because it’s not inherent to the nature of the software entity. You can eliminate or simplify it by different technologies and techniques. You can come up with a representation that is less complex, but you can’t make the essence less complex.&lt;/p&gt;
&lt;h3 id=&quot;essential-complexity-and-difficulties&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#essential-complexity-and-difficulties&quot;&gt;&lt;span&gt;Essential complexity and difficulties&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Essential complexity and difficulties that are inherent in the nature of the software.&lt;/p&gt;
&lt;h3 id=&quot;accidental-complexity-and-difficulties&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#accidental-complexity-and-difficulties&quot;&gt;&lt;span&gt;Accidental complexity and difficulties&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Difficulties and complexity that accompany software production but that are not inherent.&lt;/p&gt;
&lt;p&gt;Fred Brooks (1987) believes that the hard part of building software is the specification, design, and testing of the essence, not the labor of representing it and testing the fidelity of the representation.&lt;/p&gt;
&lt;h2 id=&quot;looking-at-complexity-in-a-new-way&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#looking-at-complexity-in-a-new-way&quot;&gt;&lt;span&gt;Looking at complexity in a new way&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Reading through this topic made me think about how, sometimes, when we work on a project for a while, we start to believe that many things are essential complexity when they actually aren’t.&lt;/p&gt;
&lt;p&gt;What if we periodically looked at our projects like they’re brand new? Consider if you could start your project over. What would you do differently? What choices would you make? What would you not do?&lt;/p&gt;
&lt;p&gt;Sure, some things are accidental complexity, but you can’t practically change them. Be it for technical, political or other reasons. For example, it’s not very realistic that you’ll avoid using CSS as a frontend developer. But even then, when was the last time you checked? Maybe it’s now possible to actually do something about it?&lt;/p&gt;
&lt;p&gt;Or perhaps you’re using a tool because everyone else is, but it’s making your work harder. Everyone suggests using &lt;a href=&quot;https://redux.js.org/&quot;&gt;Redux&lt;/a&gt;? You don’t necessarily have to. Everybody advocates strict &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt; rules? That’s not a mandate either. JavaScript is making things complicated? Maybe you could use &lt;a href=&quot;https://clojurescript.org/&quot;&gt;ClojureScript&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;No supreme deity of programming will penalize you for venturing off the beaten path. Carefully weigh the pros and cons, understand why the established tools are there, and then make your own decision.&lt;/p&gt;
&lt;p&gt;Let’s not be caught in the illusion that certain complexities are unavoidable when they are indeed optional. Take a step back sometimes. Look at your work as if it’s new. You might find a way to make things simpler.&lt;/p&gt;
&lt;h2 id=&quot;references&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#references&quot;&gt;&lt;span&gt;References&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Brooks, F. P. (1995a). Chapter 16. No Silver Bullet—Essence and Accident in Software Engineering. In &lt;a href=&quot;https://www.worldcat.org/title/mythical-man-month-essays-on-software-engineering/oclc/31166617&quot;&gt;&lt;em&gt;The mythical man-month: Essays on software engineering&lt;/em&gt; (Anniversary edition)&lt;/a&gt;. Addison-Wesley Publishing Company.&lt;/li&gt;
&lt;li&gt;Brooks, F. P. (1995b). Chapter 17. “No Silver Bullet” Refined. In &lt;a href=&quot;https://www.worldcat.org/title/mythical-man-month-essays-on-software-engineering/oclc/31166617&quot;&gt;&lt;em&gt;The mythical man-month: Essays on software engineering&lt;/em&gt; (Anniversary edition)&lt;/a&gt;. Addison-Wesley Publishing Company.&lt;/li&gt;
&lt;li&gt;Brooks, F. P. (1986). &lt;a href=&quot;https://web.archive.org/web/20160910002130/http://worrydream.com/refs/Brooks-NoSilverBullet.pdf&quot;&gt;No Silver bullet—Essence and accidents of software engineering&lt;/a&gt;. &lt;em&gt;IEEE Computer&lt;/em&gt;, &lt;em&gt;20&lt;/em&gt;(4), 10–19.&lt;/li&gt;
&lt;li&gt;Moseley, B., &amp;amp; Marks, P. (2006). &lt;a href=&quot;https://curtclifton.net/papers/MoseleyMarks06a.pdf&quot;&gt;Out of the tar pit&lt;/a&gt;. &lt;em&gt;Software Practice Advancement (SPA)&lt;/em&gt;, &lt;em&gt;2006&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;related&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/#related&quot;&gt;&lt;span&gt;Related&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/til/programming/no-silver-bullet&quot;&gt;No silver bullet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
          <category>programming</category>
        <pubDate>Fri, 02 Jun 2023 14:21:11 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/you-dont-need-that-complexity/</guid>
      </item>
      <item>
        <title>Option A vs A | null</title>
        <link>https://vladimirzdrazil.com/posts/option-a-a-null/</link>
        <description>&lt;h2 id=&quot;tldr&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#tldr&quot;&gt;&lt;span&gt;TLDR&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Two common ways to represent absence of a value in TypeScript are &lt;code&gt;A | null&lt;/code&gt; and &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;. I suggest you use &lt;code&gt;A | null&lt;/code&gt; by default and switch to &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; only when needed. Such as when you want to use &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt; utils.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#introduction&quot;&gt;&lt;span&gt;Introduction&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When representing the absence of a value in TypeScript, you can use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;union type&lt;/a&gt; &lt;code&gt;A | null&lt;/code&gt;, or a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union type&lt;/a&gt; &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;. In this post, we’ll discuss the differences between these two approaches and when to use each. Keep in mind that this post focuses on TypeScript and other languages may have different considerations.&lt;/p&gt;
&lt;h2 id=&quot;untagged-union-a-null&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#untagged-union-a-null&quot;&gt;&lt;span&gt;Untagged union: &lt;code&gt;A | null&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An &lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;untagged union&lt;/a&gt; is a type that can hold values of different types, but it &lt;strong&gt;doesn’t&lt;/strong&gt; provide any information about which type is actually present. In TypeScript, you often use the &lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;untagged union&lt;/a&gt; &lt;code&gt;A | null&lt;/code&gt; to represent a value that may or may not be present.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/** This example demonstrates the use of an untagged union. */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;charAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Output: &quot;h&quot;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Output: null&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;tagged-union-option-a&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#tagged-union-option-a&quot;&gt;&lt;span&gt;Tagged union: &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt; is a type that can contain one of several different types, but &lt;strong&gt;it does&lt;/strong&gt; provide additional information to differentiate between them. It is a subset of the more general concept of a union.&lt;/p&gt;
&lt;p&gt;In TypeScript, &lt;a href=&quot;https://en.wikipedia.org/wiki/Option_type&quot;&gt;&lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/a&gt; is an example of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt; that represents a value that may or may not be present. You might also know &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt; under names such as variant, variant record, choice type, discriminated union, disjoint union, sum type or coproduct.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; option &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fp-ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Option &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fp-ts/Option&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/** This example demonstrates the use of a tagged union. */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;charAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Output: { _tag: &#39;Some&#39;, value: &#39;h&#39; }&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFirstLetter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Output: { _tag: &#39;None&#39; }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-about-maybe-a&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#what-about-maybe-a&quot;&gt;&lt;span&gt;What about &lt;code&gt;Maybe&amp;lt;A&amp;gt;&lt;/code&gt;?&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Maybe&lt;/code&gt; are the same concept, meaning that when I’m referring to &lt;a href=&quot;https://en.wikipedia.org/wiki/Option_type&quot;&gt;&lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/a&gt;, you can consider it synonymous with &lt;code&gt;Maybe&amp;lt;A&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-about-a-undefined&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#what-about-a-undefined&quot;&gt;&lt;span&gt;What about &lt;code&gt;A | undefined&lt;/code&gt;?&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s not worth treating &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; as different types. When I say &lt;code&gt;null&lt;/code&gt;, you can pretend I mean &lt;code&gt;null | undefined&lt;/code&gt;. Ideally, TypeScript and JavaScript would have only &lt;code&gt;undefined&lt;/code&gt;. &lt;a href=&quot;https://www.youtube.com/watch?v=PSGEjv3Tqo0&amp;amp;t=561s&quot;&gt;Check out this video for more information, 9:21&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;things-to-remember&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#things-to-remember&quot;&gt;&lt;span&gt;Things to remember&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;A | null&lt;/code&gt; is a union type. It’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;untagged&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; is a union type. It’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;comparison-simplicity-and-familiarity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison-simplicity-and-familiarity&quot;&gt;&lt;span&gt;Comparison: Simplicity and familiarity&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Winner: &lt;code&gt;A | null&lt;/code&gt; ✅&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;Untagged union&lt;/a&gt; &lt;code&gt;A | null&lt;/code&gt; has an advantage of being simple and familiar to many programmers. Most programmers are already familiar with &lt;code&gt;null&lt;/code&gt; and imperative code like &lt;code&gt;if (foo != null)&lt;/code&gt; to check if a value is present or not.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; type is not as familiar as &lt;code&gt;A | null&lt;/code&gt;. This can make the code more challenging to read and understand, particularly for those who are not well-versed in functional programming concepts.&lt;/p&gt;
&lt;p&gt;However, not everything needs to be designed for beginners, as highlighted in &lt;a href=&quot;https://youtu.be/QCwqnjxqfmY?t=1914&quot;&gt;this talk by Rich Hickey, 31:54&lt;/a&gt;. While using &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; may require some additional learnings, the benefits might be worth it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We should not sell humanity short by trying to solve the problem of beginners in our stuff. We need to make things for people to use, and we need to teach people and trust people to be able to learn how to do that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://youtu.be/QCwqnjxqfmY?t=2063&quot;&gt;Design, Composition, and Performance, 34:23&lt;/a&gt;&lt;/cite&gt; by &lt;a href=&quot;https://en.wikipedia.org/wiki/Rich_Hickey&quot;&gt;Rich Hickey&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;comparison-interop-with-other-platforms-languages-and-libraries&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison-interop-with-other-platforms-languages-and-libraries&quot;&gt;&lt;span&gt;Comparison: Interop with other platforms, languages and libraries&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Winner: &lt;code&gt;A | null&lt;/code&gt; ✅&lt;/p&gt;
&lt;p&gt;&lt;code&gt;A | null&lt;/code&gt; simplifies interop with other platforms and languages that use a similar representation, such as a JSON API that uses &lt;code&gt;null&lt;/code&gt; to represent the absence of a value. This can be an advantage in terms of seamless integration between different parts of a codebase or across different systems.&lt;/p&gt;
&lt;p&gt;On the other hand, if you use &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; and need to interact with a system that uses &lt;code&gt;null&lt;/code&gt; to represent absence of a value, you’ll need to convert between &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt;. While this is not necessarily a bad or a hard thing to do, it can add additional complexity and make the code harder to read and maintain.&lt;/p&gt;
&lt;h2 id=&quot;comparison-native-language-support&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison-native-language-support&quot;&gt;&lt;span&gt;Comparison: Native language support&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Winner: &lt;code&gt;A | null&lt;/code&gt; ✅&lt;/p&gt;
&lt;p&gt;Another advantage of &lt;code&gt;A | null&lt;/code&gt; is that it allows you to use already existing syntax and usability features of Typescript designed for handling absent values.&lt;/p&gt;
&lt;p&gt;For example, in TypeScript, there is a null-aware operator &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining&quot;&gt;&lt;code&gt;(?.)&lt;/code&gt;&lt;/a&gt; that simplifies checking for null values.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Demonstrates optional chaining&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  address&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    street&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    city&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;John Smith&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Output: undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In TypeScript, &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; does not have any special language support, which can make the code more verbose and harder to read.&lt;/p&gt;
&lt;h2 id=&quot;comparison-fp-ts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison-fp-ts&quot;&gt;&lt;span&gt;Comparison: &lt;code&gt;fp-ts&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Winner: &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; ✅&lt;/p&gt;
&lt;p&gt;TypeScript needs a utility library, and the best one available is &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt;. It provides patterns and reliable abstractions from typed functional languages, including &lt;a href=&quot;https://gcanti.github.io/fp-ts/modules/Option.ts.html&quot;&gt;&lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt; can interop with &lt;code&gt;A | null&lt;/code&gt;, &lt;a href=&quot;https://gcanti.github.io/fp-ts/modules/Option.ts.html&quot;&gt;&lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/a&gt; is the preferred abstraction for absence of a value and your code will be less verbose if you use &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;comparison-support-of-functional-patterns-aka-nesting-of-types&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison-support-of-functional-patterns-aka-nesting-of-types&quot;&gt;&lt;span&gt;Comparison: Support of functional patterns aka nesting of types&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Winner: &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; ✅&lt;/p&gt;
&lt;p&gt;An advantage of using a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt; like &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; is that it allows nesting of types. &lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;Untagged union&lt;/a&gt; &lt;code&gt;A | null&lt;/code&gt; can’t do that.&lt;/p&gt;
&lt;p&gt;Support for nested types is important for many functional patterns because it allows computations to be composed in a predictable and composable way.&lt;/p&gt;
&lt;p&gt;Without support for nested types, it can be difficult or impossible to implement some functional patterns, or they may require workarounds that make the code more complex and error-prone.&lt;/p&gt;
&lt;h3 id=&quot;example-1&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#example-1&quot;&gt;&lt;span&gt;Example 1&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you write code that works with any type &lt;code&gt;A&lt;/code&gt;, without knowing its specific context, you will need a support for nested types, because in that case you may end up with something akin to &lt;code&gt;Option&amp;lt;Option&amp;lt;A&amp;gt;&amp;gt;&lt;/code&gt; and you most probably should not collapse that type to keep the behavior consistent.&lt;/p&gt;
&lt;p&gt;You can’t do that with &lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;untagged union&lt;/a&gt; &lt;code&gt;A | null&lt;/code&gt;. In many concrete contexts, you could probably simplify &lt;code&gt;Option&amp;lt;Option&amp;lt;A&amp;gt;&amp;gt;&lt;/code&gt; to just &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;, but not in the generic one.&lt;/p&gt;
&lt;p&gt;As a concrete example, consider the type of custom &lt;code&gt;tryCatch&lt;/code&gt;:&lt;/p&gt;
&lt;h4 id=&quot;implemented-with-option-a&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#implemented-with-option-a&quot;&gt;&lt;span&gt;Implemented with &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Option &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fp-ts/Option&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; option &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fp-ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;tryCatch&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tryCatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; num&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tryCatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;implemented-with-a-null&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#implemented-with-a-null&quot;&gt;&lt;span&gt;Implemented with &lt;code&gt;A | null&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;tryCatch&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tryCatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; num&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tryCatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;comparison&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison&quot;&gt;&lt;span&gt;Comparison&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Notice the types you receive after calling &lt;code&gt;tryCatch&lt;/code&gt;. When using &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;, everything is consistent. We treat &lt;code&gt;A&lt;/code&gt; as untouchable, simply putting it inside an &lt;code&gt;Option&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, with &lt;code&gt;A | null&lt;/code&gt;, if you give us an &lt;code&gt;A&lt;/code&gt; that happens to be &lt;code&gt;null&lt;/code&gt;, we just give you &lt;code&gt;null&lt;/code&gt; back instead of wrapping it in an &lt;code&gt;Option&lt;/code&gt;. This means that &lt;code&gt;A&lt;/code&gt; is no longer untouchable, and if &lt;code&gt;A&lt;/code&gt; happens to be &lt;code&gt;null&lt;/code&gt;, the type is collapsed.&lt;/p&gt;
&lt;p&gt;As a caller, you won’t be able to tell if the function failed or if the returned &lt;code&gt;null&lt;/code&gt; is a result of absence of a value.&lt;/p&gt;
&lt;h3 id=&quot;example-2&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#example-2&quot;&gt;&lt;span&gt;Example 2&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt;, the &lt;a href=&quot;https://rlee.dev/practical-guide-to-fp-ts-part-5#traversals&quot;&gt;traverse method&lt;/a&gt; is a commonly used function with a predictable behavior that users expect. For example, if you know how &lt;a href=&quot;https://gcanti.github.io/fp-ts/modules/Array.ts.html#traverse&quot;&gt;array.traverse&lt;/a&gt; works, you can likely predict the behavior of &lt;a href=&quot;https://gcanti.github.io/fp-ts/modules/Option.ts.html#traverse&quot;&gt;option.traverse&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, if you’d implement &lt;a href=&quot;https://gcanti.github.io/fp-ts/modules/Option.ts.html#traverse&quot;&gt;option.traverse&lt;/a&gt; with &lt;code&gt;A | null&lt;/code&gt;, it would behave differently than other &lt;code&gt;traverse&lt;/code&gt; functions, making it harder to understand.&lt;/p&gt;
&lt;p&gt;To prevent confusion, it’s better to use &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; instead of &lt;code&gt;A | null&lt;/code&gt;. By doing so, you ensure that everything behaves consistently.&lt;/p&gt;
&lt;h3 id=&quot;example-3&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#example-3&quot;&gt;&lt;span&gt;Example 3&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s say you’re trying to retrieve a user address by their ID, but they may or may not have an associated address.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  address&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Users&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Record&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this situation, you can encounter three possible outcomes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is no user with the specified ID.&lt;/li&gt;
&lt;li&gt;There is a user with the specified ID, but they do not have an address.&lt;/li&gt;
&lt;li&gt;There is a user with the specified ID, and they have an address.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you use the &lt;code&gt;A | null&lt;/code&gt; representation to handle these outcomes, you would get the following results:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;address&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As a result, you lose information about whether or not you found a user. However, if you use the &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; representation instead, you get more detailed results:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;None&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Some(None)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Some(Some(address))&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This representation allows you to retain more information about whether or not you found a user, and whether or not they have an associated address.&lt;/p&gt;
&lt;h2 id=&quot;comparison-flexibility-and-backwards-compatibility&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison-flexibility-and-backwards-compatibility&quot;&gt;&lt;span&gt;Comparison: Flexibility and backwards compatibility&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Winner: &lt;code&gt;A | null&lt;/code&gt; ✅&lt;/p&gt;
&lt;p&gt;Inspired by &lt;a href=&quot;https://youtu.be/YR5WdGrpoug?t=463&quot;&gt;Rick Hickey‘s presentation &lt;q&gt;Maybe not&lt;/q&gt;, 7:43&lt;/a&gt;, the following scenario explores the different outcomes of representing absent values.&lt;/p&gt;
&lt;p&gt;Consider this scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You create a function with the interface &lt;code&gt;(text: string) =&amp;gt; string&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It starts to get used in multiple places.&lt;/li&gt;
&lt;li&gt;As it evolves you decide that this function should also handle absence of a value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now one of 2 things will happen, depending on what you picked for representation of absent value.&lt;/p&gt;
&lt;h3 id=&quot;1-string-null&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#1-string-null&quot;&gt;&lt;span&gt;1. &lt;code&gt;string | null&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You change the interface to &lt;code&gt;(text: string | null) =&amp;gt; string&lt;/code&gt;. And you’re done. This change doesn’t break any callers.&lt;/p&gt;
&lt;h3 id=&quot;2-option-string&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#2-option-string&quot;&gt;&lt;span&gt;2. &lt;code&gt;Option&amp;lt;string&amp;gt;&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You change the interface to &lt;code&gt;(text: Option&amp;lt;string&amp;gt;) =&amp;gt; string&lt;/code&gt;. Well, this change breaks all callers.&lt;/p&gt;
&lt;p&gt;Ok, let’s fix that and change it to &lt;code&gt;(text: string | Option&amp;lt;string&amp;gt;) =&amp;gt; string&lt;/code&gt;. This option is also problematic because it’s a poor interface, and it’s clear that we created it only for backwards compatibility.&lt;/p&gt;
&lt;p&gt;The clean approach is to use &lt;code&gt;(text: Option&amp;lt;string&amp;gt;) =&amp;gt; string&lt;/code&gt; and rewrite all the callers accordingly.&lt;/p&gt;
&lt;h3 id=&quot;result&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#result&quot;&gt;&lt;span&gt;Result&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As you can see, using &lt;code&gt;string | null&lt;/code&gt; as the representation of absent values provides more flexibility in this regard. This applies also to a more generic &lt;code&gt;A | null&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;comparison-performance&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#comparison-performance&quot;&gt;&lt;span&gt;Comparison: Performance&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While it’s also possible to compare the performance of &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; and &lt;code&gt;A | null&lt;/code&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union#Advantages_and_disadvantages&quot;&gt;see details&lt;/a&gt;), this article focuses only on the usability of the two approaches.&lt;/p&gt;
&lt;h2 id=&quot;when-to-use-a-null-vs-option-a&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#when-to-use-a-null-vs-option-a&quot;&gt;&lt;span&gt;When to use &lt;code&gt;A | null&lt;/code&gt; vs &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we’ve looked at the advantages and disadvantages of both &lt;code&gt;A | null&lt;/code&gt; and &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;, let’s explore when to use each one. Use &lt;code&gt;A | null&lt;/code&gt; when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You have a simple use case where the absence of a value is not nested.&lt;/li&gt;
&lt;li&gt;You’re working with code that’s not heavily influenced by functional programming patterns.&lt;/li&gt;
&lt;li&gt;You’re interacting with other platforms and languages that use &lt;code&gt;null&lt;/code&gt; to represent the absence of a value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need to represent nested absences.&lt;/li&gt;
&lt;li&gt;You’re working in a functional programming context.&lt;/li&gt;
&lt;li&gt;You want to use the &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt; utilities which use &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; as an abstraction for the absence of a value.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;no-really-which-one-is-better&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#no-really-which-one-is-better&quot;&gt;&lt;span&gt;No really, which one is better?&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My recommendation is to default to using &lt;code&gt;A | null&lt;/code&gt; and only switch to &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; when necessary, limiting its use to a closely related code. It’s going to result in a simpler and more familiar codebase and makes it easier to interact with modules that don’t use &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While using &lt;code&gt;A | null&lt;/code&gt; means you lose the ability to nest nullability, from my experience, nested absent values are not very common. Therefore, this limitation is not as significant as you might think.&lt;/p&gt;
&lt;p&gt;Moreover, even in cases where nesting is required, using nested optionals can make the interface harder to use and understand and you might consider refactoring it.&lt;/p&gt;
&lt;p&gt;And if refactoring is not possible, it’s very simple to convert from &lt;code&gt;A | null&lt;/code&gt; to &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; with &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt; utils &lt;a href=&quot;https://gcanti.github.io/fp-ts/modules/Option.ts.html#fromnullable&quot;&gt;&lt;code&gt;fromNullable&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://gcanti.github.io/fp-ts/modules/Option.ts.html#tonullable&quot;&gt;&lt;code&gt;toNullable&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; option &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fp-ts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Option &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fp-ts/Option&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pipe &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;fp-ts/function&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Converting nullable to Option&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hello &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nullableValue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hello&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; optionValue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromNullable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nullableValue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Converting Option to nullable&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; optionValue2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nullableValue2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toNullable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;optionValue2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// More practical example, with the use in `pipe`&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Option&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  nullableValue&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fromNullable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result2&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  optionValue2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  option&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;toNullable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#conclusion&quot;&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In conclusion, TypeScript offers two popular options for representing the absence of a value: using an &lt;a href=&quot;https://en.wikipedia.org/wiki/Union_type&quot;&gt;untagged union&lt;/a&gt; type &lt;code&gt;A | null&lt;/code&gt; or a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt; type &lt;a href=&quot;https://en.wikipedia.org/wiki/Option_type&quot;&gt;&lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While the former is simpler and more familiar to many programmers, the latter is more consistent and better supports many functional patterns.&lt;/p&gt;
&lt;p&gt;In my opinion, it’s best to default to using &lt;code&gt;A | null&lt;/code&gt; and only switch to &lt;code&gt;Option&amp;lt;A&amp;gt;&lt;/code&gt; when necessary. This could be for a variety of reasons, such as wanting to use &lt;a href=&quot;https://gcanti.github.io/fp-ts/&quot;&gt;fp-ts&lt;/a&gt; utils.&lt;/p&gt;
&lt;p&gt;However, it’s not a strict rule and use whichever option makes the most sense for your situation.&lt;/p&gt;
&lt;h2 id=&quot;related-reading&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/option-a-a-null/#related-reading&quot;&gt;&lt;span&gt;Related reading&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;chris20194. (2020, July 26). &lt;a href=&quot;https://www.reddit.com/r/ProgrammingLanguages/comments/hy6emx/explicit_nullability_vs_optionals/&quot;&gt;&lt;em&gt;Explicit nullability vs optionals&lt;/em&gt;&lt;/a&gt; [Reddit Post]. R/ProgrammingLanguages.&lt;/li&gt;
&lt;li&gt;Crockford, D. (2014, September 18). &lt;a href=&quot;https://www.youtube.com/watch?v=PSGEjv3Tqo0&quot;&gt;&lt;em&gt;The Better Parts&lt;/em&gt;&lt;/a&gt;. Nordic.js 2014, Artipelag, Stockholm.&lt;/li&gt;
&lt;li&gt;evincarofautumn. (2020, July 26). &lt;a href=&quot;https://www.reddit.com/r/ProgrammingLanguages/comments/hy6emx/explicit_nullability_vs_optionals/fzbxfy7/&quot;&gt;&lt;em&gt;Nullability is *idem…&lt;/em&gt;&lt;/a&gt; [Reddit Comment]. R/ProgrammingLanguages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=8729954&quot;&gt;&lt;em&gt;Eh, that’s a tagged union, but I think “union type” usually refers to untagged u…&lt;/em&gt;&lt;/a&gt;. (2014, December 10). Hacker News.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=18565826&quot;&gt;&lt;em&gt;Hickey’s &lt;code&gt;Maybe&lt;/code&gt; example feels misguided (about breaking existing callers). If M…&lt;/em&gt;&lt;/a&gt;. (2018, November 30). Hacker News.&lt;/li&gt;
&lt;li&gt;Hickey, R. (2013, April 2). &lt;a href=&quot;https://www.youtube.com/watch?v=QCwqnjxqfmY&quot;&gt;&lt;em&gt;Design, Composition, and Performance&lt;/em&gt;&lt;/a&gt;. ETE 2013, Philadelphia Sheraton, Society Hil, USA.&lt;/li&gt;
&lt;li&gt;Hickey, R. (2018, November 30). &lt;a href=&quot;https://www.youtube.com/watch?v=YR5WdGrpoug&quot;&gt;&lt;em&gt;Maybe Not&lt;/em&gt;&lt;/a&gt;. Clojure Conj 2018, Durham, NC, USA.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/promises-aplus/promises-spec/issues/94&quot;&gt;&lt;em&gt;Incorporate monads and category theory&lt;/em&gt;&lt;/a&gt;. (2022, May 12). GitHub.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=32018886&quot;&gt;&lt;em&gt;Isn’t Union Types just the same as “Sum Types” (as in Haskell etc.)? But does Ha…&lt;/em&gt;&lt;/a&gt;. (2022, July 7). Hacker News.&lt;/li&gt;
&lt;li&gt;Khan, W. (2017, July 24). &lt;a href=&quot;https://blog.waleedkhan.name/union-vs-sum-types&quot;&gt;Null-tracking, or the difference between union and sum types&lt;/a&gt;. &lt;em&gt;Steno &amp;amp; PL&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Lee, R. (2020, October 1). &lt;a href=&quot;https://rlee.dev/practical-guide-to-fp-ts-part-5&quot;&gt;Practical Guide to Fp-ts P5: Apply, Sequences, and Traversals&lt;/a&gt;. &lt;em&gt;Ryan’s Blog&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;munificent. (2020b, July 26). &lt;a href=&quot;https://www.reddit.com/r/ProgrammingLanguages/comments/hy6emx/explicit_nullability_vs_optionals/fzcm9ma/&quot;&gt;&lt;em&gt;The typical answer i…&lt;/em&gt;&lt;/a&gt; [Reddit Comment]. R/ProgrammingLanguages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Option_type&amp;amp;oldid=1133347830&quot;&gt;Option type&lt;/a&gt;. (2023). In &lt;em&gt;Wikipedia&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;PrimaryBet. (2020a, March 11). &lt;a href=&quot;https://old.reddit.com/r/reasonml/comments/fh3sq1/why_use_somea_rather_than_a/fk8rzg6/&quot;&gt;&lt;em&gt;PrimaryBet comments on Why use Some(&#39;a) rather than ’a?&lt;/em&gt;&lt;/a&gt; [Reddit Post]. R/Reasonml.&lt;/li&gt;
&lt;li&gt;PrimaryBet. (2020b, August 28). &lt;a href=&quot;https://www.reddit.com/r/typescript/comments/ii88m3/maybestring_vs_string_null/g358ka0/&quot;&gt;&lt;em&gt;One big difference b…&lt;/em&gt;&lt;/a&gt; [Reddit Comment]. R/Typescript.&lt;/li&gt;
&lt;li&gt;Spar, J. (2017, August 16). &lt;a href=&quot;https://stackoverflow.com/q/45712106&quot;&gt;&lt;em&gt;Why are Promises Monads?&lt;/em&gt;&lt;/a&gt; [Forum post]. Stack Overflow.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/microsoft/TypeScript/issues/805&quot;&gt;&lt;em&gt;Spec Preview: Union types&lt;/em&gt;&lt;/a&gt;. (2015, October 28). GitHub.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/gcanti/fp-ts/issues/1336&quot;&gt;&lt;em&gt;Suggestion: Change the internals of Option type&lt;/em&gt;&lt;/a&gt;. (2020, October 23). GitHub.&lt;/li&gt;
&lt;li&gt;stepstep. (2020, July 27). &lt;a href=&quot;https://www.reddit.com/r/ProgrammingLanguages/comments/hy6emx/explicit_nullability_vs_optionals/fzd5ybe/&quot;&gt;&lt;em&gt;To all the people sa…&lt;/em&gt;&lt;/a&gt; [Reddit Comment]. R/ProgrammingLanguages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Tagged_union&amp;amp;oldid=1152114262&quot;&gt;Tagged union&lt;/a&gt;. (2023). In &lt;em&gt;Wikipedia&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;TypeScript Documentation contributors. (2023, May 1). &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types&quot;&gt;&lt;em&gt;Documentation—Everyday Types&lt;/em&gt;&lt;/a&gt; [Documentation]. TypeScript: Documentation.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Union_type&amp;amp;oldid=1151698123&quot;&gt;Union type&lt;/a&gt;. (2023). In &lt;em&gt;Wikipedia&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Wayne, H. (2023, March 6). &lt;a href=&quot;https://hacklewayne.com/untaged-union-undecidable&quot;&gt;Unions are Untagged, and should be Discriminated in TypeScript: Undecidable, collapse, and anti-patterns&lt;/a&gt;. &lt;em&gt;Hackle’s Blog&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Zaitsev, D. (2018, May 4). &lt;a href=&quot;https://stackoverflow.com/a/50173415&quot;&gt;&lt;em&gt;Answer to “Why are Promises Monads?”&lt;/em&gt;&lt;/a&gt; Stack Overflow.&lt;/li&gt;
&lt;/ul&gt;
</description>
          <category>programming</category>
          <category>typescript</category>
        <pubDate>Wed, 03 May 2023 03:45:47 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/option-a-a-null/</guid>
      </item>
      <item>
        <title>Deep and shallow modules: Module design for reduced complexity</title>
        <link>https://vladimirzdrazil.com/posts/deep-shallow-modules/</link>
        <description>&lt;details&gt;
  &lt;summary&gt;Updates&lt;/summary&gt;
  &lt;dl&gt;
    &lt;dt&gt;&lt;time datetime=&quot;2023-05-28&quot;&gt;2023-05-28&lt;/time&gt;&lt;/dt&gt;
    &lt;dd&gt;
      Added &lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#typescript-example&quot;&gt;TypeScript example&lt;/a&gt;.
    &lt;/dd&gt;
  &lt;/dl&gt;
&lt;/details&gt;
&lt;h2 id=&quot;tldr&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#tldr&quot;&gt;&lt;span&gt;TLDR&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To keep complexity in check, prefer deep modules to shallow modules. A deep module has a lot of functionality hidden behind a simple interface. A shallow module has a relatively complicated interface, but doesn’t provide much functionality behind it.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#introduction&quot;&gt;&lt;span&gt;Introduction&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this post, we’ll take a look at one of the ways to design modules in a manner that reduces complexity in your code base. By the end of it, you’ll be equipped with the knowledge you need to make your projects a bit easier to work with.&lt;/p&gt;
&lt;p&gt;This article draws its ideas from the book &lt;cite&gt;&lt;q&gt;&lt;a href=&quot;https://www.amazon.com/dp/173210221X&quot;&gt;A Philosophy of Software Design&lt;/a&gt;&lt;/q&gt;&lt;/cite&gt; by &lt;a href=&quot;https://en.wikipedia.org/wiki/John_Ousterhout&quot;&gt;John Ousterhout&lt;/a&gt;, particularly from the chapter on &lt;q&gt;Deep modules&lt;/q&gt;. I highly recommend reading this book.&lt;/p&gt;
&lt;p&gt;Here’s what we’re going to cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#definitions&quot;&gt;Definitions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#avoid-complexity-by-considering-the-cost-and-benefit-of-modules&quot;&gt;Why each module has a cost and a benefit associated with it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#deep-and-shallow-modules&quot;&gt;Deep and shallow modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#to-keep-complexity-in-check-prefer-deep-modules&quot;&gt;Why prefer deep modules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;definitions&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#definitions&quot;&gt;&lt;span&gt;Definitions&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;what-s-a-module&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#what-s-a-module&quot;&gt;&lt;span&gt;What’s a module&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A module is a relatively independent entity that can take many forms, such as classes, services, functions, or subsystems. It consists of an &lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#whats-an-interface&quot;&gt;interface&lt;/a&gt; (the &lt;em&gt;what&lt;/em&gt;) and an &lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#whats-an-implementation&quot;&gt;implementation&lt;/a&gt; (the &lt;em&gt;how&lt;/em&gt;).&lt;/p&gt;
&lt;h3 id=&quot;what-s-an-abstraction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#what-s-an-abstraction&quot;&gt;&lt;span&gt;What’s an abstraction&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;An abstraction is a simplified view of an entity, which omits unimportant details. This makes it easier to think about and manipulate such an entity.&lt;/p&gt;
&lt;h3 id=&quot;what-s-an-interface&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#what-s-an-interface&quot;&gt;&lt;span&gt;What’s an interface&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Each module has an interface which serves as the module’s abstraction. This abstraction presents a simplified view of the module’s functionality. You can interact with the module through this abstraction without needing to know the implementation details.&lt;/p&gt;
&lt;p&gt;The module interface contains essential information you need to use a module effectively. It consists of two kinds of information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#formal-interface-information&quot;&gt;formal information&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#informal-interface-information&quot;&gt;informal information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;formal-interface-information&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#formal-interface-information&quot;&gt;&lt;span&gt;Formal interface information&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Formal interface information is specified explicitly in code, and some of it can be checked for correctness by your programming language.&lt;/p&gt;
&lt;p&gt;For example, the formal interface of a method is expressed in its signature, which includes the parameter names, types and the return value’s type.&lt;/p&gt;
&lt;h4 id=&quot;informal-interface-information&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#informal-interface-information&quot;&gt;&lt;span&gt;Informal interface information&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Informal interface information describes behaviors and usage restrictions that cannot be enforced and described by the programming language. They can only be described through comments, and they are usually more complicated than the formal information.&lt;/p&gt;
&lt;p&gt;Examples could be description of the limitations or known issues with the module.&lt;/p&gt;
&lt;h3 id=&quot;what-s-an-implementation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#what-s-an-implementation&quot;&gt;&lt;span&gt;What’s an implementation&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Implementation is the actual code that does what the module’s interface promised. It’s all the technical stuff behind the scenes, like algorithms and data structures, that achieves what the interface described.&lt;/p&gt;
&lt;h2 id=&quot;avoid-complexity-by-considering-the-cost-and-benefit-of-modules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#avoid-complexity-by-considering-the-cost-and-benefit-of-modules&quot;&gt;&lt;span&gt;Avoid complexity by considering the cost and benefit of modules&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Adding a module to your codebase introduces complexity because it adds another thing you need to understand and integrate with existing code.&lt;/p&gt;
&lt;p&gt;The cost associated with a module is primarily its interface. As a user of the module, you do not need to know its implementation details, only how to interact with its interface. The smaller and simpler the interface, the less complexity the module introduces.&lt;/p&gt;
&lt;p&gt;The benefit associated with a module is the additional functionality it provides to your program.&lt;/p&gt;
&lt;p&gt;To avoid complexity, you need to consider the cost and benefit associated with each module. The cost primarily relates to the complexity the module’s interface is introducing, while the benefit comes from the additional functionality the module provides.&lt;/p&gt;
&lt;h2 id=&quot;deep-and-shallow-modules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#deep-and-shallow-modules&quot;&gt;&lt;span&gt;Deep and shallow modules&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By comparing the functionality and interface of modules, which we described in terms of cost vs. benefit, you can categorize modules into two types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#deep-modules&quot;&gt;deep modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#shallow-modules&quot;&gt;shallow modules&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A module’s depth refers to the amount of functionality it has hidden behind an interface. The more functionality there is hidden behind an interface, the deeper the module is.&lt;/p&gt;
&lt;h3 id=&quot;deep-modules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#deep-modules&quot;&gt;&lt;span&gt;Deep modules&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A deep module has a lot of functionality hidden behind a simple interface.&lt;/p&gt;
&lt;h3 id=&quot;shallow-modules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#shallow-modules&quot;&gt;&lt;span&gt;Shallow modules&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A shallow module has a relatively complicated interface, but doesn’t provide much functionality behind it. In extreme cases, a module can be so shallow that it adds no abstraction — using it requires more documentation and effort than just directly manipulating the variable it’s supposed to modify.&lt;/p&gt;
&lt;h3 id=&quot;deep-and-shallow-modules-figure&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#deep-and-shallow-modules-figure&quot;&gt;&lt;span&gt;Deep and shallow modules figure&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-goat&quot; data-codeblock=&quot;true&quot; data-language=&quot;goat&quot;&gt;&lt;code class=&quot;language-goat&quot;&gt;                 interface/cost
             ┌─ (less is better)
             │ │
             │ │
             │ │
             │ │
             │ │                   functionality/benefit
 ■■■■■■■■■■■◀┘ │      ┌───────────── (more is better)
 │          │  │      │
 │          │  │      │                           │
 │          │  │      │                           │
 │          │  │      │                           │
 │          │  │      │              ┌────────────┘
 │       ◀─────┼──────┘              │
 │          │  │                     │
 │          │  │                     │
 │          │  │                     │
 │          │  └───▶■■■■■■■■■■■■■■■■■│■■■■
 │          │      │                 ▼   │
 │          │      │                     │
 └──────────┘      └─────────────────────┘
 deep module           shallow module&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;to-keep-complexity-in-check-prefer-deep-modules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#to-keep-complexity-in-check-prefer-deep-modules&quot;&gt;&lt;span&gt;To keep complexity in check, prefer deep modules&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The best modules are those that offer significant benefits while keeping the costs low. Deep modules are an example of this, as they offer a lot of functionality behind a simple interface, while imposing the least amount of complexity on the system.&lt;/p&gt;
&lt;p&gt;On the other hand, shallow modules don’t help much in managing complexity, as they offer little to no abstraction and make things more complicated. In other words, they add complexity but provide no compensating benefit.&lt;/p&gt;
&lt;p&gt;When you’re adding a module, do a cost-benefit analysis. Ask yourself if the module provides enough benefit (functionality) compared to its cost (interface). By thinking in terms of deep modules, you can ensure that you’re adding modules that offer significant benefits while keeping the costs low.&lt;/p&gt;
&lt;h2 id=&quot;typescript-example&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#typescript-example&quot;&gt;&lt;span&gt;TypeScript example&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;details&gt;
  &lt;summary&gt;Examples&lt;/summary&gt;
&lt;p&gt;This TypeScript example demonstrates the concepts of shallow and deep modules. The code is organized into separate modules represented by region comments.&lt;/p&gt;
&lt;p&gt;In the first example, we have several shallow modules. In the second example, I’ve refactored the code to reduce the number of those shallow modules.&lt;/p&gt;
&lt;p&gt;Feel free to dig in, play around with it, and ask yourself: Which example is easier to understand and maintain? Which one introduces more complexity?&lt;/p&gt;
&lt;h3 id=&quot;example-with-shallow-modules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#example-with-shallow-modules&quot;&gt;&lt;span&gt;Example with shallow modules&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * Pretend that each region comment represents a separate module.
 *
 * By keeping everything in one file, it&#39;s easier to experiment with the example
 * in a REPL.
 */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `types.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  cancellationPolicies&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CancellationPolicy&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  prices&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductPrice&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  productGroups&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductGroup&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `cancellationPolicy.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CancellationPolicy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getCancellationPolicies&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cancellationPolicies&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getProductCancellationPolicies&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; policies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCancellationPolicies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; policies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;policy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; policy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productId &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; productId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;isCancellationPolicyFree&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  absoluteFee&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  relativeFee&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CancellationPolicy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; absoluteFee &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; relativeFee &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;isSomeProductCancellationPolicyFree&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; policies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductCancellationPolicies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; policies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isCancellationPolicyFree&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;hasProductGroupFreeCancellation&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productIds&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  productIds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;isSomeProductCancellationPolicyFree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `productPrice.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; getProductPrices &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductPrice&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prices&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getProductGroupPrices&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; prices &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductPrices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; prices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prices&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; prices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productGroupId &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; productGroupId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getPriceProductIds&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productPrices&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductPrice&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  productPrices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; price&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `productGroup.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductGroup&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getProductGroups&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productGroups&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getProductGroup&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroups &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductGroups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; productGroups&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productGroup&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; productGroup&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `productGroupView.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productGroup &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/* #region We’re going to refactor these callers and callees in the second example. */&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroupPrices &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductGroupPrices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productIds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPriceProductIds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productGroupPrices&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hasFreeCancellation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hasProductGroupFreeCancellation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    productIds&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    hasFreeCancellation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroup&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// #region Module `main.ts`&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productId1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productId1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productId2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productId2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productId3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productId3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroupId1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productGroupId1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroupId2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productGroupId2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroupId3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productGroupId3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Assume that you cannot change the returned state.
 *
 * We could restructure the state to make it easier to achieve our desired
 * outcome, but in longer-term projects, that task might not be as
 * straightforward.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    cancellationPolicies&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    productGroups&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Product group 1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Product group 2&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    prices&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;36&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;47&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;example-refactored-based-on-the-idea-of-deep-modules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#example-refactored-based-on-the-idea-of-deep-modules&quot;&gt;&lt;span&gt;Example refactored based on the idea of deep modules&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve kept the root selectors in each module and have not refactored &lt;code&gt;hasProductGroupFreeCancellation&lt;/code&gt; to directly access the &lt;code&gt;state&lt;/code&gt;. In our example, it doesn’t matter if we access the state directly, but in larger projects, it might be a good idea to encapsulate the state shape.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * Pretend that each region comment represents a separate module.
 *
 * By keeping everything in one file, it&#39;s easier to experiment with the example
 * in a REPL.
 */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `types.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  cancellationPolicies&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; CancellationPolicy&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  prices&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductPrice&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  productGroups&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductGroup&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `cancellationPolicy.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CancellationPolicy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getCancellationPolicies&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cancellationPolicies&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `productPrice.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductPrice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; getProductPrices &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ProductPrice&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prices&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `productGroup.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ProductGroup&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getProductGroups&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productGroups&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getProductGroup&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroups &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductGroups&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; productGroups&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productGroup&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; productGroup&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #region Module `productGroupView.ts` */&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hasProductGroupFreeCancellation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productIds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductPrices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prices&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; prices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productGroupId &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; productGroupId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;price&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; price&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;productId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * When you start putting things closer together, as we did here, you might
   * start seeing opportunities for refactors you haven&#39;t seen before.
   *
   * For example, in this case, I removed the nested `some` and used `includes`
   * instead.
   */&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cancellationPolicies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCancellationPolicies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; matchedPolicies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cancellationPolicies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; productId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; absoluteFee&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; relativeFee &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
      absoluteFee &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; relativeFee &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; productIds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; matchedPolicies&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getProductGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;productGroup &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Callers and callees are refactored.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hasFreeCancellation &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hasProductGroupFreeCancellation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    productGroupId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    hasFreeCancellation&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroup&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// #region Module `main.ts`&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productId1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productId1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productId2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productId2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productId3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productId3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroupId1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productGroupId1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroupId2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productGroupId2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; productGroupId3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;productGroupId3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Assume that you cannot change the returned state, for example, because it
 * comes from a third-party API.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; State &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    cancellationPolicies&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; absoluteFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; relativeFee&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    productGroups&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Product group 1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Product group 2&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    prices&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;36&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; productGroupId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productGroupId2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; productId3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;47&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getProductGroupData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; productGroupId3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/* #endregion */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#conclusion&quot;&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When designing modules, consider the balance between the cost and benefit associated with each module. To keep complexity in check, generally prefer deep modules over shallow modules.&lt;/p&gt;
&lt;p&gt;Deep modules provide a lot of functionality behind a simple interface, while shallow modules have a relatively complicated interface but do not provide much functionality. By choosing deep modules, you can ensure that you are adding significant benefits to your codebase while keeping complexity lower.&lt;/p&gt;
&lt;h2 id=&quot;related-reading&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#related-reading&quot;&gt;&lt;span&gt;Related reading&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Book and book chapter — Ousterhout, J. K. (2022). &lt;a href=&quot;https://www.amazon.com/dp/173210221X&quot;&gt;Deep modules. In A philosophy of software design (Second edition)&lt;/a&gt;. Yaknyam Press.&lt;/li&gt;
&lt;li&gt;Talk — Ousterhout, J. (2018, August 1). &lt;a href=&quot;https://www.youtube.com/watch?v=bmSAYlu0NcY&quot;&gt;A Philosophy of Software Design&lt;/a&gt;. Talks at Google.&lt;/li&gt;
&lt;li&gt;Google Talk Forum — Ousterhout, J. (2018, May 24). &lt;a href=&quot;https://groups.google.com/g/software-design-book&quot;&gt;Software-Design-Book&lt;/a&gt; Google Talk Forum.&lt;/li&gt;
&lt;li&gt;Lecture notes – Ousterhout, J. (2018). &lt;a href=&quot;https://web.stanford.edu/~ouster/cgi-bin/cs190-winter18/lecture.php?topic=modularDesign&quot;&gt;Modular Design—Lecture Notes for CS 190&lt;/a&gt;. CS 190: Software Design Studio (Winter 2018)&lt;/li&gt;
&lt;li&gt;Article — P. Gabriel, R. (1991). &lt;a href=&quot;https://dreamsongs.com/WIB.html&quot;&gt;Worse Is Better&lt;/a&gt;.
&lt;ul&gt;
&lt;li&gt;&lt;q&gt;Simplicity – the design must be simple, both in implementation and interface. It is more important for the interface to be simple than the implementation.&lt;/q&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;This review is interesting because the reviewer disagrees with some points of the book. Personally, I’m still siding with points expressed in the book:
&lt;ul&gt;
&lt;li&gt;Koppel, J. (2018, October 29). &lt;a href=&quot;https://www.pathsensitive.com/2018/10/book-review-philosophy-of-software.html&quot;&gt;Book Review: A Philosophy of Software Design&lt;/a&gt;. Path-Sensitive.&lt;/li&gt;
&lt;li&gt;Koppel, J. (2018, October 8). &lt;a href=&quot;https://groups.google.com/g/software-design-book/c/DvnQ1Bvqy30&quot;&gt;Book Review: A Philosophy of Software Design&lt;/a&gt;. Software-Design-Book Google Talk Forum.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;related-posts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/deep-shallow-modules/#related-posts&quot;&gt;&lt;span&gt;Related posts&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vladimirzdrazil.com/til/programming/philosophy-of-software-design&quot;&gt;Philosophy of software design (2018) — John Ousterhout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
          <category>programming</category>
        <pubDate>Sat, 15 Apr 2023 19:02:34 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/deep-shallow-modules/</guid>
      </item>
      <item>
        <title>Binary search debugging: Simplify your debugging process</title>
        <link>https://vladimirzdrazil.com/posts/binary-search-debugging/</link>
        <description>&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#introduction&quot;&gt;&lt;span&gt;Introduction&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tracking down bugs in your code is often frustrating. With a binary search debugging you can make it less so. It’s a simple technique that can help you pinpoint problematic lines of code quickly and efficiently.&lt;/p&gt;
&lt;h2 id=&quot;what-is-binary-search-debugging&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#what-is-binary-search-debugging&quot;&gt;&lt;span&gt;What is binary search debugging?&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Binary search debugging is a methodical process that aims to narrow down the cause of a bug by systematically testing different parts of the code. The name “binary” refers to the fact that at each step, you divide the code that you suspect is causing the problem in the middle and evaluate its behavior, typically using a breakpoint or a print statement.&lt;/p&gt;
&lt;p&gt;After each evaluation, you choose a new breakpoint closer to the suspected problem area and repeat the process until you pinpoint the single line of code responsible for the bug.&lt;/p&gt;
&lt;h2 id=&quot;step-by-step-guide&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#step-by-step-guide&quot;&gt;&lt;span&gt;Step-by-step guide&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Identify the problem
&lt;ul&gt;
&lt;li&gt;The first step in debugging any piece of code is to identify the problem. Determine the exact behavior that is not working as intended.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Choose a breakpoint
&lt;ul&gt;
&lt;li&gt;Decide where to place the breakpoint. This should be a line of code that is close to the middle of the section of code you suspect is causing the problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run the code with the breakpoint in place.&lt;/li&gt;
&lt;li&gt;Determine the result
&lt;ul&gt;
&lt;li&gt;Does the code behave as expected at this breakpoint?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Choose a new breakpoint
&lt;ul&gt;
&lt;li&gt;Choose a new breakpoint that is located midway between the previous breakpoint and the start or end of the section of code, depending on the result of the previous run.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Run the code and evaluate again.&lt;/li&gt;
&lt;li&gt;Repeat steps 3-6 until you have narrowed down the section of code causing the issue to a single line.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;different-name-same-thing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#different-name-same-thing&quot;&gt;&lt;span&gt;Different name, same thing&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Binary search debugging is a technique that uses the &lt;a href=&quot;https://en.wikipedia.org/wiki/Binary_search_algorithm&quot;&gt;binary search algorithm&lt;/a&gt;. However, instead of searching for a specific value, you are looking for the side effect of a value, such as an error or unexpected behavior in your code.&lt;/p&gt;
&lt;p&gt;Sometimes, people refer to this approach as the &lt;a href=&quot;https://doi.org/10.1145/358690.358695&quot;&gt;Wolf Fence algorithm&lt;/a&gt;, named after a hypothetical scenario where you need to find a lone wolf in Alaska. To do so, you fence Alaska in half and wait for the wolf to howl. Once you know which half the wolf is in, you repeat the process, splitting the section in half again until you find the wolf.&lt;/p&gt;
&lt;p&gt;Another term used to describe this technique is &lt;a href=&quot;https://en.wikipedia.org/wiki/Bisection_(software_engineering)&quot;&gt;bisection&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Divide-and-conquer_algorithm&quot;&gt;divide and conquer&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;benefits&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#benefits&quot;&gt;&lt;span&gt;Benefits&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It helps you find bugs in your code faster.&lt;/li&gt;
&lt;li&gt;You’re less likely to miss something since you’re being methodical.&lt;/li&gt;
&lt;li&gt;It breaks the debugging process into smaller, easier-to-manage chunks.&lt;/li&gt;
&lt;li&gt;It’s super easy to use, you don’t need any fancy tools or software.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;drawbacks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#drawbacks&quot;&gt;&lt;span&gt;Drawbacks&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Limited to specific types of bugs
&lt;ul&gt;
&lt;li&gt;Binary search debugging is most effective for bugs that are easily reproducible and have a clear input/output. Bugs that are more intermittent or related to external factors may be more difficult to isolate using this technique.&lt;/li&gt;
&lt;li&gt;It may not be effective for bugs that occur in things that are executed multiple times. Like loops.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Requires familiarity with the codebase
&lt;ul&gt;
&lt;li&gt;Binary search debugging assumes that you have a good understanding of the codebase and can identify which sections of the code to isolate.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#conclusion&quot;&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Binary search debugging is a technique that can help you locate and resolve bugs in software projects more efficiently. The approach involves repeatedly dividing the codebase into smaller sections to narrow down the buggy lines faster. By isolating and testing each section systematically, you can quickly pinpoint problematic lines of code and resolve the issue more efficiently.&lt;/p&gt;
&lt;h2 id=&quot;did-you-know&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#did-you-know&quot;&gt;&lt;span&gt;Did you know?&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Git uses this algorithm for the command &lt;a href=&quot;https://git-scm.com/docs/git-bisect&quot;&gt;&lt;code&gt;git bisect&lt;/code&gt;&lt;/a&gt; to determine which commit introduced a particular bug.&lt;/p&gt;
&lt;h2 id=&quot;related-reading&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/binary-search-debugging/#related-reading&quot;&gt;&lt;span&gt;Related reading&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;C2 Wiki Contributors. (2006, October 11). &lt;a href=&quot;https://wiki.c2.com/?BinaryChop&quot;&gt;&lt;em&gt;Binary Chop&lt;/em&gt;&lt;/a&gt;. C2 Wiki.&lt;/li&gt;
&lt;li&gt;Gauss, E. J. (1982). &lt;a href=&quot;https://doi.org/10.1145/358690.358695&quot;&gt;The “Wolf Fence” algorithm for debugging&lt;/a&gt;. Communications of the ACM, 25(11), 780.&lt;/li&gt;
&lt;li&gt;unj2. (2010, May 19). &lt;a href=&quot;https://stackoverflow.com/q/843909&quot;&gt;&lt;em&gt;Debugging and Binary Search&lt;/em&gt;&lt;/a&gt; [Forum post]. Stack Overflow.&lt;/li&gt;
&lt;/ul&gt;
</description>
          <category>debugging</category>
          <category>programming</category>
        <pubDate>Fri, 07 Apr 2023 13:49:16 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/binary-search-debugging/</guid>
      </item>
      <item>
        <title>Why Object.keys doesn’t and shouldn’t return (keyof T)[]</title>
        <link>https://vladimirzdrazil.com/posts/object-keys-keyof-t/</link>
        <description>&lt;h2 id=&quot;tldr&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#tldr&quot;&gt;&lt;span&gt;TLDR&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Object.keys()&lt;/code&gt; doesn’t return &lt;code&gt;(keyof T)[]&lt;/code&gt; in TypeScript because objects can have additional properties at runtime, leading to potential issues. Use &lt;a href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#i-understand-all-this-but-i-still-want-to-do-it&quot;&gt;wrapper&lt;/a&gt; as a workaround and be aware of the limitations when using it.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#introduction&quot;&gt;&lt;span&gt;Introduction&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Have you ever wondered why &lt;code&gt;Object.keys&lt;/code&gt; doesn’t return type &lt;code&gt;(keyof T)[]&lt;/code&gt; in TypeScript? In this article, we’ll explore the reasons behind this decision and look at some examples to illustrate the potential issues with returning &lt;code&gt;(keyof T)[]&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;overview-of-object-keys&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#overview-of-object-keys&quot;&gt;&lt;span&gt;Overview of &lt;code&gt;Object.keys()&lt;/code&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In TypeScript, &lt;code&gt;Object.keys()&lt;/code&gt; is a built-in method that &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys&quot;&gt;returns an array of a given object’s own enumerable string-keyed property names&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Object.keys(obj: object): string[];&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  age&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; person&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Person &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  age&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;person&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// return type is string[]&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&quot;name&quot;, &quot;age&quot;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;why-object-keys-doesn-t-return-keyof-t&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#why-object-keys-doesn-t-return-keyof-t&quot;&gt;&lt;span&gt;Why &lt;code&gt;Object.keys()&lt;/code&gt; doesn’t return &lt;code&gt;(keyof T)[]&lt;/code&gt;?&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The reason &lt;code&gt;Object.keys()&lt;/code&gt; doesn’t return type &lt;code&gt;(keyof T)[]&lt;/code&gt; in TypeScript is that once you move to the instantiated type world, an object can have more properties at runtime than are statically known at compile time. As a result, returning &lt;code&gt;(keyof T)[]&lt;/code&gt; makes sense only in the domain of type variables, such as &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;keyof T&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Anders_Hejlsberg&quot;&gt;Anders Hejlsberg&lt;/a&gt;, a core developer of TypeScript, explained this in a comment on &lt;cite&gt;&lt;a href=&quot;https://github.com/Microsoft/TypeScript/pull/12253#issuecomment-263132208&quot;&gt;GitHub&lt;/a&gt;&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;All this goes back to the reasoning why TypeScript uses &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/type-compatibility.html&quot;&gt;structural type system&lt;/a&gt;. You can’t know that JavaScript object won’t have additional properties. If TypeScript supported &lt;a href=&quot;https://flow.org/en/docs/types/objects/&quot;&gt;exact types&lt;/a&gt;, it would make sense to use &lt;code&gt;(keyof T)[]&lt;/code&gt;. But TypeScript doesn’t have them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Anders_Hejlsberg&quot;&gt;Hejlsberg&lt;/a&gt; also gave an example to illustrate his point:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, imagine a type &lt;code&gt;Base&lt;/code&gt; with just a few properties and a family of types derived from that. Calling &lt;code&gt;Object.keys&lt;/code&gt; with a &lt;code&gt;Base&lt;/code&gt; would return a &lt;code&gt;(keyof Base)[]&lt;/code&gt; which is almost certainly wrong because an actual instance would be a derived object with more keys. It completely degenerates for type &lt;code&gt;{}&lt;/code&gt; which could be any object but would return &lt;code&gt;never[]&lt;/code&gt; for its keys.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://github.com/Microsoft/TypeScript/pull/12253#issuecomment-263132208&quot;&gt;Object.keys() types refinement, and Object.entries() types bug fix — ahejlsberg Nov 27, 2016&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;In the following section, we’ll explore some code examples to see what could go wrong if &lt;code&gt;Object.keys()&lt;/code&gt; did return &lt;code&gt;(keyof T)[]&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;example-1&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#example-1&quot;&gt;&lt;span&gt;Example 1&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pretend that &lt;code&gt;Object.keys()&lt;/code&gt; does return &lt;code&gt;(keyof T)[]&lt;/code&gt; and consider this example:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TaskCategory&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;work&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TaskCounts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Record&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TaskCategory&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logCategoryCounts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;counts&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; TaskCounts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; categoryNames &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;counts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Task categories:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; categoryNames&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; taskCounts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; work&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; personal&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;logCategoryCounts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;taskCounts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is what the return type is and what is logged:&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot; data-codeblock=&quot;true&quot; data-language=&quot;typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; categoryNames &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;counts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// categoryNames type is [&quot;work&quot; | &quot;home&quot;]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Task categories:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; categoryNames&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// logs [&quot;work&quot; | &quot;home&quot; | &quot;personal&quot;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There’s a mismatch between what we logged and what the types said.&lt;/p&gt;
&lt;p&gt;This is allowed due to TypeScript’s use of a &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/type-compatibility.html&quot;&gt;structural type system&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;example-2&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#example-2&quot;&gt;&lt;span&gt;Example 2&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Again, pretend that &lt;code&gt;Object.keys()&lt;/code&gt; does return &lt;code&gt;(keyof T)[]&lt;/code&gt;. This example demonstrates how &lt;code&gt;Object.keys()&lt;/code&gt; would return the wrong &lt;code&gt;never[]&lt;/code&gt; type.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logCategoryCounts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;counts&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; categoryNames &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;counts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// categoryNames type is never[]&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Task categories:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; categoryNames&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// logs [&quot;work&quot; | &quot;home&quot;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; taskCounts &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; work&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;logCategoryCounts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;taskCounts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;example-3&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#example-3&quot;&gt;&lt;span&gt;Example 3&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Consider this code:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; windowKeys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;windowKeys&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have no way of knowing whether the &lt;code&gt;window&lt;/code&gt; object has been mutated, or if the browser’s &lt;code&gt;window&lt;/code&gt; has more properties than what our types indicate. This means that it could potentially have properties that weren’t known at compile time. Assuming that &lt;code&gt;Object.keys()&lt;/code&gt; does return &lt;code&gt;(keyof T)[]&lt;/code&gt;, &lt;code&gt;Object.keys()&lt;/code&gt; return type could be incorrect.&lt;/p&gt;
&lt;h2 id=&quot;i-understand-all-this-but-i-still-want-to-do-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#i-understand-all-this-but-i-still-want-to-do-it&quot;&gt;&lt;span&gt;I understand all this, but I still want to do it&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you still want to use return type &lt;code&gt;(keyof T)[]&lt;/code&gt; for &lt;code&gt;Object.keys()&lt;/code&gt;, you can create a wrapper around it like so:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; data-codeblock=&quot;true&quot; data-language=&quot;ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * A wrapper for `Object.keys()` that forces a `(keyof T)[]` return type.
 * Warning: using this wrapper may lead to potential issues if the object being
 * passed in has additional properties that aren&#39;t known at compile time. Please
 * use with caution and ensure that you&#39;re aware of the limitations of this
 * approach.
 * [https://stackoverflow.com/a/55012175](https://stackoverflow.com/a/55012175)
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; keys &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keys &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;o&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Extract&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;keyof&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://github.com/Microsoft/TypeScript/pull/12253#issuecomment-393954723&quot;&gt;Object.keys() types refinement, and Object.entries() types bug fix — domoritz Jun 1, 2018&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;However, it’s important to be aware of the potential drawbacks of using this type of wrapper, so consider adding a warning message to it.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#conclusion&quot;&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We explored why TypeScript doesn’t return type &lt;code&gt;(keyof T)[]&lt;/code&gt; when using &lt;code&gt;Object.keys()&lt;/code&gt;. This decision stems from the fact that objects can have more properties at runtime than what is known at compile time. Returning &lt;code&gt;(keyof T)[]&lt;/code&gt; would be misleading and could potentially cause issues.&lt;/p&gt;
&lt;p&gt;You saw some examples of how this could happen and saw a wrapper for a workaround. It is important to understand the reasoning behind this decision and consider the potential drawbacks when working with returning &lt;code&gt;(keyof T)[]&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;related-reading&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/object-keys-keyof-t/#related-reading&quot;&gt;&lt;span&gt;Related reading&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Cavanaugh, R. (2019a, March 5). &lt;a href=&quot;https://stackoverflow.com/q/55012174&quot;&gt;&lt;em&gt;Why doesn’t Object.keys return a keyof type in TypeScript?&lt;/em&gt;&lt;/a&gt; [Forum post]. Stack Overflow.&lt;/li&gt;
&lt;li&gt;Cavanaugh, R. (2019b, March 5). &lt;a href=&quot;https://stackoverflow.com/a/55012175&quot;&gt;&lt;em&gt;Answer to “Why doesn’t Object.keys return a keyof type in TypeScript?”&lt;/em&gt;&lt;/a&gt; Stack Overflow.&lt;/li&gt;
&lt;li&gt;Flow Documentation Contributors. (2023, May 1). &lt;a href=&quot;https://flow.org/en/docs/types/objects/&quot;&gt;&lt;em&gt;Object Types&lt;/em&gt;&lt;/a&gt;. Flow Documentation.&lt;/li&gt;
&lt;li&gt;Hejlsberg, A. (2016, November 27). &lt;a href=&quot;https://github.com/Microsoft/TypeScript/pull/12253#issuecomment-263132208&quot;&gt;&lt;em&gt;Object.keys() types refinement, and Object.entries() types bugfix&lt;/em&gt;&lt;/a&gt;. GitHub.&lt;/li&gt;
&lt;li&gt;TypeScript Documentation contributors. (2023, May 1). &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/type-compatibility.html&quot;&gt;&lt;em&gt;Type Compatibility&lt;/em&gt;&lt;/a&gt;. TypeScript: Documentation.&lt;/li&gt;
&lt;/ul&gt;
</description>
          <category>programming</category>
          <category>typescript</category>
        <pubDate>Sun, 02 Apr 2023 10:22:14 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/object-keys-keyof-t/</guid>
      </item>
      <item>
        <title>The AHA principle: Avoid hasty abstractions</title>
        <link>https://vladimirzdrazil.com/posts/aha-principle/</link>
        <description>&lt;h2 id=&quot;tldr&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#tldr&quot;&gt;&lt;span&gt;TLDR&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://kentcdodds.com/blog/aha-programming&quot;&gt;&lt;abbr&gt;AHA&lt;/abbr&gt; (Avoid Hasty Abstractions) principle&lt;/a&gt; advises preferring duplication over the wrong abstraction, optimizing for change first, and waiting for necessary abstractions to emerge. Benefits are easier maintenance and flexibility. Be careful about excessive avoidance of abstractions and potential refactoring/testing challenges.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#introduction&quot;&gt;&lt;span&gt;Introduction&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a developer, you strive to write a clean and efficient code. One principle you likely follow is to avoid repetition and create abstractions for reusable code. However, there are times when duplicating code is the way to go and creating abstractions should wait.&lt;/p&gt;
&lt;h2 id=&quot;the-aha-principle&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#the-aha-principle&quot;&gt;&lt;span&gt;The AHA principle&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://kentcdodds.com/blog/aha-programming&quot;&gt;&lt;abbr&gt;AHA&lt;/abbr&gt; (Avoid Hasty Abstractions) principle&lt;/a&gt; advises you against creating unnecessary or premature abstractions that would otherwise increase code complexity and make maintenance more difficult in the long run. Instead, duplicate the code and hold off on refactoring until a clear and useful abstraction emerges.&lt;/p&gt;
&lt;p&gt;You can summarize the AHA principle in 2 points:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Prefer duplication over the wrong abstraction.&lt;/li&gt;
&lt;li&gt;Optimize for change first.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://kentcdodds.com/about&quot;&gt;Kent C. Dodds&lt;/a&gt; described the AHA principle in his blog post &lt;a href=&quot;https://kentcdodds.com/blog/aha-programming&quot;&gt;AHA Programming&lt;/a&gt;. It’s based on &lt;a href=&quot;https://sandimetz.com/about&quot;&gt;Sandi Metz&lt;/a&gt;’s “&lt;a href=&quot;https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction&quot;&gt;Prefer duplication over the wrong abstraction&lt;/a&gt;”.&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-aha-principle&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#benefits-of-aha-principle&quot;&gt;&lt;span&gt;Benefits of AHA principle&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Maintainability
&lt;ul&gt;
&lt;li&gt;Without unnecessary abstractions, it’s easier to maintain and modify your code in the long run.&lt;/li&gt;
&lt;li&gt;Code is easier to read and understand, as it avoids unnecessary complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Flexibility
&lt;ul&gt;
&lt;li&gt;By optimizing for change first, you create code that is more adaptable to future changes and requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;challenges-of-aha-principle&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#challenges-of-aha-principle&quot;&gt;&lt;span&gt;Challenges of AHA principle&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Excessive avoidance of abstractions
&lt;ul&gt;
&lt;li&gt;Excessive avoidance of abstractions or delaying them for too long can backfire, resulting in a code that is difficult to maintain, defeating the very purpose of the AHA principle.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Refactoring and testing
&lt;ul&gt;
&lt;li&gt;It may require more refactoring and testing when you eventually decide to abstract your code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;reliance-on-developer-judgment-and-experience&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#reliance-on-developer-judgment-and-experience&quot;&gt;&lt;span&gt;Reliance on developer judgment and experience&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Q: Doesn’t the AHA principle rely too much on subjective judgment of developers to determine when and how to abstract their code?&lt;/p&gt;
&lt;p&gt;A: Yes it does. Same as every other related principle. There’s no silver bullet and there’s no principle you can follow blindly. Think of it more like a guideline.&lt;/p&gt;
&lt;h2 id=&quot;what-about-dry-and-wet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#what-about-dry-and-wet&quot;&gt;&lt;span&gt;What about DRY and WET?&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;AHA suggests that both &lt;a href=&quot;https://en.wikipedia.org/wiki/Don%27t_repeat_yourself#WET&quot;&gt;&lt;abbr&gt;WET&lt;/abbr&gt; (Write Everything Twice)&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Don%27t_repeat_yourself#&quot;&gt;&lt;abbr&gt;DRY&lt;/abbr&gt; (Don’t Repeat Yourself)&lt;/a&gt; approaches can result in a software that is inflexible and difficult to maintain. Instead of starting with an abstraction (DRY) or abstracting after a certain number of duplications (WET), the AHA proposes to wait with the abstraction until you feel like you know the use cases for that duplicate code. At that point, you’ll have a clearer understanding of how the abstraction should function.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#conclusion&quot;&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I can relate to the desire to create reusable code and avoid repetition. But sometimes duplication is the way to go, and that’s where the AHA principle comes in. It emphasizes the importance of carefully considering when and how to create abstractions, rather than automatically abstracting your code.&lt;/p&gt;
&lt;p&gt;By avoiding premature abstractions, you create code that is easier to maintain and modify in the long run.&lt;/p&gt;
&lt;p&gt;So, next time you face a coding challenge, don’t be afraid to duplicate your code if it makes sense. By doing so, you may actually be making your code easier to work with.&lt;/p&gt;
&lt;h2 id=&quot;related-reading&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/aha-principle/#related-reading&quot;&gt;&lt;span&gt;Related reading&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;C. Dodds, K. (2020, June 22). &lt;a href=&quot;https://kentcdodds.com/blog/aha-programming&quot;&gt;AHA Programming&lt;/a&gt;. &lt;em&gt;Kent C. Dodds&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/w/index.php?title=Don%27t_repeat_yourself&amp;amp;oldid=1146053248#Alternatives&quot;&gt;Alternatives&lt;/a&gt;. In Don’t repeat yourself. (2023). In &lt;em&gt;Wikipedia&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Metz, S. (2016, January 20). &lt;a href=&quot;https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction&quot;&gt;The Wrong Abstraction&lt;/a&gt;. &lt;em&gt;Sandi Metz&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
          <category>programming</category>
        <pubDate>Sat, 01 Apr 2023 11:33:28 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/aha-principle/</guid>
      </item>
      <item>
        <title>Links from the past few weeks (Nov 30, 2022)</title>
        <link>https://vladimirzdrazil.com/posts/2022-11-30-links/</link>
        <description>&lt;p&gt;List of links, articles, and other resources you might find interesting from the past few weeks.&lt;/p&gt;
&lt;h2 id=&quot;markdown&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#markdown&quot;&gt;&lt;span&gt;Markdown&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;don-t-complicate-markdown-use-markdown-and-html-together&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#don-t-complicate-markdown-use-markdown-and-html-together&quot;&gt;&lt;span&gt;Don’t complicate Markdown, use Markdown and HTML together&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/John_Gruber&quot;&gt;John Gruber&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Aaron_Swartz&quot;&gt;Aaron Swartz&lt;/a&gt; intended &lt;a href=&quot;https://en.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; to be used for prose and for it to be readable with no further processing. When Markdown’s syntax is insufficient for what you need to do, you can use regular &lt;a href=&quot;https://daringfireball.net/projects/markdown/syntax#html&quot;&gt;inline and block-level HTML elements&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are &lt;a href=&quot;https://en.wikipedia.org/wiki/Markdown#Variants&quot;&gt;Markdown flavors&lt;/a&gt; which see Markdown as too simplistic, and they extend its syntax. But in my opinion, that is a mistake. Let’s keep Markdown simple and use HTML for the more complex stuff.&lt;/p&gt;
&lt;p&gt;This is also addressed in the &lt;a href=&quot;https://daringfireball.net/projects/markdown/syntax#html&quot;&gt;official Markdown documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Markdown’s syntax is intended for one purpose: to be used as a format for &lt;em&gt;writing&lt;/em&gt; for the web.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Markdown is not a replacement for HTML, or even close to it. Its syntax is very small, corresponding only to a very small subset of HTML tags. The idea is not to create a syntax that makes it easier to insert HTML tags. In my opinion, HTML tags are already easy to insert. The idea for Markdown is to make it easy to read, write, and edit prose. HTML is a publishing format; Markdown is a writing format. Thus, Markdown’s formatting syntax only addresses issues that can be conveyed in plain text.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://daringfireball.net/projects/markdown/syntax#html&quot;&gt;Markdown: Syntax, HTML&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;So, don’t complicate Markdown. Just use Markdown and HTML together. Or maybe consider if Markdown is even what you want. You might be better off with regular HTML.&lt;/p&gt;
&lt;h3 id=&quot;is-html-a-humane-markup-language-2008&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#is-html-a-humane-markup-language-2008&quot;&gt;&lt;span&gt;Is HTML a humane markup language? (2008)&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;What about HTML? Isn’t writing it easy enough? Do we even need Markdown?&lt;/p&gt;
&lt;p&gt;Article &lt;cite&gt;&lt;a href=&quot;https://blog.codinghorror.com/is-html-a-humane-markup-language/&quot;&gt;Is HTML a humane markup language? (2008)&lt;/a&gt;&lt;/cite&gt; by &lt;a href=&quot;https://en.wikipedia.org/wiki/Jeff_Atwood&quot;&gt;Jeff Atwood&lt;/a&gt; tries to dig deeper into these questions. I like how it raises the question that maybe HTML itself is already simple enough when programmers are the intended users. The most interesting tidbit:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But in general, I’d much rather rely on a subset of trusty old HTML than expend brain cells trying to remember the fake-HTML way to make something bold, or create a hyperlink. HTML isn’t perfect, but it’s an eminently reasonable humane markup language.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://blog.codinghorror.com/is-html-a-humane-markup-language/&quot;&gt;Is HTML a humane markup language?&lt;/a&gt;&lt;/cite&gt; by &lt;a href=&quot;https://en.wikipedia.org/wiki/Jeff_Atwood&quot;&gt;Jeff Atwood&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the end, I’m still a fan of how Markdown does it. It simplifies the syntax for writing prose, but it doesn’t try to replace HTML and offers a simple way to use HTML for the more advanced stuff.&lt;/p&gt;
&lt;h2 id=&quot;html-and-css&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#html-and-css&quot;&gt;&lt;span&gt;HTML and CSS&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;accessibility-insights&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#accessibility-insights&quot;&gt;&lt;span&gt;Accessibility insights&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Trying to make your website more accessible? Microsoft has a free browser extension &lt;a href=&quot;https://accessibilityinsights.io/&quot;&gt;Accessibility Insights&lt;/a&gt; to help you with that.&lt;/p&gt;
&lt;h3 id=&quot;w3c-core-styles&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#w3c-core-styles&quot;&gt;&lt;span&gt;W3C Core Styles&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;By default, HTML documents don’t look good because the default browser styles have some poor defaults. If you’d rather not bother with styling HTML documents yourself, you might want to try &lt;a href=&quot;https://www.w3.org/StyleSheets/Core/&quot;&gt;W3C Core Styles&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;They offer several themes which you can just use by linking them from the head of your documents. Some of them look pretty outdated, but some of them still look good.&lt;/p&gt;
&lt;h3 id=&quot;accessible-inline-list-with-bullets-between-items&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#accessible-inline-list-with-bullets-between-items&quot;&gt;&lt;span&gt;Accessible inline list with bullets between items&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve been looking for a way to create an accessible inline list with bullets between items, such as this: &lt;code&gt;item 1 • item 2 • item 3&lt;/code&gt;. There are numerous solutions how to do this, but most of them don’t have good accessibility. The best solution I’ve found: &lt;cite&gt;&lt;a href=&quot;https://blog.sapegin.me/all/accessible-inline-list/&quot;&gt;Accessible inline list with bullets between items&lt;/a&gt;&lt;/cite&gt;. It has some gotchas, all is described in the article.&lt;/p&gt;
&lt;h2 id=&quot;good-taste&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#good-taste&quot;&gt;&lt;span&gt;Good taste&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;linus-torvalds-on-good-taste&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#linus-torvalds-on-good-taste&quot;&gt;&lt;span&gt;Linus Torvalds on good taste&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the interview &lt;cite&gt;&lt;a href=&quot;https://www.tag1consulting.com/blog/interview-linus-torvalds-linux-and-git&quot;&gt;Linus Torvalds on Linux, Git, and the future of open-source&lt;/a&gt;&lt;/cite&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Linus_Torvalds&quot;&gt;Linus Torvalds&lt;/a&gt; touched upon something he describes as “good taste”:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But there is that occasional “inspiration” part, that “good taste” thing that is about more than just solving some problem — solving it cleanly and nicely and yes, even beautifully.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.tag1consulting.com/blog/interview-linus-torvalds-linux-and-git#git-distributed-version-control-&quot;&gt;An interview with Linus Torvalds: Linux and Git — Part 1&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;I never thought this way about why some people solve programming problems more elegantly than others. In this interview, &lt;a href=&quot;https://en.wikipedia.org/wiki/Linus_Torvalds&quot;&gt;Linus Torvalds&lt;/a&gt; gives an interesting take on it.&lt;/p&gt;
&lt;h3 id=&quot;ira-glass-on-the-creative-process-and-a-good-taste&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#ira-glass-on-the-creative-process-and-a-good-taste&quot;&gt;&lt;span&gt;Ira Glass on the creative process and a good taste&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Ira_Glass&quot;&gt;Ira Glass&lt;/a&gt;, host of the radio program &lt;a href=&quot;https://en.wikipedia.org/wiki/This_American_Life&quot;&gt;This American Life&lt;/a&gt;, talks about the creative process and a good taste:&lt;/p&gt;
&lt;my-youtube&gt;
&lt;a href=&quot;https://www.youtube.com/watch?v=X2wLP0izeJE&quot;&gt;Play Ira Glass on good taste&lt;/a&gt;
&lt;/my-youtube&gt;
&lt;blockquote&gt;
&lt;p&gt;But it’s like there’s a gap, that for the first couple years that you’re making stuff, what you’re making isn’t so good. … But your taste … is still killer, and your taste is good enough that you can tell that what you’re making is kind of a disappointment to you. … And the most important possible thing you can do is do a lot of work — do a huge volume of work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=X2wLP0izeJE&quot;&gt;Ira Glass on good taste&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;h2 id=&quot;internet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#internet&quot;&gt;&lt;span&gt;Internet&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;don-t-use-services-that-hate-the-internet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#don-t-use-services-that-hate-the-internet&quot;&gt;&lt;span&gt;Don’t use services that hate the Internet&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Weird things happening at &lt;a href=&quot;https://en.wikipedia.org/wiki/Acquisition_of_Twitter_by_Elon_Musk#Post-acquisition_3&quot;&gt;Twitter&lt;/a&gt;, so you might be seeking some alternative. It’s critical to remember that you &lt;a href=&quot;https://www.jwz.org/blog/2022/11/psa-do-not-use-services-that-hate-the-internet/&quot;&gt;should try to avoid services that hate the Internet&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;programming&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#programming&quot;&gt;&lt;span&gt;Programming&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;just-for-fun-no-really&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#just-for-fun-no-really&quot;&gt;&lt;span&gt;Just for fun. No, really.&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you ever make something just for fun and someone starts criticizing what you did, just remember the site &lt;a href=&quot;https://justforfunnoreally.dev/&quot;&gt;Just for fun. No, really.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Because every so often you do something really just for fun. There’s no purpose, it’s not supposed to be better than something else, it might be even completely useless. It’s made just for fun.&lt;/p&gt;
&lt;h3 id=&quot;finding-your-favorite-programming-font&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#finding-your-favorite-programming-font&quot;&gt;&lt;span&gt;Finding your favorite programming font&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Find your favorite programming font by playing the &lt;a href=&quot;https://www.codingfont.com/&quot;&gt;coding font tournament&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;don-t-rewrite-project-from-scratch&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-11-30-links/#don-t-rewrite-project-from-scratch&quot;&gt;&lt;span&gt;Don’t rewrite project from scratch&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Joel_Spolsky&quot;&gt;Joel Spolsky&lt;/a&gt; has a pretty hard stance on rewriting large codebase from scratch: &lt;a href=&quot;https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/&quot;&gt;Don’t do it&lt;/a&gt;. It’s a waste of time and money, and you might even end up with something that’s worse than what you had before. It’s better to improve upon what you already have.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s important to remember that when you start from scratch there is absolutely no reason to believe that you are going to do a better job than you did the first time. First, you probably don’t even have the same programming team that worked on version one, so you don’t actually have “more experience”. You’re just going to make most of the old mistakes again, and introduce some new problems that weren’t in the original version.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/&quot;&gt;Things you should never do, part I&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
</description>
          <category>digest</category>
          <category>programming</category>
        <pubDate>Wed, 30 Nov 2022 20:28:00 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/2022-11-30-links/</guid>
      </item>
      <item>
        <title>Git tips and tricks</title>
        <link>https://vladimirzdrazil.com/posts/git-tips-tricks/</link>
        <description>&lt;details&gt;
  &lt;summary&gt;Updates&lt;/summary&gt;
  &lt;dl&gt;
    &lt;dt&gt;&lt;time datetime=&quot;2022-11-13&quot;&gt;2022-11-13&lt;/time&gt;&lt;/dt&gt;
    &lt;dd&gt;
      Added &lt;a href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#git-repl&quot;&gt;&lt;code&gt;git repl&lt;/code&gt;&lt;/a&gt; section.
    &lt;/dd&gt;
    &lt;dt&gt;&lt;time datetime=&quot;2023-05-07&quot;&gt;2023-05-07&lt;/time&gt;&lt;/dt&gt;
    &lt;dd&gt;
      This article has been split into multiple posts for easier reading and
      updating. Check out &lt;a href=&quot;https://vladimirzdrazil.com/til/git/&quot;&gt;TIL Git&lt;/a&gt; for the latest tips.
    &lt;/dd&gt;
  &lt;/dl&gt;
&lt;/details&gt;
&lt;p&gt;A collection of Git tips and tricks you might not know.&lt;/p&gt;
&lt;h2 id=&quot;find-the-most-frequently-changed-files&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#find-the-most-frequently-changed-files&quot;&gt;&lt;span&gt;Find the most frequently changed files&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can find the most frequently changed files in the repository with this command:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;format: --name-only &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uniq&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-rn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-10&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;format: --name-only &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uniq&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-rn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-10&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;format: --name-only packages/news &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uniq&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-rn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;path&lt;/code&gt; limits the search to a specific directory, but you can omit it to search the whole repository.&lt;/p&gt;
&lt;p&gt;You can use this list to decide which files to refactor first. For example, imagine you want to move a project from JavaScript to TypeScript. You can find the most changed files and start with them.&lt;/p&gt;
&lt;p&gt;Or imagine you encounter a new codebase. Finding the most frequently changed files can help you figure out, what to focus on first.&lt;/p&gt;
&lt;h2 id=&quot;find-the-most-recent-branches&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#find-the-most-recent-branches&quot;&gt;&lt;span&gt;Find the most recent branches&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The following command will show you the branches sorted by the date of the last commit.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--global&lt;/span&gt; alias.recent &lt;span class=&quot;token string&quot;&gt;&quot;!git for-each-ref refs/heads --sort committerdate --format=&#39;%(HEAD) %(refname:short)&#39;&quot;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; recent&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I sometimes forget the name of the branch I want to switch to, and this command makes finding it easy. But instead of &lt;kbd&gt;git recent&lt;/kbd&gt; I aliased it to &lt;kbd&gt;git brt&lt;/kbd&gt;, because it’s faster to type.&lt;/p&gt;
&lt;h2 id=&quot;reuse-recorded-resolution-of-conflicted-merges&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#reuse-recorded-resolution-of-conflicted-merges&quot;&gt;&lt;span&gt;Reuse recorded resolution of conflicted merges&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Git rerere can automatically resolve merge conflicts you resolved before, but you need to enable it first:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--global&lt;/span&gt; rerere.enabled &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info in &lt;a href=&quot;https://git-scm.com/book/en/v2/Git-Tools-Rerere&quot;&gt;Git rerere&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;avoid-unnecessary-merge-commits-on-pull&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#avoid-unnecessary-merge-commits-on-pull&quot;&gt;&lt;span&gt;Avoid unnecessary merge commits on pull&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you pull a branch, Git will by default create a merge commit. If you don’t want to have a merge commit, you can use the following setting to rebase the local commits instead:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--global&lt;/span&gt; pull.rebase &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As nobody knows your commits yet, nobody will get confused when you rebase them, and it keeps the history clean.&lt;/p&gt;
&lt;p&gt;More info in &lt;a href=&quot;https://git-scm.com/docs/git-config#Documentation/git-config.txt-pullrebase&quot;&gt;Git config &lt;code&gt;pull.rebase&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;setup-git-ssh-signing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#setup-git-ssh-signing&quot;&gt;&lt;span&gt;Setup Git SSH signing&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.34.0.txt&quot;&gt;version 2.34&lt;/a&gt;, Git introduced &lt;a href=&quot;https://github.blog/2021-11-15-highlights-from-git-2-34/#tidbits&quot;&gt;SSH signing&lt;/a&gt;. Git supported GPG signing for a long time, but I found it cumbersome. With SSH signing, you can use your already configured SSH key.&lt;/p&gt;
&lt;p&gt;See how to &lt;a href=&quot;https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification#ssh-commit-signature-verification&quot;&gt;set up Git SSH signing locally and on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;import-configs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#import-configs&quot;&gt;&lt;span&gt;Import configs&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can include other configs in your &lt;code&gt;.gitconfig&lt;/code&gt; file.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--global&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--add&lt;/span&gt; include.path &lt;span class=&quot;token string&quot;&gt;&#39;~/.git-config-work&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info at &lt;a href=&quot;https://git-scm.com/docs/git-config#_includes&quot;&gt;Git config includes documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;use-git-bisect-to-find-buggy-commits&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#use-git-bisect-to-find-buggy-commits&quot;&gt;&lt;span&gt;Use git bisect to find buggy commits&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you have a bug in your code, and you want to find out which commit introduced it, you can use &lt;kbd&gt;git bisect&lt;/kbd&gt;. With it, you will use binary search which is much faster than going through all the commits in a sequence.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; bisect start HEAD abc123 &lt;span class=&quot;token comment&quot;&gt;# HEAD is the buggy commit, abc123 is the good commit without a bug. It can be anywhere from the past.&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; bisect bad &lt;span class=&quot;token comment&quot;&gt;# if Git switched to a commit which is bad/has a bug&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; bisect good &lt;span class=&quot;token comment&quot;&gt;# if commit is good&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; bisect reset &lt;span class=&quot;token comment&quot;&gt;# to abort&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info at &lt;a href=&quot;https://rkoutnik.com/articles/The-gits-guide-to-git-Bisect.html&quot;&gt;The git’s guide to git: Bisect&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;auto-setup-remote-on-push&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#auto-setup-remote-on-push&quot;&gt;&lt;span&gt;Auto setup remote on push&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://lore.kernel.org/git/MEYP282MB35646319926B07F89FBF577DA3819@MEYP282MB3564.AUSP282.PROD.OUTLOOK.COM/T/&quot;&gt;Git version 2.37&lt;/a&gt; introduced a new config option: &lt;code&gt;push.autoSetupRemote&lt;/code&gt;. You can use it to automatically set up a remote when you push. Which means you don’t need &lt;kbd&gt;git push --set-upstream origin my-work&lt;/kbd&gt; or &lt;kbd&gt;git push -u origin my-work&lt;/kbd&gt; anymore.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config &lt;span class=&quot;token parameter variable&quot;&gt;--global&lt;/span&gt; push.autoSetupRemote &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info at &lt;a href=&quot;https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushautoSetupRemote&quot;&gt;Git config &lt;code&gt;push.autoSetupRemote&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;git-repl&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/git-tips-tricks/#git-repl&quot;&gt;&lt;span&gt;Git REPL&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tired of typing &lt;kbd&gt;git&lt;/kbd&gt; when you run git commands? You can install &lt;a href=&quot;https://github.com/tj/git-extras&quot;&gt;git-extras&lt;/a&gt; and use its &lt;a href=&quot;https://github.com/tj/git-extras/blob/master/Commands.md#git-repl&quot;&gt;&lt;kbd&gt;git repl&lt;/kbd&gt;&lt;/a&gt; to run multiple commands in a row.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; repl
status
&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Add feed&quot;&lt;/span&gt;
push
&lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</description>
          <category>programming</category>
        <pubDate>Sat, 05 Nov 2022 05:53:47 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/git-tips-tricks/</guid>
      </item>
      <item>
        <title>Links from the past few weeks (Oct 30, 2022)</title>
        <link>https://vladimirzdrazil.com/posts/2022-10-30-links/</link>
        <description>&lt;p&gt;List of links, articles, and other resources you might find interesting from the past few weeks.&lt;/p&gt;
&lt;h2 id=&quot;javascript&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#javascript&quot;&gt;&lt;span&gt;JavaScript&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;ecmascript-proposal-decorators&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#ecmascript-proposal-decorators&quot;&gt;&lt;span&gt;ECMAScript proposal: Decorators&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JavaScript will soon have a new feature: decorators. The committee moved the &lt;a href=&quot;https://github.com/tc39/proposal-decorators&quot;&gt;proposal&lt;/a&gt; to &lt;a href=&quot;https://tc39.es/process-document/&quot;&gt;stage 3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The proposal defines &lt;dfn&gt;decorators&lt;/dfn&gt; as &lt;q&gt;functions called on classes, class elements, or other JavaScript syntax forms during definition. … Decorators let you metaprogram and add functionality to a value, without fundamentally changing its external behavior.&lt;/q&gt; &lt;cite&gt;&lt;a href=&quot;https://github.com/tc39/proposal-decorators&quot;&gt;Decorators for ES6 classes&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;What does it mean?&lt;/p&gt;
&lt;p&gt;One example that made it much clearer for me was the one for &lt;a href=&quot;https://github.com/tc39/proposal-decorators#class-methods&quot;&gt;class methods&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; data-codeblock=&quot;true&quot; data-language=&quot;js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;logged&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; kind&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;kind &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;starting &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; with arguments &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;, &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;ending &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ret&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  @logged
  &lt;span class=&quot;token function&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// starting m with arguments 1&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// ending m&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This example roughly “desugars“ to:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; data-codeblock=&quot;true&quot; data-language=&quot;js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;logged&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;https://github.com/tc39/proposal-decorators&quot;&gt;Decorators for ES6 classes&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;h3 id=&quot;ecmascript-proposal-type-annotations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#ecmascript-proposal-type-annotations&quot;&gt;&lt;span&gt;ECMAScript proposal: Type annotations&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Likewise, somebody prepared an interesting proposal for &lt;a href=&quot;https://github.com/tc39/proposal-type-annotations&quot;&gt;type annotations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If realized, you could &lt;q&gt;run programs written in TypeScript, Flow, and other static typing supersets of JavaScript with no need for transpilation.&lt;/q&gt; &lt;cite&gt;&lt;a href=&quot;https://github.com/tc39/proposal-type-annotations&quot;&gt;ECMAScript proposal: Type annotations&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;h2 id=&quot;html&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#html&quot;&gt;&lt;span&gt;HTML&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;description-list-versus-unordered-list-with-headings&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#description-list-versus-unordered-list-with-headings&quot;&gt;&lt;span&gt;Description list versus unordered list with headings&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Turns out, HTML supports &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl&quot;&gt;description lists&lt;/a&gt; (otherwise called definition lists), and you should sometimes use them instead of unordered lists. They’re more suitable for things like listing post titles and their descriptions.&lt;/p&gt;
&lt;p&gt;For example, you shouldn’t write this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; data-codeblock=&quot;true&quot; data-language=&quot;html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Posts&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/posts/article-1/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Article 1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This summarizes article 1.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/posts/article-2/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Article 2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This summarizes article 2.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead, do this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; data-codeblock=&quot;true&quot; data-language=&quot;html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Posts&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/posts/article-1/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Article 1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This summarizes article 1.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/posts/article-2/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Article 2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This summarizes article 2.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To understand why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/utilizing-the-underused-but-semantically-awesome-definition-list/&quot;&gt;Utilizing the underused (but semantically awesome) definition list&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/a/13903283&quot;&gt;Definition list vs. unordered list with headings — which makes more semantic sense?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;whatwg-or-w3c&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#whatwg-or-w3c&quot;&gt;&lt;span&gt;WHATWG or W3C?&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you search through HTML specifications, you might stumble upon two organizations: &lt;a href=&quot;https://en.wikipedia.org/wiki/WHATWG&quot;&gt;WHATWG&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/World_Wide_Web_Consortium&quot;&gt;W3C&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Which one should you listen to?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WHATWG&lt;/strong&gt;. WHATWG describes the browser implementation. W3C was more theoretical.&lt;/p&gt;
&lt;p&gt;Furthermore, W3C and WHATWG &lt;a href=&quot;https://www.w3.org/blog/news/archives/7753&quot;&gt;signed an agreement to work together on a single version of HTML and DOM&lt;/a&gt;, agreeing that WHATWG will maintain the HTML and DOM Living Standards.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://groups.google.com/g/mozilla.dev.platform/c/BnY1261cNJo/m/MdkaT_EX6M0J&quot;&gt;David Baron from Mozilla also says to prefer WHATWG&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When the W3C’s and WHATWG’s HTML specifications differ, we tend to follow the WHATWG one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;before-the-srcset-there-was-a-dynamic-image-resizing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#before-the-srcset-there-was-a-dynamic-image-resizing&quot;&gt;&lt;span&gt;Before the srcset, there was a dynamic image resizing&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can serve responsive images using the &lt;code&gt;srcset&lt;/code&gt; attribute. But what were people doing before?&lt;/p&gt;
&lt;p&gt;You can read up on two solutions I’ve found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sneak.co.nz/projects/img-resizing/&quot;&gt;Dynamic image resizing with PHP and mod-rewrite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://adaptive-images.com/&quot;&gt;Adaptive images&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;css&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#css&quot;&gt;&lt;span&gt;CSS&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;what-css-units-to-prefer&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#what-css-units-to-prefer&quot;&gt;&lt;span&gt;What CSS units to prefer&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It depends on what you want to do. See an excellent summary from &lt;a href=&quot;https://old.reddit.com/r/Frontend/comments/wmuqk8/tips_for_css_units_what_are_your_go_to_units_in/ik4t8cp/&quot;&gt;Reddit user Tontonsb&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Furthermore, to go into more detail explaining why you shouldn’t settle with &lt;code&gt;px&lt;/code&gt; unit, check out &lt;a href=&quot;https://www.joshwcomeau.com/css/surprising-truth-about-pixels-and-accessibility/&quot;&gt;The surprising truth about pixels and accessibility&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;css-hyphenation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#css-hyphenation&quot;&gt;&lt;span&gt;CSS hyphenation&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Did you know that websites can use hyphens? Find out more in &lt;a href=&quot;https://clagnut.com/blog/2395&quot;&gt;All you need to know about hyphenation in CSS&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;system-font-stack&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#system-font-stack&quot;&gt;&lt;span&gt;System font stack&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You don’t always have to bother with loading custom fonts. A lot of people find regular system fonts great, and the text will still look beautiful.&lt;/p&gt;
&lt;p&gt;For instance, see a perfect list of system fonts: &lt;a href=&quot;https://systemfontstack.com/&quot;&gt;System font stack&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;empathetic-animations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#empathetic-animations&quot;&gt;&lt;span&gt;Empathetic animations&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Don’t do animations because you can. Use them to help the users understand what’s going on. More details in &lt;a href=&quot;https://css-tricks.com/empathetic-animation/&quot;&gt;Empathetic animations&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;security&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#security&quot;&gt;&lt;span&gt;Security&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;make-sure-you-send-correct-security-headers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/2022-10-30-links/#make-sure-you-send-correct-security-headers&quot;&gt;&lt;span&gt;Make sure you send correct security headers&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A lot of websites have improperly set security headers, or they didn’t set them at all. Test your site with &lt;a href=&quot;https://observatory.mozilla.org/&quot;&gt;observatory.mozilla.org&lt;/a&gt; to find the possible deficiencies. Another excellent alternative is &lt;a href=&quot;https://securityheaders.com/&quot;&gt;securityheaders.com&lt;/a&gt;.&lt;/p&gt;
</description>
          <category>digest</category>
          <category>programming</category>
        <pubDate>Sun, 30 Oct 2022 21:02:17 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/2022-10-30-links/</guid>
      </item>
      <item>
        <title>Fuzzy search through files in Visual Studio Code</title>
        <link>https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/</link>
        <description>&lt;p&gt;Visual Studio Code already supports searching across all the project files. But let’s make searching inside them even more ergonomic and easier to use. We’ll do it by taking an inspiration in the behavior of the command &lt;kbd&gt;:RG&lt;/kbd&gt; from Vim plugin &lt;a href=&quot;https://github.com/junegunn/fzf.vim&quot;&gt;junegunn/fzf.vim&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-goal&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#the-goal&quot;&gt;&lt;span&gt;The goal&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Check out the Find in files in Visual Studio Code:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-imgSmall&quot;&gt;&lt;img alt=&quot;Screenshot of the Find in files in Visual Studio Code&quot; class=&quot;MarkdownImage&quot; sizes=&quot;(min-width: 648px) 648px, 96vw&quot; srcset=&quot;https://vladimirzdrazil.com/media/find-in-files-480.jpg 480w, https://vladimirzdrazil.com/media/find-in-files-648.jpg 648w, https://vladimirzdrazil.com/media/find-in-files.jpg 736w&quot; src=&quot;https://vladimirzdrazil.com/media/find-in-files.jpg&quot; title=&quot;Find in files in Visual Studio Code&quot; width=&quot;300&quot; height=&quot;355&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As an alternative, we’ll create a custom shell command &lt;kbd&gt;rgf&lt;/kbd&gt; for fuzzy searching. After we select the result, command &lt;kbd&gt;rgf&lt;/kbd&gt; will open the file in Visual Studio Code on the correct line. Then we’ll simplify running &lt;kbd&gt;rgf&lt;/kbd&gt; from Visual Studio Code. We’ll build this new, alternative, flow:&lt;/p&gt;
&lt;figure&gt;
  &lt;video controls=&quot;&quot; muted=&quot;&quot; class=&quot;u-fullWidth&quot;&gt;
    &lt;source src=&quot;https://vladimirzdrazil.com/media/fuzzy-searching-in-visual-studio-code.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;Fuzzy searching in Visual Studio Code&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;prerequisites&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#prerequisites&quot;&gt;&lt;span&gt;Prerequisites&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, make sure you have these installed and set up so all works as expected:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unix system, tested on macOS.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;fzf&lt;/a&gt; &amp;gt;= 0.30.0&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;ripgrep&lt;/a&gt; &amp;gt;= 13.0.0&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sharkdp/bat&quot;&gt;bat&lt;/a&gt; &amp;gt;= 0.20.0&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt; &amp;gt;= 1.66.2&lt;/li&gt;
&lt;li&gt;Extension &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=edonet.vscode-command-runner&quot;&gt;Command Runner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You can open Visual Studio Code from the command line with the command &lt;a href=&quot;https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line&quot;&gt;&lt;code&gt;code&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/bash/&quot;&gt;Bash&lt;/a&gt; &amp;gt;= 5.1.16&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;recommended-settings-for-fzf&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#recommended-settings-for-fzf&quot;&gt;&lt;span&gt;Recommended settings for fzf&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now, save this shell environment variable. Probably to &lt;code&gt;$HOME/.bashrc&lt;/code&gt;, but it depends on your shell and your setup:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FZF_DEFAULT_OPTS&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;--history=&lt;span class=&quot;token environment constant&quot;&gt;$HOME&lt;/span&gt;/.fzf-history&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This setting lets &lt;code&gt;fzf&lt;/code&gt; load search history from the specified file and update the file on completion. You can then use &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;N&lt;/kbd&gt; and &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;P&lt;/kbd&gt; to go back and forward through search history and &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;H&lt;/kbd&gt; and &lt;kbd&gt;Ctrl&lt;/kbd&gt;+&lt;kbd&gt;J&lt;/kbd&gt; or arrow keys &lt;kbd&gt;↑&lt;/kbd&gt; and &lt;kbd&gt;↓&lt;/kbd&gt; to select the next and previous result.&lt;/p&gt;
&lt;h3 id=&quot;install-the-script-for-fuzzy-searching&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#install-the-script-for-fuzzy-searching&quot;&gt;&lt;span&gt;Install the script for fuzzy searching&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Similarly, save the following script to your &lt;code&gt;$PATH&lt;/code&gt; and make it executable, so you can run it in your shell:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Interactive search.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# go to provided folder or noop&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FZF_DEFAULT_COMMAND&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;rg --column --line-number --no-heading --color=always -- &#39;&#39;&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;selected&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;
  fzf &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    &lt;span class=&quot;token parameter variable&quot;&gt;--ansi&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    &lt;span class=&quot;token parameter variable&quot;&gt;--delimiter&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    &lt;span class=&quot;token parameter variable&quot;&gt;--bind&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;f12:execute-silent:(code -g &lt;span class=&quot;token environment constant&quot;&gt;$PWD&lt;/span&gt;/{1..3})&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    --preview-window &lt;span class=&quot;token string&quot;&gt;&#39;up,60%,border-bottom,+{2}+3/3,~3&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    &lt;span class=&quot;token parameter variable&quot;&gt;--preview&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;bat -f --highlight-line={2} {1}&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cut&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;:&quot;&lt;/span&gt; -f1,2,3
&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$selected&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; code &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token environment constant&quot;&gt;$PWD&lt;/span&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$selected&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, on macOS, you can copy the script, then run this in your terminal:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; data-codeblock=&quot;true&quot; data-language=&quot;bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pbpaste &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ~/bin/rgf &lt;span class=&quot;token comment&quot;&gt;# ~/bin is in my $PATH&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x ~/bin/rgf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Having done all this, you can now use &lt;kbd&gt;rgf&lt;/kbd&gt; to fuzzy search in your shell. Try it!&lt;/p&gt;
&lt;h3 id=&quot;what-does-the-script-do&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#what-does-the-script-do&quot;&gt;&lt;span&gt;What does the script do&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The script combines &lt;kbd&gt;fzf&lt;/kbd&gt;, &lt;kbd&gt;rg&lt;/kbd&gt;, &lt;kbd&gt;bat&lt;/kbd&gt;, and &lt;kbd&gt;code&lt;/kbd&gt; to fuzzy search through your code and to open the result in Visual Studio Code. I based it on &lt;a href=&quot;https://github.com/junegunn/fzf/blob/master/ADVANCED.md#using-fzf-as-interative-ripgrep-launcher&quot;&gt;Using fzf as interactive ripgrep launcher&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Compared to the original, the script behaves like the &lt;kbd&gt;:RG&lt;/kbd&gt; command in &lt;a href=&quot;https://github.com/junegunn/fzf.vim&quot;&gt;junegunn/fzf.vim&lt;/a&gt;. It uses &lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;fzf&lt;/a&gt; fuzzy searching right away, and it doesn’t pre-filter the results with &lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;ripgrep&lt;/a&gt;. The script uses &lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;ripgrep&lt;/a&gt; to list the lines in the project, with path, filename, and line number.&lt;/p&gt;
&lt;h3 id=&quot;install-fuzzy-search-command-to-visual-studio-code&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#install-fuzzy-search-command-to-visual-studio-code&quot;&gt;&lt;span&gt;Install fuzzy search command to Visual Studio Code&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Next in order, simplify running &lt;kbd&gt;rgf&lt;/kbd&gt; from Visual Studio Code.&lt;/p&gt;
&lt;p&gt;Add this to your Visual Studio Code &lt;a href=&quot;https://code.visualstudio.com/docs/getstarted/settings#_settingsjson&quot;&gt;settings.json&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; data-codeblock=&quot;true&quot; data-language=&quot;json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;command-runner.commands&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;rgf&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rgf; exit&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After doing this, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Press &lt;kbd&gt;Cmd&lt;/kbd&gt;+&lt;kbd&gt;Shift&lt;/kbd&gt;+&lt;kbd&gt;P&lt;/kbd&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;kbd&gt;&lt;samp&gt;Run Command&lt;/samp&gt;&lt;/kbd&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;kbd&gt;&lt;samp&gt;rgf&lt;/samp&gt;&lt;/kbd&gt;.&lt;/li&gt;
&lt;li&gt;Now you can fuzzy-search. Press &lt;kbd&gt;Enter&lt;/kbd&gt; to open the search result and close the window. Or press &lt;kbd&gt;F12&lt;/kbd&gt;. This won’t close the window, making it possible to continue with your search uninterrupted.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;add-fuzzy-search-shortcut&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#add-fuzzy-search-shortcut&quot;&gt;&lt;span&gt;Add fuzzy search shortcut&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Add this to your Visual Studio Code &lt;a href=&quot;https://code.visualstudio.com/docs/getstarted/keybindings#_advanced-customization&quot;&gt;keybindings.json&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; data-codeblock=&quot;true&quot; data-language=&quot;json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;rgf&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;command-runner.run&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cmd+k .&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;new-workflow&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#new-workflow&quot;&gt;&lt;span&gt;New workflow&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After doing this, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Press &lt;kbd&gt;Cmd&lt;/kbd&gt;+&lt;kbd&gt;K&lt;/kbd&gt; and then &lt;kbd&gt;.&lt;/kbd&gt; to start fuzzy searching.&lt;/li&gt;
&lt;li&gt;Press &lt;kbd&gt;Enter&lt;/kbd&gt; to open the search result and close the search window. Or press &lt;kbd&gt;F12&lt;/kbd&gt;. This won’t close the window. Instead, it will open the search result, and you can continue with your search. This way, you can open multiple files without canceling the search.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
  &lt;video controls=&quot;&quot; muted=&quot;&quot; class=&quot;u-fullWidth&quot;&gt;
    &lt;source src=&quot;https://vladimirzdrazil.com/media/fuzzy-searching-in-visual-studio-code.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;Fuzzy searching in Visual Studio Code&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;how-does-this-differ-from-the-default&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#how-does-this-differ-from-the-default&quot;&gt;&lt;span&gt;How does this differ from the default&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;fuzzy-search&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#fuzzy-search&quot;&gt;&lt;span&gt;Fuzzy search&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I want to avoid writing complicated regular expressions. I prefer not to write out the full names. If I’m looking for the function &lt;var&gt;getSelectedAddressFormValues&lt;/var&gt;, I should be able to find it with the search term &lt;kbd&gt;getseladd&lt;/kbd&gt;.&lt;/p&gt;
&lt;p&gt;In comparison with Find in files, you don’t need regex.&lt;/p&gt;
&lt;h3 id=&quot;one-field-nothing-more&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#one-field-nothing-more&quot;&gt;&lt;span&gt;One field, nothing more&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With Find in files, you have several input fields and extra toggles which you need to keep checking and toggling either with a mouse or complicated shortcuts.&lt;/p&gt;
&lt;p&gt;Instead, I want to have one input field where the search term affects almost everything. See how &lt;a href=&quot;https://github.com/junegunn/fzf#search-syntax&quot;&gt;fzf does it&lt;/a&gt;. Do you want to use the exact match? &lt;kbd&gt;&#39;wild&lt;/kbd&gt; Do you want to use an inverse match? &lt;kbd&gt;!wild&lt;/kbd&gt;&lt;/p&gt;
&lt;p&gt;Everything is part of the search term.&lt;/p&gt;
&lt;h3 id=&quot;limiting-the-files-included-in-the-search-is-easier&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#limiting-the-files-included-in-the-search-is-easier&quot;&gt;&lt;span&gt;Limiting the files included in the search is easier&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With Find in files, you can limit the files included in your search in at least two ways, but I find neither of them ergonomic enough:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write out the exact path of the folder, for example, &lt;kbd&gt;./packages/my-package/web-app&lt;/kbd&gt;, to a separate field.&lt;/li&gt;
&lt;li&gt;Select a folder in the folder list and then run the &lt;kbd&gt;Find in folder&lt;/kbd&gt; command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why do you need to write out the whole path? You can use &lt;a href=&quot;https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options&quot;&gt;glob syntax&lt;/a&gt;. But you still have to figure out where to put them.&lt;/p&gt;
&lt;p&gt;By comparison, what if you could enter the folder/file name right inside the same input field as the search term and use fuzzy matching? You’d find a lot of things faster.&lt;/p&gt;
&lt;h4 id=&quot;example&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#example&quot;&gt;&lt;span&gt;Example&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Take the case of finding the word &lt;code&gt;wild&lt;/code&gt; inside the folder &lt;code&gt;web-app&lt;/code&gt;. The folder &lt;code&gt;web-app&lt;/code&gt; is located in &lt;code&gt;./packages/web-app&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I’d like to use this search term:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; data-codeblock=&quot;true&quot; data-language=&quot;text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;web-app wild&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or even this should work:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; data-codeblock=&quot;true&quot; data-language=&quot;text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;weba wild # fuzzy matching&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;complete-search-history&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;HeadingLink&quot; href=&quot;https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/#complete-search-history&quot;&gt;&lt;span&gt;Complete search history&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Lastly, with Find in files, you can go through previous searches but Visual Studio Code doesn’t remember the switches and files to include field. I’d prefer to have access to the complete search history, with the toggles and other fields as part of it.&lt;/p&gt;
</description>
          <category>programming</category>
        <pubDate>Tue, 19 Apr 2022 05:02:12 +0000</pubDate>

        <dc:creator>Vladimír Zdražil</dc:creator>
        <guid>https://vladimirzdrazil.com/posts/fuzzy-search-through-files-in-visual-studio-code/</guid>
      </item>
  </channel>
</rss>