<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Jason's Blog</title><link>/</link><description>Recent content on Jason's Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>Rametta</copyright><lastBuildDate>Fri, 01 Jan 2100 00:00:00 +0000</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml"/><item><title>2025 Year in Review</title><link>/posts/2025-year-in-review/</link><pubDate>Wed, 31 Dec 2025 09:35:00 +0000</pubDate><guid>/posts/2025-year-in-review/</guid><description>&lt;p&gt;This is the 4th edition of my annual review post!&lt;/p&gt;
&lt;p&gt;Overall, 2025 was a great year. The first half of the year I was still working on making game development easier for indie developers at Void - Unfortunately Void shut down at the end of May due to funding, but it was one of my favourite jobs I ever had, and I will miss the exciting work we were doing on creating our game engine, editor, and SDKs.&lt;/p&gt;</description><content>&lt;p&gt;This is the 4th edition of my annual review post!&lt;/p&gt;
&lt;p&gt;Overall, 2025 was a great year. The first half of the year I was still working on making game development easier for indie developers at Void - Unfortunately Void shut down at the end of May due to funding, but it was one of my favourite jobs I ever had, and I will miss the exciting work we were doing on creating our game engine, editor, and SDKs.&lt;/p&gt;
&lt;p&gt;My role at Void was specifically around SDK&amp;rsquo;s and designing the &lt;a href="https://github.com/vague-archive/fiasco"&gt;TypeScript SDK&lt;/a&gt; for interacting with our new Rust ECS game engine - it involved a lot of work around the TypeScript Compiler API to achieve an SDK that was enjoyable to use. Most of the work I was doing is now open source and available on Github &lt;a href="https://github.com/vague-archive"&gt;here&lt;/a&gt;. I also created many prototypes with Rust interop in our SDK&amp;rsquo;s with other languages such as a &lt;a href="https://github.com/vague-archive/python-sdk"&gt;Python SDK&lt;/a&gt; that leveraged Cython to compile Python directly to C, a &lt;a href="https://github.com/vague-archive/CS_SDK"&gt;C# SDK&lt;/a&gt; that compiled natively using AOT, and a pure &lt;a href="https://github.com/vague-archive/sample-c"&gt;C SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Along with creating SDK&amp;rsquo;s, I also worked on some unique projects at Void, such as integrating the &lt;a href="https://deno.com"&gt;Deno JS&lt;/a&gt; runtime into our &lt;a href="https://github.com/vague-archive/engine"&gt;Rust game engine&lt;/a&gt; so that our engine can execute and communicate with the game developer&amp;rsquo;s code - this was challenging but I learned a lot about the inner workings of the V8 engine.&lt;/p&gt;
&lt;p&gt;After Void, I took some time off while searching for my next role. A few interviews later and I landed at Zapier in the AI Orchestration zone working on &lt;a href="https://zapier.com/agents"&gt;Agents&lt;/a&gt; 🎉. AI is clearly changing the way the world works, so I&amp;rsquo;m excited to contribute to making AI Agents better and more useful for everyone.&lt;/p&gt;
&lt;p&gt;Aside from work-related topics, I&amp;rsquo;m happy that during my time off this year I got to play a lot of golf and even broke 100 for the first time. I look forward to golfing more next summer!&lt;/p&gt;
&lt;p&gt;For 2026, I&amp;rsquo;m looking forward to improving AI Agents at Zapier by helping make them more deterministic and more reliable. I want to continue playing golf, padel, magic the gathering, and hopefully reach 50 donations of &lt;a href="https://www.hemaquebec.ca/en/plasma-donation"&gt;plasma&lt;/a&gt; at HemaQuebec.&lt;/p&gt;
&lt;p&gt;Cheers 🥂&lt;/p&gt;</content></item><item><title>2024 Year in Review</title><link>/posts/2024-year-in-review/</link><pubDate>Tue, 31 Dec 2024 17:43:46 +0000</pubDate><guid>/posts/2024-year-in-review/</guid><description>&lt;p&gt;This is my 3rd annual yearly review post!&lt;/p&gt;
&lt;p&gt;2024 was a somewhat uneventful year - not much to highlight, but also nothing to complain about either.&lt;/p&gt;
&lt;p&gt;In 2023, one of my goals was to finally give a talk at a tech conference, and I managed to do it! I gave a talk at Future Frontend in Finland about some of my observations concerning frontend, and how it can be improved. The &lt;a href="/posts/reliable-i-o-with-the-typescript-compiler-api-video/"&gt;talk&lt;/a&gt; went great and I&amp;rsquo;m super happy with the result!&lt;/p&gt;</description><content>&lt;p&gt;This is my 3rd annual yearly review post!&lt;/p&gt;
&lt;p&gt;2024 was a somewhat uneventful year - not much to highlight, but also nothing to complain about either.&lt;/p&gt;
&lt;p&gt;In 2023, one of my goals was to finally give a talk at a tech conference, and I managed to do it! I gave a talk at Future Frontend in Finland about some of my observations concerning frontend, and how it can be improved. The &lt;a href="/posts/reliable-i-o-with-the-typescript-compiler-api-video/"&gt;talk&lt;/a&gt; went great and I&amp;rsquo;m super happy with the result!&lt;/p&gt;
&lt;p&gt;My other big goal from last year was to move the needle in the game development space. That goal is still a work-in-progress but making great strides at the company I&amp;rsquo;ve been working at since last January - &lt;a href="https://void.dev"&gt;Void&lt;/a&gt;. Hopefully in 2025 we will unveil all the hard work we&amp;rsquo;ve been putting into making game dev a more enjoyable experience.&lt;/p&gt;
&lt;p&gt;For 2025, my goals stay pretty much the same, with the addition of strengthening my online security and privacy. I already have a very strong online security practice (details in my november post - &lt;a href="/posts/project-encrypt/"&gt;project encrypt&lt;/a&gt;) - but I want to go even further by setting up redundancy and exploring more ways to stay secure online and offline.&lt;/p&gt;</content></item><item><title>Project Encrypt</title><link>/posts/project-encrypt/</link><pubDate>Wed, 27 Nov 2024 00:00:00 +0000</pubDate><guid>/posts/project-encrypt/</guid><description>&lt;p&gt;Project encrypt is an ongoing personal hobby of mine to fully encrypt every activity I do online. This post will cover almost everything I do to secure my privacy and data online.&lt;/p&gt;
&lt;p&gt;I will go over everything in detail but the summary is that this project includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passkeys for passwordless login and 2FA.&lt;/li&gt;
&lt;li&gt;Email aliases for every account.&lt;/li&gt;
&lt;li&gt;Encrypting email, storage, calendar, passwords &amp;amp; more.&lt;/li&gt;
&lt;li&gt;Generating credit card number cvv&amp;rsquo;s for every purchase.&lt;/li&gt;
&lt;li&gt;Secure messaging &amp;amp; contact key verification.&lt;/li&gt;
&lt;li&gt;App permissions&lt;/li&gt;
&lt;li&gt;Emergency sheets &amp;amp; backups.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you follow this project, or any individual steps, your online data will definitely be safer and more secure than before.&lt;/p&gt;</description><content>&lt;p&gt;Project encrypt is an ongoing personal hobby of mine to fully encrypt every activity I do online. This post will cover almost everything I do to secure my privacy and data online.&lt;/p&gt;
&lt;p&gt;I will go over everything in detail but the summary is that this project includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passkeys for passwordless login and 2FA.&lt;/li&gt;
&lt;li&gt;Email aliases for every account.&lt;/li&gt;
&lt;li&gt;Encrypting email, storage, calendar, passwords &amp;amp; more.&lt;/li&gt;
&lt;li&gt;Generating credit card number cvv&amp;rsquo;s for every purchase.&lt;/li&gt;
&lt;li&gt;Secure messaging &amp;amp; contact key verification.&lt;/li&gt;
&lt;li&gt;App permissions&lt;/li&gt;
&lt;li&gt;Emergency sheets &amp;amp; backups.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you follow this project, or any individual steps, your online data will definitely be safer and more secure than before.&lt;/p&gt;
&lt;h2 id="passkeys-security-keys--2famfa"&gt;Passkeys, Security Keys &amp;amp; 2FA/MFA&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re not aware of what passkeys are yet, &lt;code&gt;then let this be the one important takeaway from this article.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Passkeys are a way to log in to your accounts&lt;/strong&gt; without having to remember a password, and sometimes in the case of passwordless then you don&amp;rsquo;t even need to remember your username. The passkey is generated and stored securely on your device or inside your password manager and can&amp;rsquo;t be accessed easily without device access.&lt;/p&gt;
&lt;p&gt;Passkeys are not only more secure but also more convenient than passwords because they can be accessed via biometrics (FaceID/TouchID) or a master password.&lt;/p&gt;
&lt;p&gt;To start using them, navigate to the security settings for any product you use and check if they support them. This is what the Google security settings look like for passkey registration:&lt;/p&gt;
&lt;p&gt;&lt;img src="/google-passkeys.png" alt="google passkey settings screenshot"&gt;&lt;/p&gt;
&lt;p&gt;When registering a passkey, you can choose where to save it, either in a password manager or using a physical security key like a &lt;a href="https://www.yubico.com/products/yubikey-5-overview/"&gt;Yubi key&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For some more information on passkeys and security keys, here are some recommended links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.passkeycentral.org/introduction-to-passkeys/how-passkeys-work"&gt;What are passkeys?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.1password.com/hardware-security-keys-explained/"&gt;Physical Security Keys Explained&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One other great advantage of passkeys is that they can be used for two-factor authentication (2FA), so not needing to copy/paste codes from an authenticator app or email/text message is a huge convenience with no security downside.&lt;/p&gt;
&lt;p&gt;Not every product or service supports 2FA or passkeys, and the ones that do will support it to varying degrees. For example, some sites may have 2FA but only for text message codes and email codes (looking at you Banks and Government services&amp;hellip;), which is less secure than things like an Authenticator app or passkeys.&lt;/p&gt;
&lt;p&gt;Whenever creating a new account for any product or service, I always enable 2FA and register multiple devices. My preferences are (in order):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Passkeys with physical security keys - (Yubi Key / Titan Key)&lt;/li&gt;
&lt;li&gt;Passkeys saved in a password manager&lt;/li&gt;
&lt;li&gt;Authenticator App&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;Text Message / Phone Call&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I usually register &lt;strong&gt;two security keys&lt;/strong&gt; and one passkey in my password manager. Prefer to use passkeys if supported, if you&amp;rsquo;re in the Apple ecosystem then their built-in password manager has support for them already. Ditto for Android. If passkeys are still confusing, then opt to use an authenticator app (&lt;a href="https://www.keepersecurity.com/blog/2023/07/20/what-are-authenticator-apps-and-how-do-they-work/"&gt;How authenticator apps work&lt;/a&gt;) like &lt;a href="https://ente.io/auth/"&gt;Ente&lt;/a&gt; for 2FA codes. The app shows codes rotating over time, and you must copy/paste them into the app during login.&lt;/p&gt;
&lt;p&gt;Text message 2FA is by far the weakest form of 2FA, below is a good video about how easy it is for bad actors to intercept phone calls and text messages without you knowing it.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/wVyu7NB7W6Y?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="email-aliases"&gt;Email Aliases&lt;/h2&gt;
&lt;p&gt;The idea of email aliases is to have a different email address for every online account.&lt;/p&gt;
&lt;p&gt;This means having one email for something like Twitter and a different email for Instagram. There are many advantages to doing this, one benefit is spam management - if you start receiving spam to one email then you can just deactivate it.&lt;/p&gt;
&lt;p&gt;It also allows you to centralize the forwarding process, so if one day you are forwarding all emails to a master address like &lt;code&gt;name@domain.com&lt;/code&gt; and you would like to switch all your 150 accounts to a different address, then it&amp;rsquo;s as easy as switching in one place instead of inside all 150 accounts.&lt;/p&gt;
&lt;p&gt;Apple supports aliases with their &amp;ldquo;Hide my email&amp;rdquo; feature in iCloud to generate email addresses easily or with &amp;ldquo;Sign in with Apple&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img src="/icloud-hide-email.png" alt="iclouds hide my email interface in settings"&gt;&lt;/p&gt;
&lt;p&gt;I used Apple&amp;rsquo;s for a while and now use SimpleLogin for aliases.&lt;/p&gt;
&lt;p&gt;Another benefit of aliases is that it keeps your master email unknown to anybody. This allows you to easily control who has access to contacting you. Nobody will know your real email, only your aliases, and you can easily deactivate an alias if someone uses it without permission.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Secure aliases like Apple&amp;rsquo;s or Proton&amp;rsquo;s are different than ones that services like Gmail provide with the &lt;code&gt;+&lt;/code&gt; trick. The &lt;code&gt;+&lt;/code&gt; trick does not hide your original email, and anyone who knows that will have access to messaging you directly to your original email.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="encrypted-email-storage-calendar--passwords"&gt;Encrypted email, storage, calendar &amp;amp; passwords.&lt;/h2&gt;
&lt;p&gt;This section is dedicated to &lt;a href="https://proton.me"&gt;Proton&lt;/a&gt; - proton is a product suite that provides encryption for various tools and has replacements for things like email, storage (like Google Drive), calendars, VPN&amp;rsquo;s, wallets, and passwords, but all private and end-to-end encrypted (E2EE).&lt;/p&gt;
&lt;p&gt;I have all my email aliases forwarded into my Proton mail account, I use Proton Storage for storing encrypted files, Proton Calendar for my calendar needs, and Proton Pass for my password manager which includes authenticator codes, passkeys, and email aliases. This suite replaces my need for similar Google products that are not encrypted.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in trying out Proton, I highly recommend it, and I have a referral code: &lt;a href="https://pr.tn/ref/MQ4N9PEJTH10"&gt;https://pr.tn/ref/MQ4N9PEJTH10&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you would like to send me an E2EE email, please check out my &lt;a href="/contact/"&gt;contact&lt;/a&gt; page for my public PGP encryption key.&lt;/p&gt;
&lt;h2 id="credit-cards"&gt;Credit Cards&lt;/h2&gt;
&lt;p&gt;As often as possible I will use Apple Pay to pay with my credit card as Apple automatically generates new CVV&amp;rsquo;s with every purchase, masking your real CVV - this prevents vendors from stealing your full credit card information, as the generated number is only valid for that one time purchase.&lt;/p&gt;
&lt;p&gt;Also, I use Wise to generate virtual prepaid credit cards when I really don&amp;rsquo;t trust the company I&amp;rsquo;m purchasing from. This protects my real CC number and if the prepaid card number is stolen then there will be no funds on it besides what I originally needed it for.&lt;/p&gt;
&lt;h2 id="messaging--contact-key-verification"&gt;Messaging &amp;amp; Contact Key Verification&lt;/h2&gt;
&lt;p&gt;Messaging with friends and family is usually done via iMessage, and sometimes with &lt;a href="https://signal.org"&gt;Signal&lt;/a&gt; when my contacts have it installed. Signal is a true end-to-end encrypted chat - it has no ads, no tracking and doesn&amp;rsquo;t gather metadata like other encrypted chats such as WhatsApp.&lt;/p&gt;
&lt;p&gt;Preferably I would use Signal all the time, but not everyone understands the benefits yet - it is up to us to spread the word about Signal to friends who have not heard about it yet.&lt;/p&gt;
&lt;p&gt;For iMessage I have enabled and set up Contact Key Verification with a few contacts to verify devices, this provides some extra security around account takeovers and you will be warned if a message is coming from an unverified device. &lt;em&gt;But&lt;/em&gt;, it is a slow and manual process to verify each individual contact, and trying to explain to everyone the benefits of contact key verification is really difficult.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://security.apple.com/blog/imessage-contact-key-verification/"&gt;Details about Contact Key Verification from Apple Security Engineering&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is my public verification code:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;APKTIDxRWrX5TLPlHGKpt7vDntZ832yLS0hNee8bVc3Fk0MDWjnw
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;iMessage is not perfect, but it seems to be the lesser of evils compared to services like WhatsApp, FB Messenger or Telegram which claim to be E2EE but are tracking a lot of extra metadata about you.&lt;/p&gt;
&lt;h2 id="app-permissions"&gt;App Permissions&lt;/h2&gt;
&lt;p&gt;On the iPhone&amp;rsquo;s AppStore, there is a little known section at the bottom of every app that lists all the data the app has access to and links to you. I always try to avoid apps that grant themselves access to too much information.&lt;/p&gt;
&lt;p&gt;Check out this comparison between what TikTok has access to, vs the Standard Notes app.&lt;/p&gt;
&lt;img style="max-height: 600px" alt="iOS App Store Standard Notes Permissions &amp; Data linked to you" src="/tt-sn-permissions.jpg" /&gt;
&lt;h2 id="emergency-sheet--backups"&gt;Emergency Sheet &amp;amp; Backups&lt;/h2&gt;
&lt;p&gt;When using password managers, email aliases, and authenticator codes, it is important to have a solid strategy for doing periodic backups of this data because if you lose access to it one day, it will cause endless problems.&lt;/p&gt;
&lt;p&gt;I have two methods of backups, and both are encrypted in different ways.&lt;/p&gt;
&lt;p&gt;My primary backup method is using my personal server and database that I have hosted in an undisclosed data center. I have created a personal app that takes any data I want and encrypts it using a provided encryption key. The encrypted data is stored in my database and no encryption keys are stored with the server or database. This ensures that even if there&amp;rsquo;s a data breach, all the data would be encrypted without possibility to decrypt.&lt;/p&gt;
&lt;p&gt;The second method is using Google Drive to store encrypted backups from Proton Pass. I store the encryption keys on my emergency sheet.&lt;/p&gt;
&lt;p&gt;Finally, I created an emergency sheet. This is a physical paper sheet I keep in my house with master passwords, encryption keys, and recovery codes in case I lose access to anything very important. This is a worst-case scenario sheet, but it&amp;rsquo;s always good to have just in case.&lt;/p&gt;
&lt;h2 id="miscellaneous"&gt;Miscellaneous&lt;/h2&gt;
&lt;p&gt;There are a lot of other small things I do that don&amp;rsquo;t warrant their own section so I&amp;rsquo;ll just list them here quickly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Turn on &lt;a href="https://support.apple.com/en-ca/108756"&gt;Advanced Data Protection&lt;/a&gt; for iCloud storage, which encrypts iCloud data, which is off by default. &lt;em&gt;(Everybody should do this one, it&amp;rsquo;s easy and important)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Turn off location services on iPhone.&lt;/li&gt;
&lt;li&gt;Reject any prompts for Data Tracking on apps.&lt;/li&gt;
&lt;li&gt;Use VPN&amp;rsquo;s as often as possible to mask IP addresses.&lt;/li&gt;
&lt;li&gt;Avoid products and services from Google and large tech companies.&lt;/li&gt;
&lt;li&gt;Avoid using or downloading apps such as TikTok, Facebook, Instagram or Twitter.&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://duckduckgo.com"&gt;DuckDuckGo&lt;/a&gt; instead of Google Search.&lt;/li&gt;
&lt;li&gt;Avoid any &amp;ldquo;always listening&amp;rdquo; smart-home products like Google Home, Amazon Alexa, or Siri.&lt;/li&gt;
&lt;li&gt;Use Firefox instead of Chrome.&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://standardnotes.com"&gt;Standard Notes&lt;/a&gt; for note taking.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m continuously improving my online security strategy so I may update this article periodically to add or remove items. I hope this article has exposed you to something new and I hope it encourages you to start improving your online security as well.&lt;/p&gt;</content></item><item><title>JS Proxies for array indices getters &amp; setters</title><link>/posts/proxies-js-array-getters/</link><pubDate>Wed, 18 Sep 2024 00:00:00 +0000</pubDate><guid>/posts/proxies-js-array-getters/</guid><description>&lt;p&gt;This post will cover a technique for implementing getters and setters for every item in an array, using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy"&gt;Proxies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A common issue with getters and setters is that they are not recursive for nested objects or arrays. This can cause confusion when accessing an object via a getter and attempting to mutate a field on the returned object and not seeing the changes take effect.&lt;/p&gt;
&lt;p&gt;Here is an example of the issue. If we have a class that stores its data in an ArrayBuffer instead of just plain variables, then the issue becomes easier to understand.&lt;/p&gt;</description><content>&lt;p&gt;This post will cover a technique for implementing getters and setters for every item in an array, using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy"&gt;Proxies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A common issue with getters and setters is that they are not recursive for nested objects or arrays. This can cause confusion when accessing an object via a getter and attempting to mutate a field on the returned object and not seeing the changes take effect.&lt;/p&gt;
&lt;p&gt;Here is an example of the issue. If we have a class that stores its data in an ArrayBuffer instead of just plain variables, then the issue becomes easier to understand.&lt;/p&gt;
&lt;p&gt;This example just stores an RGBa color in the buffer as 4 u8&amp;rsquo;s.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;view&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DataView&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ArrayBuffer&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;color() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// red
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// green
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// blue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// alpha
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Accessing and setting the entire color will always work as expected:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Foo&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [1, 6, 8, 4] - it works!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So we see that assigning and getting the entire array works as expected, the issue comes when trying to access and then mutate individual items in the array:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Foo&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [1, 6, 8, 4] - Wrong! not updated correctly
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We see above that when logging the color again we don&amp;rsquo;t see the first element in the array being &lt;code&gt;100&lt;/code&gt; which is unexpected - it should&amp;rsquo;ve been mutated.&lt;/p&gt;
&lt;h2 id="why-does-this-happen"&gt;Why does this happen?&lt;/h2&gt;
&lt;p&gt;When attempting to set an indexed item in an array returned from a getter like this &lt;code&gt;foo.color[0] = 100&lt;/code&gt; what is happening is that &lt;code&gt;foo.color&lt;/code&gt; calls the getter which returns a new array with the correct values, &lt;code&gt;[1, 6, 8, 4]&lt;/code&gt;, and mutating that array works, so it becomes &lt;code&gt;[100, 6, 8, 4]&lt;/code&gt;, &lt;strong&gt;&lt;em&gt;but&lt;/em&gt;&lt;/strong&gt; the changes do not get propagated to the underlying array buffer because the array indices are not connected via getters or setters!&lt;/p&gt;
&lt;p&gt;So when logging out the underlying data again using the getter, we still only see the old data in the buffer&amp;hellip;&lt;/p&gt;
&lt;h2 id="how-do-we-fix-this"&gt;How do we fix this?&lt;/h2&gt;
&lt;p&gt;For nested objects, in most cases, we can use nested getters and setters to allow the mutations on a per-field basis. But for arrays, it is more difficult to define getters and setters on a per-index basis, and using tools like &lt;code&gt;Object.defineProperty(...)&lt;/code&gt; can get messy and hard to extend to Typescript.&lt;/p&gt;
&lt;p&gt;So how do we solve this for arrays returned from getters?&lt;/p&gt;
&lt;p&gt;In comes &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy"&gt;Proxy&lt;/a&gt;! Proxies are a way to intercept actions performed on objects or arrays - they can see when something tries to get or set a field and change either the return value, or how the data is set completely.&lt;/p&gt;
&lt;p&gt;To fix our example, we can modify the color getter to return a Proxied array instead of a normal array, so we intercept mutations on individual items and set them accordingly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;view&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DataView&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ArrayBuffer&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;color() {&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Proxy&lt;/span&gt;([
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ], {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;prop&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;self&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(parseInt(&lt;span style="color:#a6e22e"&gt;prop&lt;/span&gt;), &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;view&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setUint8&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s try mutating individual items again.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Foo&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// [100, 6, 8, 4] - it works!!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now consumers of this API can safely mutate the data received from the getters with no issues.&lt;/p&gt;
&lt;h2 id="drawbacks"&gt;Drawbacks&lt;/h2&gt;
&lt;p&gt;One drawback to returning a Proxied object from a getter is when logging the entire object to the console, the type of the object is wrapped in the Proxy instance.&lt;/p&gt;
&lt;p&gt;So a normal console log of an unproxied array would be printed like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// [1, 6, 8, 4]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but if it&amp;rsquo;s proxied it would print like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;foo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// firefox
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// { &amp;lt;target&amp;gt;: [1, 6, 8, 4], &amp;lt;handler&amp;gt;: {...} }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// chrome
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// { [[Target]]: [1, 6, 8, 4], [[Handler]]: {...}, [[IsRevoked]]: false }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This may confuse users, but it will behave exactly like a normal array.&lt;/p&gt;
&lt;p&gt;I hope this post was helpful in understanding how to allow mutations on an array returned from a getter. Go forth and Proxy!&lt;/p&gt;</content></item><item><title>Reliable I/O with the TypeScript Compiler API (Video)</title><link>/posts/reliable-i-o-with-the-typescript-compiler-api-video/</link><pubDate>Mon, 01 Jul 2024 13:04:43 +0000</pubDate><guid>/posts/reliable-i-o-with-the-typescript-compiler-api-video/</guid><description>&lt;p&gt;On June 13th, 2024, I gave a talk about code generation at the Future Frontend conference in Helsinki, Finland. The title of the talk was &amp;ldquo;Reliable I/O with the TypeScript Compiler API&amp;rdquo; where I spoke about the brief history of I/O in frontend applications and how we can make I/O more reliable in the future.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/3f3Ev0zASsI?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;</description><content>&lt;p&gt;On June 13th, 2024, I gave a talk about code generation at the Future Frontend conference in Helsinki, Finland. The title of the talk was &amp;ldquo;Reliable I/O with the TypeScript Compiler API&amp;rdquo; where I spoke about the brief history of I/O in frontend applications and how we can make I/O more reliable in the future.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/3f3Ev0zASsI?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;</content></item><item><title>2023 Year in Review</title><link>/posts/2023-review-2024-goals/</link><pubDate>Mon, 18 Dec 2023 15:11:43 +0000</pubDate><guid>/posts/2023-review-2024-goals/</guid><description>&lt;p&gt;This is the 2nd annual yearly-review post that I have written. Last year was the first and can be viewed &lt;a href="/posts/2022-review-2023-goals/"&gt;here&lt;/a&gt;, and a list of all reviews can be found &lt;a href="/tags/review/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last year&amp;rsquo;s post was split into 4 sections, professional review and goals and personal review and goals - this year everything will just be split into 2 sections, review of the year and goals for next year.&lt;/p&gt;
&lt;h3 id="review"&gt;Review&lt;/h3&gt;
&lt;p&gt;Some of my notable events this year were:&lt;/p&gt;</description><content>&lt;p&gt;This is the 2nd annual yearly-review post that I have written. Last year was the first and can be viewed &lt;a href="/posts/2022-review-2023-goals/"&gt;here&lt;/a&gt;, and a list of all reviews can be found &lt;a href="/tags/review/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last year&amp;rsquo;s post was split into 4 sections, professional review and goals and personal review and goals - this year everything will just be split into 2 sections, review of the year and goals for next year.&lt;/p&gt;
&lt;h3 id="review"&gt;Review&lt;/h3&gt;
&lt;p&gt;Some of my notable events this year were:&lt;/p&gt;
&lt;h4 id="wrote-a-book"&gt;Wrote a Book&lt;/h4&gt;
&lt;p&gt;Something that wasn&amp;rsquo;t planned from last year, but I successfully wrote and self-published my &lt;a href="https://typescriptcompilerapi.com"&gt;own ebook&lt;/a&gt; about The Typescript Compiler API. This was a topic I found very interesting and had a vast amount of experience and knowledge around, so it made sense to write about it and obtain some passive income from the sales.&lt;/p&gt;
&lt;h4 id="quit-my-job"&gt;Quit My Job&lt;/h4&gt;
&lt;p&gt;I left my job at Unity in June. I worked there for just over 3 years and I wanted to take some extended time off to learn about new topics and build my own multiplayer games. It was a difficult decision at the time, but in hindsight, it was a great decision.&lt;/p&gt;
&lt;h4 id="created-2-indie-games"&gt;Created 2 Indie Games&lt;/h4&gt;
&lt;p&gt;During my 6 months off, I learned a lot about 3D modeling in Blender and I successfully created 2 multiplayer games in the Godot engine that I always wanted to build.&lt;/p&gt;
&lt;p&gt;The first was a multiplayer 2v2 3rd-person shooter named &lt;strong&gt;Neon Blitz&lt;/strong&gt; (not publicly released). The objective of the game was for teams to plant bombs around a map and have the other team attempt to defuse the bomb or kill all the members of the opposing team. The game was heavily based on the rules of &amp;ldquo;&lt;em&gt;Search &amp;amp; Destroy&lt;/em&gt;&amp;rdquo; from Call of Duty. All assets were created by me from scratch in Blender.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="en" dir="ltr"&gt;Fun time play-testing tonight with &lt;a href="https://twitter.com/EhLouisEh?ref_src=twsrc%5Etfw"&gt;@EhLouisEh&lt;/a&gt; &lt;a href="https://twitter.com/VeeMerk?ref_src=twsrc%5Etfw"&gt;@VeeMerk&lt;/a&gt; &lt;a href="https://twitter.com/Cryo_Pun?ref_src=twsrc%5Etfw"&gt;@Cryo_Pun&lt;/a&gt;. Found some more bugs and got great feedback for things to improve &lt;a href="https://twitter.com/hashtag/GodotEngine?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#GodotEngine&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/IndieGameDev?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#IndieGameDev&lt;/a&gt; &lt;a href="https://t.co/sI6NmTLyYl"&gt;pic.twitter.com/sI6NmTLyYl&lt;/a&gt;&lt;/p&gt;&amp;mdash; Jason (@Rametta) &lt;a href="https://twitter.com/Rametta/status/1689809967379865600?ref_src=twsrc%5Etfw"&gt;August 11, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;The second game was a multiplayer card game named &lt;strong&gt;Pali&lt;/strong&gt;, similar to something like Pokemon or Magic the Gathering. The objective of the card game was to build the best 5 card hand possible using the same deck as your opponent sitting at the table. The game rules were inspired by the Star Trek card game. I open-sourced the entire codebase for the game &lt;a href="https://github.com/rametta/Pali"&gt;here&lt;/a&gt; so it can be used as a reference for anyone else who wants to build similar games. Some assets were created by me, and some were premade or generated.&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="en" dir="ltr"&gt;Been working on a small 3D card game idea. Added in multiplayer this week. &lt;a href="https://twitter.com/hashtag/GodotEngine?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#GodotEngine&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/IndieGameDev?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#IndieGameDev&lt;/a&gt; &lt;br&gt;Room assets by &lt;a href="https://twitter.com/KayLousberg?ref_src=twsrc%5Etfw"&gt;@KayLousberg&lt;/a&gt; &lt;a href="https://t.co/t8iY3fWgAz"&gt;pic.twitter.com/t8iY3fWgAz&lt;/a&gt;&lt;/p&gt;&amp;mdash; Jason (@Rametta) &lt;a href="https://twitter.com/Rametta/status/1729234111695335720?ref_src=twsrc%5Etfw"&gt;November 27, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;h4 id="10-day-meditation-retreat"&gt;10-Day Meditation Retreat&lt;/h4&gt;
&lt;p&gt;In early March, I accomplished one of my previous years goals which was to attend a 10-day &lt;a href="https://suttama.dhamma.org"&gt;meditation retreat&lt;/a&gt;. This one was in Montebello, Quebec, and taught by S.N Goenka. It was a lot of work - long days starting at 4 am with around 10 hours of meditation per day, with no talking or contact with anyone. Overall though, it was a great experience, and look forward to attending again in the future.&lt;/p&gt;
&lt;h4 id="conference-talk-planned"&gt;Conference Talk Planned&lt;/h4&gt;
&lt;p&gt;Another goal from last year was to give a conference talk this year. I didn&amp;rsquo;t get a chance to achieve that yet but I do have it planned for next year as I will be speaking at &lt;a href="https://futurefrontend.com/"&gt;Future Frontend 2024&lt;/a&gt; in 🇫🇮 Helsinki!&lt;/p&gt;
&lt;h3 id="goals"&gt;Goals&lt;/h3&gt;
&lt;p&gt;Last year, I had a lot of smaller-sized goals for the year, this year I only have 1 real big goal for 2024 and that is to move the needle on game development.&lt;/p&gt;
&lt;p&gt;Game development needs a change and I have big plans, but I can&amp;rsquo;t share any details yet. Hopefully, by next year&amp;rsquo;s review, I will have some great announcements related to game development!&lt;/p&gt;</content></item><item><title>WebAuthN in Remix - FaceID, YubiKey, and more!</title><link>/posts/remix-webauthn/</link><pubDate>Wed, 06 Dec 2023 00:00:00 +0000</pubDate><guid>/posts/remix-webauthn/</guid><description>&lt;p&gt;This article covers how to add &amp;ldquo;&lt;strong&gt;passwordless&lt;/strong&gt;&amp;rdquo; authentication to any &lt;a href="https://remix.run"&gt;Remix&lt;/a&gt; application using &lt;a href="https://en.wikipedia.org/wiki/WebAuthn"&gt;WebAuthN&lt;/a&gt;. This allows users to authenticate using their iPhones FaceID, TouchID, a physical security key like a &lt;a href="https://www.yubico.com"&gt;YubiKey&lt;/a&gt;, or a virtual &lt;a href="https://passkey.org/"&gt;Passkey&lt;/a&gt; that can be stored in password managers like LastPass/Bitwarden/OnePassword etc..&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Passkeys are like passwords but better. They’re better because they aren’t created insecurely by humans and because they use public key cryptography to create much more secure experiences.”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;- &lt;a href="https://passkey.org"&gt;https://passkey.org&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description><content>&lt;p&gt;This article covers how to add &amp;ldquo;&lt;strong&gt;passwordless&lt;/strong&gt;&amp;rdquo; authentication to any &lt;a href="https://remix.run"&gt;Remix&lt;/a&gt; application using &lt;a href="https://en.wikipedia.org/wiki/WebAuthn"&gt;WebAuthN&lt;/a&gt;. This allows users to authenticate using their iPhones FaceID, TouchID, a physical security key like a &lt;a href="https://www.yubico.com"&gt;YubiKey&lt;/a&gt;, or a virtual &lt;a href="https://passkey.org/"&gt;Passkey&lt;/a&gt; that can be stored in password managers like LastPass/Bitwarden/OnePassword etc..&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Passkeys are like passwords but better. They’re better because they aren’t created insecurely by humans and because they use public key cryptography to create much more secure experiences.”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;- &lt;a href="https://passkey.org"&gt;https://passkey.org&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="why-integrate-with-webauthn-eli5"&gt;Why integrate with WebAuthN? (ELI5)&lt;/h2&gt;
&lt;p&gt;WebAuthN is a more secure and usually a better UX for users to authenticate with your application. Instead of typing a password, or opening a password manager and finding your login credentials, one can just use their phone&amp;rsquo;s native bio authentication mechanisms like FaceID or fingerprints to authenticate.&lt;/p&gt;
&lt;p&gt;This involves creating a pair of private and public keys and storing the private keys on a local device, and sharing the public keys with a server&amp;rsquo;s database. This process is facilitated by WebAuthN standards.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Although there are many ways to do MFA, security keys are a highly secure and convenient option. Login codes sent via text message can be intercepted, and authentication apps require that your phone be charged and available.”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;- &lt;a href="https://www.yubico.com"&gt;https://www.yubico.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Even if the database&amp;rsquo;s data is compromised and data is leaked, it will not matter because the public key does not have any important information - it is only useful when paired with the private key.&lt;/p&gt;
&lt;p&gt;Adding this feature to your application allows extra security by enforcing it after a normal login for an MFA flow, or just to replace the password altogether. It can also be considered a faster MFA implementation because it does not require waiting for a text message or email with a code to copy/paste, or an Authenticator app to copy/paste 6-digit codes from.&lt;/p&gt;
&lt;h2 id="how-to-integrate-webauthn-into-remix"&gt;How to integrate WebAuthN into Remix&lt;/h2&gt;
&lt;p&gt;The process involves two steps. First step is to have users register some credentials, the second step is to use the credentials when the user tries to login in the future and verify their identity.&lt;/p&gt;
&lt;p&gt;This process can be achieved completely &amp;ldquo;natively&amp;rdquo; by using the Browsers &lt;code&gt;navigator.credentials&lt;/code&gt; API for creating a getting keys on the client side, but it can be more tedious overall since it is more low level.&lt;/p&gt;
&lt;p&gt;So this article will use the great library &lt;a href="https://github.com/MasterKale/SimpleWebAuthn"&gt;SimpleWebAuthN&lt;/a&gt; from &lt;a href="https://twitter.com/iamkale"&gt;Matthew Miller&lt;/a&gt;, which provides packages for the server side, client side, and typescript types, that make everything easier.&lt;/p&gt;
&lt;h2 id="registering-credentials"&gt;Registering Credentials&lt;/h2&gt;
&lt;p&gt;For both registration and authentication of credentials, the flow is similar. For registration it goes like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The client indicates to the server that it wants to register some new credentials.&lt;/li&gt;
&lt;li&gt;The server generates some options that it will pass back to the client, which includes a secret challenge. This is done in the library with &lt;code&gt;webauthn.generateRegistrationOptions(...)&lt;/code&gt;. The secret challenge is stored in a readonly http session cookie.&lt;/li&gt;
&lt;li&gt;The client takes the options and passes it to the WebAuthN facilitator, such as SimpleWebAuthN library to do &lt;code&gt;webauthn.startRegistration(options)&lt;/code&gt; - the client will be prompted by the browser or native OS to choose a format, such as FaceID or passkey.&lt;/li&gt;
&lt;li&gt;The client then takes the result of the registration and passes it back to the server.&lt;/li&gt;
&lt;li&gt;The server validates and verifies the results with something like &lt;code&gt;webauthn.verifyRegistrationResponse(results)&lt;/code&gt; which includes the secret challenge from the session.&lt;/li&gt;
&lt;li&gt;If the verification passes, the &lt;code&gt;publicKey&lt;/code&gt; is stored in the database, along with the corresponding &lt;code&gt;credentialID&lt;/code&gt;, the &lt;code&gt;transports&lt;/code&gt; and a &lt;code&gt;counter&lt;/code&gt;. The transports just indicate the type of device that was used, such as a USB key or other means, and the counter is used to ensure the same device is not used too many times. This data will be fetched and used when the user tries to login later.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; When generating the options on the server - the server can include already existing keys for that user in the options response to prevent the client from trying to register the same credential twice.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Overall, there are a few back-and-forth requests between server and client, and in Remix this can be handled in a few different ways, either using native &lt;a href="https://remix.run/docs/en/main/guides/data-writes#plain-html-forms"&gt;Forms&lt;/a&gt; or by using Remix&amp;rsquo;s &lt;a href="https://remix.run/docs/en/main/hooks/use-fetcher#usefetcher"&gt;useFetcher&lt;/a&gt; hooks, or just with normal http ajax requests like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;Fetch&lt;/a&gt;, &lt;a href="https://axios-http.com/"&gt;Axios&lt;/a&gt; or the O.G &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest"&gt;XMLHTTPRequest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Session cookies are stored using Remix&amp;rsquo;s &lt;a href="https://remix.run/docs/en/main/utils/sessions#createcookiesessionstorage"&gt;createCookieSessionStorage()&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="authenticating"&gt;Authenticating&lt;/h2&gt;
&lt;p&gt;After the credentials are created and stored on the user&amp;rsquo;s device and the public key is stored in the app&amp;rsquo;s database, we can now use them to authenticate the user.&lt;/p&gt;
&lt;p&gt;The flow is as follows (for passwordless):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The user indicates to the server that they would like to login.&lt;/li&gt;
&lt;li&gt;The server generates some options that it will pass back to the client, which includes a secret challenge. This is done in the library with &lt;code&gt;webauthn.generateAuthenticationOptions(...)&lt;/code&gt;. The secret challenge is stored in a readonly http session cookie.&lt;/li&gt;
&lt;li&gt;The client takes the options and passes them to &lt;code&gt;webauthn.startAuthentication(options)&lt;/code&gt; - the client will be prompted by the browser or native OS to choose a format, such as FaceID or passkey.&lt;/li&gt;
&lt;li&gt;The client then takes the result of the registration and passes it back to the server.&lt;/li&gt;
&lt;li&gt;The server validates and verifies the results with &lt;code&gt;webauthn.verifyAuthenticationResponse(results)&lt;/code&gt; which includes the secret challenge from the session.&lt;/li&gt;
&lt;li&gt;If the verification passes, the user is considered valid and another session cookie is set, such as &lt;code&gt;isLoggedIn&lt;/code&gt; and is set to &lt;code&gt;true&lt;/code&gt;, with an expiry date for however long you want the user to be authenticated without having to re-authenticate. The server can redirect the user to an authenticated page with the new session cookie so they can use the app freely, and authenticated.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="recovery"&gt;Recovery&lt;/h2&gt;
&lt;p&gt;Overall WebAuthN is a great solution for stellar UX and strong security in applications - but a drawback can be if the user loses their security device, or loses their phone which holds their private keys. This would mean they lose access to any application that requires their private key for authentication on the client side.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why it is important to also provide a recovery mechanism for lost devices. Most applications provide a series of &amp;ldquo;codes&amp;rdquo; that the user should store somewhere &lt;em&gt;else&lt;/em&gt;, in case they lose access to their primary device, they can add a new device using the recovery codes.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s it! It is pretty simple to integrate WebAuthN into Remix applications, and it provides great UX and great security for users.&lt;/p&gt;
&lt;p&gt;For further information about WebAuthN, check out their official site &lt;a href="https://webauthn.io/"&gt;webauthn.io&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Follow me on twitter (&lt;a href="https://twitter.com/Rametta"&gt;@Rametta&lt;/a&gt;) to hear about new articles.&lt;/p&gt;</content></item><item><title>Godot Data Validation with Zodot</title><link>/posts/godot-data-validation-zodot/</link><pubDate>Tue, 17 Oct 2023 00:00:00 +0000</pubDate><guid>/posts/godot-data-validation-zodot/</guid><description>&lt;p&gt;&lt;a href="https://github.com/rametta/zodot"&gt;Zodot&lt;/a&gt; is a new data validation library for &lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt;, with an API that was inspired by the popular Typescript/Javascript npm package &lt;a href="https://www.npmjs.com/package/zod"&gt;Zod&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Data validation is an important concept in many programming environments, including Godot. It is the process of taking &lt;code&gt;unknown&lt;/code&gt; data and confirming that it matches the shape that is expected. If the data does not match the
expected shape, then gracefully handle the error.&lt;/p&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;p&gt;Some of Zodot&amp;rsquo;s convenient features include:&lt;/p&gt;</description><content>&lt;p&gt;&lt;a href="https://github.com/rametta/zodot"&gt;Zodot&lt;/a&gt; is a new data validation library for &lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt;, with an API that was inspired by the popular Typescript/Javascript npm package &lt;a href="https://www.npmjs.com/package/zod"&gt;Zod&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Data validation is an important concept in many programming environments, including Godot. It is the process of taking &lt;code&gt;unknown&lt;/code&gt; data and confirming that it matches the shape that is expected. If the data does not match the
expected shape, then gracefully handle the error.&lt;/p&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;p&gt;Some of Zodot&amp;rsquo;s convenient features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Typed dictionaries in GDScript&lt;/li&gt;
&lt;li&gt;Typed Unions&lt;/li&gt;
&lt;li&gt;Support for nullables&lt;/li&gt;
&lt;li&gt;Automatic data coercing with &lt;code&gt;str_to_var()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More details on these features below.&lt;/p&gt;
&lt;h2 id="when-to-use-zodot"&gt;When to use Zodot&lt;/h2&gt;
&lt;p&gt;Oftentimes in game development, or any development - developers will store or retrieve data externally from their codebase, either from a database, an API rest endpoint, a file, or just an external package. Such data can be things like a player&amp;rsquo;s inventory system, their statistics, lobby information, friends lists, or more.&lt;/p&gt;
&lt;p&gt;No matter how you retrieve some external data, the important step is to validate that the data you received matches the shape that you are expecting, otherwise you may start accessing the data when assuming its shape, but results in a runtime crash when the data has changed unexpectedly.&lt;/p&gt;
&lt;h2 id="how-to-use-zodot"&gt;How to use Zodot&lt;/h2&gt;
&lt;p&gt;Using Zodot is super easy. The first thing to do is define a schema, and then use the schema to parse the data that you want to validate.&lt;/p&gt;
&lt;p&gt;Example of defining a player schema with 3 fields:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;var PlayerSchema &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;schema({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;user_id&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;string(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;avatar_color&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;color(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;position&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vector3()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This schema defined an object with 3 typed fields. Now we can take some data and pass it to the schema to be validated against:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;func parse_player(data: Variant):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; var result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; PlayerSchema&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;not&lt;/span&gt; result&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ok():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(&lt;span style="color:#e6db74"&gt;&amp;#34;The data does not match the expected shape&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(result&lt;span style="color:#f92672"&gt;.&lt;/span&gt;error)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Do things with the valid data now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print(result&lt;span style="color:#f92672"&gt;.&lt;/span&gt;data)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above example, we see the data comes in as a &lt;code&gt;Variant&lt;/code&gt; type, which just means it could be anything, then we pass that to our schema. If our result from the parse is &lt;code&gt;not ok&lt;/code&gt;, then we have access to a detailed error message as &lt;code&gt;result.error&lt;/code&gt;. If it does match the schema, then we have access to the typed data in &lt;code&gt;result.data&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="data-coercing"&gt;Data Coercing&lt;/h2&gt;
&lt;p&gt;One of the best features of Zodot is its ability to &lt;code&gt;corece&lt;/code&gt; data before validating. This is popular when complex data is stored as strings and then needs to be deserialized back into its real type after retrieval. Let&amp;rsquo;s look at an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;var schema &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;schema({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;color()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;coerce(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;position&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vector2()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;coerce()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We use the &lt;code&gt;.coerce()&lt;/code&gt; extension for each field we want to deserialize because we are expecting to receive that field as a string that was previously serialized using Godot&amp;rsquo;s &lt;a href="https://docs.godotengine.org/en/stable/classes/class_@globalscope.html#class-globalscope-method-var-to-str"&gt;var_to_str&lt;/a&gt; method.&lt;/p&gt;
&lt;p&gt;Now if we have serialized data such as:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# notice the values are wrapped in strings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;var data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;color&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Color(1,2,3,.5)&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;position&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Vector3(4,2,5)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can parse it and receive the actual types after successful validation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;var result &lt;span style="color:#f92672"&gt;=&lt;/span&gt; schema&lt;span style="color:#f92672"&gt;.&lt;/span&gt;parse(data)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(result&lt;span style="color:#f92672"&gt;.&lt;/span&gt;data&lt;span style="color:#f92672"&gt;.&lt;/span&gt;color) &lt;span style="color:#75715e"&gt;# Color(1,2,3,.5) - real type, not wrapped in strings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="typed-dictionaries"&gt;Typed Dictionaries&lt;/h2&gt;
&lt;p&gt;Zodot provides some powerful features that are not even available in GDScript, such as typed dictionaries. Take a look at a dictionary example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;var schema &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;schema({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;other_field&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;float(),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;my_dict&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;dictionary(Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;color())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since GDScript can&amp;rsquo;t define the type for the dictionary values, we can use Zodot&amp;rsquo;s dictionary validator to ensure that all the values in the dictionary are of a certain type - like this example, all values in the dictionary must be a &lt;code&gt;Color&lt;/code&gt; type.&lt;/p&gt;
&lt;h2 id="typed-unions"&gt;Typed Unions&lt;/h2&gt;
&lt;p&gt;Another powerful validator from Zodot is called &lt;code&gt;z.union()&lt;/code&gt; which is another feature that GDScript does not provide. This validator allows fields to be more than one type.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;schema({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;user_id&amp;#34;&lt;/span&gt;: Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;union([Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;string(), Z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;integer()])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this example, the &lt;code&gt;user_id&lt;/code&gt; is defined to accept a string or even an integer as a valid type! This is similar to other languages like Typescript which would be defined as: &lt;code&gt;type UserId = string | number&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="nullables"&gt;Nullables&lt;/h2&gt;
&lt;p&gt;One last feature of Zodot is its ability to allow any field to be &lt;code&gt;null&lt;/code&gt; just by adding &lt;code&gt;.nullable()&lt;/code&gt; to the end of the field validator.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;var nullable_color_field &lt;span style="color:#f92672"&gt;=&lt;/span&gt; z&lt;span style="color:#f92672"&gt;.&lt;/span&gt;color()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nullable()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This makes it much more clear than the basic GDScript type definitions since GDScript has no real way of defining that relationship.&lt;/p&gt;
&lt;h2 id="try-it-out"&gt;Try it out&lt;/h2&gt;
&lt;p&gt;Zodot is available on the Godot Asset Store &lt;a href="https://godotengine.org/asset-library/asset/2261"&gt;here&lt;/a&gt;, and it can also just be downloaded directly from Github &lt;a href="https://github.com/rametta/zodot"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Follow me on &lt;a href="https://twitter.com/Rametta"&gt;Twitter&lt;/a&gt; to hear more about interesting Godot projects!&lt;/p&gt;</content></item><item><title>My New Book! The Typescript Compiler API</title><link>/posts/typescript-compiler-api-book/</link><pubDate>Fri, 02 Jun 2023 00:00:00 +0000</pubDate><guid>/posts/typescript-compiler-api-book/</guid><description>&lt;p&gt;I am proud to announce that my new book about The Typescript Compiler API is now available at &lt;a href="https://typescriptcompilerapi.com"&gt;https://typescriptcompilerapi.com&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;This book is a culmination of years of work as a software engineer working on metaprogramming - the art of generating code, reading code automatically, and extending language feature sets. Typescript is quickly taking over the world as the most popular &lt;em&gt;compile-to-javascript&lt;/em&gt; language and this book will explain the magic behind metaprogramming with Typescript. If you&amp;rsquo;re a software developer, I guarantee you will learn something new and useful by reading this book, and apply it to your own work to automate tasks, even if not using Typescript.&lt;/p&gt;</description><content>&lt;p&gt;I am proud to announce that my new book about The Typescript Compiler API is now available at &lt;a href="https://typescriptcompilerapi.com"&gt;https://typescriptcompilerapi.com&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;This book is a culmination of years of work as a software engineer working on metaprogramming - the art of generating code, reading code automatically, and extending language feature sets. Typescript is quickly taking over the world as the most popular &lt;em&gt;compile-to-javascript&lt;/em&gt; language and this book will explain the magic behind metaprogramming with Typescript. If you&amp;rsquo;re a software developer, I guarantee you will learn something new and useful by reading this book, and apply it to your own work to automate tasks, even if not using Typescript.&lt;/p&gt;
&lt;p&gt;Cheers! 🍻&lt;/p&gt;</content></item><item><title>2022 Year in Review</title><link>/posts/2022-review-2023-goals/</link><pubDate>Sat, 31 Dec 2022 15:11:43 +0000</pubDate><guid>/posts/2022-review-2023-goals/</guid><description>&lt;p&gt;This is the first time that I do this type of year-end review post, and I hope to continue this tradition for some time.&lt;/p&gt;
&lt;p&gt;I would like to summarize the things that I am proud of achieving throughout the year. This is for three reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I would like to look back and celebrate everything I have done over the year.&lt;/li&gt;
&lt;li&gt;I would like to review this post next year and see if I achieved my goals that I specified.&lt;/li&gt;
&lt;li&gt;As I continue this tradition in the future I may forget when and what I have learned over the years and I can come back and track my wins over the years by revisiting these posts.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I will split the review into two sections: &lt;a href="/posts/2022-review-2023-goals/#personal"&gt;Personal&lt;/a&gt; review and goals, and &lt;a href="/posts/2022-review-2023-goals/#professional"&gt;Professional&lt;/a&gt; review and goals.&lt;/p&gt;</description><content>&lt;p&gt;This is the first time that I do this type of year-end review post, and I hope to continue this tradition for some time.&lt;/p&gt;
&lt;p&gt;I would like to summarize the things that I am proud of achieving throughout the year. This is for three reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I would like to look back and celebrate everything I have done over the year.&lt;/li&gt;
&lt;li&gt;I would like to review this post next year and see if I achieved my goals that I specified.&lt;/li&gt;
&lt;li&gt;As I continue this tradition in the future I may forget when and what I have learned over the years and I can come back and track my wins over the years by revisiting these posts.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I will split the review into two sections: &lt;a href="/posts/2022-review-2023-goals/#personal"&gt;Personal&lt;/a&gt; review and goals, and &lt;a href="/posts/2022-review-2023-goals/#professional"&gt;Professional&lt;/a&gt; review and goals.&lt;/p&gt;
&lt;h2 id="personal"&gt;Personal&lt;/h2&gt;
&lt;p&gt;This personal section are things that I have learned and started doing in 2022 that are non-work related, and that I am proud of discovering and trying, and plan to continue doing in the new year.&lt;/p&gt;
&lt;h3 id="personal-2022-review"&gt;Personal 2022 Review&lt;/h3&gt;
&lt;h4 id="cold-showers"&gt;Cold Showers&lt;/h4&gt;
&lt;p&gt;I started taking cold showers. I found them to be helpful for me in reducing inflammation in my sinuses, making me feel better in the mornings, and improving my sleep and metabolism. Sometimes I&amp;rsquo;ll just end a hot shower with a few minutes of cold water, and sometimes I&amp;rsquo;ll start the cold from the beginning.&lt;/p&gt;
&lt;h4 id="hot-yoga"&gt;Hot Yoga&lt;/h4&gt;
&lt;p&gt;Hot Yoga has been an amazing discovery for me, initially it was an idea for staying active during the winter months when I can&amp;rsquo;t play tennis outdoors, but it evolved into being one of my favourite activities and I try to go two or three times per week. I find it helps with my flexibility, cardiovascular health, mood and general well-being.&lt;/p&gt;
&lt;h4 id="wim-hof-breathing"&gt;Wim Hof Breathing&lt;/h4&gt;
&lt;p&gt;If you don&amp;rsquo;t know Wim Hof, check him out, he is an incredible person that advocates cold water therapy and has a special breathing technique for improving the immune system. I found his breathing method to help improve my sinus health and it puts me in a calm mood.&lt;/p&gt;
&lt;h4 id="meditation"&gt;Meditation&lt;/h4&gt;
&lt;p&gt;I discovered Sam Harris&amp;rsquo;s meditation app called Waking Up and have really enjoyed learning about meditation and mindfulness, along with practising the techniques that he discusses in his lessons. Although I find it very difficult, I have begun to see and understand the benefits of being more mindful.&lt;/p&gt;
&lt;h4 id="fasting"&gt;Fasting&lt;/h4&gt;
&lt;p&gt;I started both intermittent fasting and prolonged fasting this year. Near the end of the year in December I finished my first 3 day water fast and loved it even more than intermittent fasting. There are just so many health benefits to fasting such as Autophagy, improved insulin sensitivity, and decreases in inflammation.&lt;/p&gt;
&lt;h4 id="biology"&gt;Biology&lt;/h4&gt;
&lt;p&gt;I have been learning a lot about biology because my interest keeps growing in this field. Topics such as the nervous system, the endocrine system and the cardiovascular system were all at the top of my personal studies throughout the year. I learned a lot but only touched the tip of the iceberg.&lt;/p&gt;
&lt;h4 id="sauna"&gt;Sauna&lt;/h4&gt;
&lt;p&gt;After a trip to Finland in September to attend a conference for work, I rediscovered saunas and their benefits, especially when paired with cold water therapy. Cardiovascular health improvements are just a small slice of benefits that come from saunas.&lt;/p&gt;
&lt;h4 id="walking--podcasts"&gt;Walking &amp;amp; Podcasts&lt;/h4&gt;
&lt;p&gt;I often went on walks before 2022, but in 2022 I increased that and went at least once per day, sometimes twice, and found that podcasts are a great way to learn new things while walking. Some of my favourite podcasts I found this year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Huberman Lab (Dr. Andrew Huberman)&lt;/li&gt;
&lt;li&gt;The Peter Attia Drive (Dr. Peter Attia)&lt;/li&gt;
&lt;li&gt;FoundMyFitness (Dr. Ronda Patrick)&lt;/li&gt;
&lt;li&gt;Lifespan - (Dr. David Sinclair)&lt;/li&gt;
&lt;li&gt;Lex Friedman Podcast&lt;/li&gt;
&lt;li&gt;All In Podcast&lt;/li&gt;
&lt;li&gt;Making Sense - Sam Harris&lt;/li&gt;
&lt;li&gt;The Tim Ferriss Show&lt;/li&gt;
&lt;li&gt;The Ben Shapiro Show&lt;/li&gt;
&lt;li&gt;Wellness Unpacked - Ella Mills&lt;/li&gt;
&lt;li&gt;Ear Biscuits - Rhett &amp;amp; Link&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="mycology"&gt;Mycology&lt;/h4&gt;
&lt;p&gt;A new hobby of mycology has emerged for me, learning about different species of mushrooms, how mycelium works, growing my own mushrooms and learning how to clone and grow mushrooms from scratch in petri dishes. This hobby has also led me to eat more medicinal mushrooms such as Lion&amp;rsquo;s Mane, Reishi and Turkey Tail, and encouraged me to go for more walks in forests to try and identify wild mushrooms.&lt;/p&gt;
&lt;h4 id="adaptogens"&gt;Adaptogens&lt;/h4&gt;
&lt;p&gt;Related to medicinal mushrooms, I started learning more about the benefits of vitamins and other supplements such as adaptogens, mushroom supplements and the importance of Omega-3 fatty acids, Vitamin D and the Vitamin B&amp;rsquo;s.&lt;/p&gt;
&lt;h4 id="carbohydrates"&gt;Carbohydrates&lt;/h4&gt;
&lt;p&gt;I always knew about carbs but this year I did a deep dive on how they work and how they affect blood glucose, ketone production, metabolism, and how they can also affect mental disorders. The more I learn about carbs, the more I want to reduce my consumption of them.&lt;/p&gt;
&lt;h4 id="buddhism"&gt;Buddhism&lt;/h4&gt;
&lt;p&gt;I am not a Buddhist but I have been learning about their ideologies and disciplines, especially in regards to meditation and mindfulness. I read some books about Buddhism and plan to continue this research as I find it interesting.&lt;/p&gt;
&lt;h4 id="drinking"&gt;Drinking&lt;/h4&gt;
&lt;p&gt;Alcohol has always been known to me to be bad for both physical and mental health. I have not eliminated it completely from my life but drastically reduced my consumption and have noticed great benefits already, especially in regards to weight loss, mood improvements, sleep improvements and general health improvements.&lt;/p&gt;
&lt;h4 id="books"&gt;Books&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;ve read a handful of books this year, some better than others, but my two favourite books of the year are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The China Study - Dr. T. Colin Campbell&lt;/li&gt;
&lt;li&gt;Brain Energy - Dr. Chris M. Palmer (Reading in progress but very good so far)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="personal-2023-goals"&gt;Personal 2023 Goals&lt;/h3&gt;
&lt;h4 id="retreat"&gt;Retreat&lt;/h4&gt;
&lt;p&gt;I would like to attend a 7-10 day vipassana meditation retreat to gain a better understanding of meditation and mindfulness.&lt;/p&gt;
&lt;h4 id="fasting-1"&gt;Fasting&lt;/h4&gt;
&lt;p&gt;I would like to do a 3 to 5 day fast every few months. At least 3 times in the new year.&lt;/p&gt;
&lt;h4 id="mushroom-identification-certificate"&gt;Mushroom Identification Certificate&lt;/h4&gt;
&lt;p&gt;I would like to continue to study more mycology and take some exams for obtaining a mushroom identification certificate for indentifying wild mushrooms.&lt;/p&gt;
&lt;h4 id="monitor-ketones-and-blood-glucose"&gt;Monitor Ketones and Blood Glucose&lt;/h4&gt;
&lt;p&gt;To better understand how my body reacts to different foods and exercises, I would like to obtain a Continuous Glucose Monitor (CGM) to be able to always track my blood glucose levels. Even though I am not a diabetic I still find these tools insightful. I would also like a ketone monitor to be able to measure the amount of ketones that are being produced in my system, which will give me a better understanding on where the source of my energy is originating (food or personal fat reserves).&lt;/p&gt;
&lt;h4 id="politics"&gt;Politics&lt;/h4&gt;
&lt;p&gt;I have always considered myself left-of-center leaning, if not completely left, but as I learn new things about conservative and liberal policies I realize that I know very little and I would like to learn more from both sides to better be able to understand our political climate and be more informed.&lt;/p&gt;
&lt;h4 id="philosophy"&gt;Philosophy&lt;/h4&gt;
&lt;p&gt;I would like to learn more about different philosophical topics such as stoicism, hedonism and epicureanism.&lt;/p&gt;
&lt;h4 id="read-at-least-25-books"&gt;Read at least 25 books&lt;/h4&gt;
&lt;p&gt;I would like to read at least 25 books and have a breakdown by subject that will help achieve my other goals, so I would like to read at least:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 books about politics, 1 for conservatism, 1 for liberalism, and maybe an extra about libertarianism.&lt;/li&gt;
&lt;li&gt;2 books about Buddhism or mindfulness.&lt;/li&gt;
&lt;li&gt;3 books about philosophy (stoicism, hedonism, epicureanism).&lt;/li&gt;
&lt;li&gt;Books about mycology and adaptogens.&lt;/li&gt;
&lt;li&gt;Books about metabolism, immune systems, autophagy, and general physiology.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="professional"&gt;Professional&lt;/h2&gt;
&lt;h3 id="professional-2022-review"&gt;Professional 2022 Review&lt;/h3&gt;
&lt;h4 id="open-source-work"&gt;Open Source Work&lt;/h4&gt;
&lt;p&gt;In 2022 I have some notable accomplishments with the open source libraries I have created.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/rametta/pratica"&gt;Pratica&lt;/a&gt; library that I created now has around 350 github stars!&lt;/li&gt;
&lt;li&gt;All my github libraries and tools have surpassed 500 stars combined.&lt;/li&gt;
&lt;li&gt;Created my most useful library yet called &lt;a href="https://github.com/rametta/rapini"&gt;Rapini&lt;/a&gt; that is a code generator that combines OpenAPI, React, React Query, Typescript, and Axios.&lt;/li&gt;
&lt;li&gt;I started &lt;a href="https://github.com/rametta?tab=sponsoring"&gt;sponsoring&lt;/a&gt; someone on github because they work on open source projects than I rely upon.&lt;/li&gt;
&lt;li&gt;Contributed to my favourite haskell open source project called &lt;a href="https://github.com/digitallyinduced/ihp"&gt;IHP&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="unity"&gt;Unity&lt;/h4&gt;
&lt;p&gt;I have surpassed my 2.5 year point at &lt;a href="https://unity.com/"&gt;Unity&lt;/a&gt;. I have worked on a lot of great projects there, including &lt;a href="https://unity.com/products/unity-reflect"&gt;Unity Reflect&lt;/a&gt;, Game Growth, &lt;a href="https://dashboard.unity3d.com"&gt;Unity Dashboard&lt;/a&gt;, and User Generated Content. I have given internal presentations on topics that I find interesting and that are useful for others and I mentor lower level engineers on how to write systems and grow as a software engineer.&lt;/p&gt;
&lt;h4 id="hugo-mini-course-income"&gt;Hugo Mini Course Income&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://hugo-mini-course.netlify.app/"&gt;My mini course&lt;/a&gt; that I created about the Hugo static site generator has now started providing some passive income through ad revenue.&lt;/p&gt;
&lt;h3 id="professional-2023-goals"&gt;Professional 2023 Goals&lt;/h3&gt;
&lt;h4 id="kubernetes-certificate"&gt;Kubernetes Certificate&lt;/h4&gt;
&lt;p&gt;I&amp;rsquo;ve been using Kubernetes for years at work to build large scale microservices but never completed my understanding of all it&amp;rsquo;s concepts, I would like to finish that by getting a certificate such as &lt;a href="https://training.linuxfoundation.org/certification/certified-kubernetes-application-developer-ckad/"&gt;CKAD&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="conference-presentation"&gt;Conference Presentation&lt;/h4&gt;
&lt;p&gt;In 2023 I would like to give my first public conference talk about a topic of my choosing. Most likely codegen and the typescript compiler API, as it is my specialty. This talk should ideally be in Montreal.&lt;/p&gt;
&lt;h4 id="ai--tensorflow"&gt;AI &amp;amp; Tensorflow&lt;/h4&gt;
&lt;p&gt;I would like to start learning Tensorflow for handling the processing of data with AI models. I would also like to deep dive into &lt;a href="https://stability.ai/blog/stable-diffusion-public-release"&gt;Stable Diffusion&lt;/a&gt;, &lt;a href="https://dreambooth.github.io/"&gt;Dreambooth&lt;/a&gt;, and OpenAI&amp;rsquo;s &lt;a href="https://openai.com/blog/chatgpt/"&gt;ChatGPT&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id="multiplayer"&gt;Multiplayer&lt;/h4&gt;
&lt;p&gt;As I work at a gaming company, I would like to gain a better understanding of the different multiplayer aspects of large scale multiplayer games. Right now I work on multiplayer concepts such as UGC but I have knowledge gaps in networking concepts such as jitter buffers, state synchronization, priority accumulators, NAT punch-through, and visual smoothing. I would like to increase knowledge in these areas to be able to build better tools for unity developers.&lt;/p&gt;
&lt;h4 id="big-data-processing"&gt;Big Data Processing&lt;/h4&gt;
&lt;p&gt;When working with large scale microservice systems, we inevitably have large amounts of data to sift through. I know a few techniques for processing data that leverage Google&amp;rsquo;s BigQuery but I would like to learn how to set up full ETL systems with tools such as Apache Airflow, or other similar tools.&lt;/p&gt;
&lt;h4 id="open-source"&gt;Open Source&lt;/h4&gt;
&lt;p&gt;I would like to become a maintainer for an open source library that I have not created, but rely upon. I hope to become a maintainer for an F# library called &lt;a href="https://github.com/fsprojects/SwaggerProvider"&gt;SwaggerProvider&lt;/a&gt;&lt;/p&gt;</content></item><item><title>React Query Codegen from OpenAPI</title><link>/posts/rapini-react-query-openapi-codegen/</link><pubDate>Thu, 09 Jun 2022 00:00:00 +0000</pubDate><guid>/posts/rapini-react-query-openapi-codegen/</guid><description>&lt;p&gt;&lt;a href="https://github.com/rametta/rapini"&gt;Rapini&lt;/a&gt; is a new tool that can generate custom &lt;a href="https://react-query.tanstack.com/"&gt;React Query&lt;/a&gt; hooks using &lt;a href="https://www.openapis.org/"&gt;OpenAPI&lt;/a&gt; (Swagger) files.&lt;/p&gt;
&lt;p&gt;The Command Line Interface (CLI) tool will take a path to an Open API file and generate a package that includes react hooks, typescript types and &lt;a href="https://axios-http.com/"&gt;axios&lt;/a&gt; http requests - and this package is conveniently bundled in a way that it can be published to NPM or any other package registry of your choosing.&lt;/p&gt;
&lt;p&gt;No need to manually write axios request functions and react query code to start using your backend endpoints, just generate and import your code to ship features faster.&lt;/p&gt;</description><content>&lt;p&gt;&lt;a href="https://github.com/rametta/rapini"&gt;Rapini&lt;/a&gt; is a new tool that can generate custom &lt;a href="https://react-query.tanstack.com/"&gt;React Query&lt;/a&gt; hooks using &lt;a href="https://www.openapis.org/"&gt;OpenAPI&lt;/a&gt; (Swagger) files.&lt;/p&gt;
&lt;p&gt;The Command Line Interface (CLI) tool will take a path to an Open API file and generate a package that includes react hooks, typescript types and &lt;a href="https://axios-http.com/"&gt;axios&lt;/a&gt; http requests - and this package is conveniently bundled in a way that it can be published to NPM or any other package registry of your choosing.&lt;/p&gt;
&lt;p&gt;No need to manually write axios request functions and react query code to start using your backend endpoints, just generate and import your code to ship features faster.&lt;/p&gt;
&lt;h2 id="how-to-generate-react-hooks-from-open-api-files"&gt;How to generate react hooks from Open API files&lt;/h2&gt;
&lt;p&gt;Using the &lt;a href="https://github.com/rametta/rapini"&gt;rapini&lt;/a&gt; CLI, here is an example to generate your react query hooks, axios requests and typescript types from Open API.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Install the CLI tool globally (need npm)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm i -g rapini
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Pass the path to your Open API file to rapini&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rapini -p path/to/openapi.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s it! 1 command to install the CLI globally and 1 command to generate everything you will ever need.&lt;/p&gt;
&lt;p&gt;The generated code will be outputted to &lt;code&gt;rapini-generated-package&lt;/code&gt; folder in your current directory, but that could be changed with a CLI option &lt;code&gt;--output-dir&lt;/code&gt;, like this: &lt;code&gt;rapini -p path/to/openapi.yaml --output-dir /my-custom-package&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are many CLI options to customize the generated code, including options for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;specifying the name and package version for the generated package&amp;rsquo;s &lt;code&gt;package.json&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;specifying a base url for every request since it may not be included in the OpenAPI files&lt;/li&gt;
&lt;li&gt;specifying &lt;code&gt;replacers&lt;/code&gt; to customize the route used in the requests incase you may need to modify what&amp;rsquo;s in the OpenAPI file without actually changing the OpenAPI file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the options can be found on the rapini &lt;a href="https://github.com/rametta/rapini#cli-options"&gt;readme&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="why-codegen-react-query-with-openapi"&gt;Why codegen React-Query with OpenAPI?&lt;/h2&gt;
&lt;p&gt;Code generation or codegen is a popular way to increase productivity, reduce bugs, and lower the amount of time it takes to ship features quickly.&lt;/p&gt;
&lt;p&gt;OpenAPI already provides all the necessary information for writing code automatically, so we don&amp;rsquo;t need to write the code manually anymore. We no longer need to manually write out the Typescript types for every requests payload and response, because they are already specified in the OpenAPI file. No longer do we need to write axios functions for every request, or react query hooks for every axios call.&lt;/p&gt;
&lt;p&gt;Every GET request will get it&amp;rsquo;s own React Query custom Query hook, and every non-GET, such as POST/PUT/PATCH/DELETE will get their own custom React Query Mutation hook.&lt;/p&gt;
&lt;h2 id="why-codegen-axios-requests-with-openapi"&gt;Why codegen Axios requests with OpenAPI?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/rametta/rapini"&gt;Rapini&lt;/a&gt; uses axios as it&amp;rsquo;s main http client because of it&amp;rsquo;s flexibility for request and response interceptors and global configs. Rapini takes an axios instance when initializing and uses that instance for all react query hooks under the hood.&lt;/p&gt;
&lt;h2 id="react-query-openapi-codegen-example"&gt;React Query OpenAPI Codegen Example&lt;/h2&gt;
&lt;p&gt;Once you generate the custom npm package using &lt;a href="https://github.com/rametta/rapini"&gt;rapini&lt;/a&gt;, you can start to import all the react query hooks, types, requests and query keys from the package. Let&amp;rsquo;s say you generated your package with output name of &lt;code&gt;my-package&lt;/code&gt;, like this: &lt;code&gt;rapini -p path/to/openapi.yaml --output-dir /my-package&lt;/code&gt; then you can start importing like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;initialize&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;my-package&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Pet&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;my-package&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;axiosInstance&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./your-custom-axios-instance&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rapini&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initialize&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;axiosInstance&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;queries&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;mutations&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;queryIds&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;requests&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rapini&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyComponent&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;isLoading&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;isError&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;queries&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;usePets&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;pets&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;pet&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;pet&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;}&amp;gt;{&lt;span style="color:#a6e22e"&gt;pet&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ))}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; );
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rapini uses the OpenAPI &lt;code&gt;operationId&lt;/code&gt; to name all the hooks and requests in the code, so if you have a request with &lt;code&gt;operationId&lt;/code&gt; like &lt;code&gt;createPet&lt;/code&gt;, then an axios request will be made called &lt;code&gt;createPet&lt;/code&gt; and react query mutation hook will be created called &lt;code&gt;useCreatePet&lt;/code&gt; and a query key will be created called &lt;code&gt;createPet&lt;/code&gt;, and all relevant request payload will be taken into account.&lt;/p&gt;
&lt;p&gt;I hope you enjoy rapini and start deleting old code to replace with new generated code!&lt;/p&gt;</content></item><item><title>Traversing the C# syntax tree with F#</title><link>/posts/traverse-csharp-with-fsharp/</link><pubDate>Thu, 09 Dec 2021 00:00:00 +0000</pubDate><guid>/posts/traverse-csharp-with-fsharp/</guid><description>&lt;p&gt;This article will go over the basics of the .NET compiler platform feature for analyzing the C# syntax tree, using F#.&lt;/p&gt;
&lt;p&gt;.NET provides a Syntax API that can read any C# or Visual Basic source file and provide the corresponding Syntax Tree for that code.&lt;/p&gt;
&lt;h2 id="why"&gt;Why&lt;/h2&gt;
&lt;p&gt;Why would someone need to traverse the C# syntax tree?&lt;/p&gt;
&lt;p&gt;Well, it can be for a number of reasons, maybe you want to gather statistics about how many classes, namespaces and methods you have, maybe you want generate code based on what is already written, maybe you want to create new tools like a new linter or a tool like Swagger. All these things can be done by analyzing the syntax tree.&lt;/p&gt;</description><content>&lt;p&gt;This article will go over the basics of the .NET compiler platform feature for analyzing the C# syntax tree, using F#.&lt;/p&gt;
&lt;p&gt;.NET provides a Syntax API that can read any C# or Visual Basic source file and provide the corresponding Syntax Tree for that code.&lt;/p&gt;
&lt;h2 id="why"&gt;Why&lt;/h2&gt;
&lt;p&gt;Why would someone need to traverse the C# syntax tree?&lt;/p&gt;
&lt;p&gt;Well, it can be for a number of reasons, maybe you want to gather statistics about how many classes, namespaces and methods you have, maybe you want generate code based on what is already written, maybe you want to create new tools like a new linter or a tool like Swagger. All these things can be done by analyzing the syntax tree.&lt;/p&gt;
&lt;p&gt;Recently I found myself using the Syntax API for finding Attributes above certain methods and classes, and based on the name and arguments of the Attributes, I generated various other files that were used elsewhere.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-cs" data-lang="cs"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; System.Collections;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; System.Linq;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;using&lt;/span&gt; System.Text;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;namespace&lt;/span&gt; FunWithSyntaxTrees
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Main(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The snippet above shows a small program. We will use this snippet as our input for analyzing the syntax tree.&lt;/p&gt;
&lt;h2 id="how"&gt;How&lt;/h2&gt;
&lt;p&gt;Assuming you have an F# environment setup. You can begin by installing the nuget package &lt;code&gt;Microsoft.CodeAnalysis.CSharp&lt;/code&gt; and importing that into your project.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt; Microsoft.CodeAnalysis
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt; Microsoft.CodeAnalysis.CSharp
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;open&lt;/span&gt; Microsoft.CodeAnalysis.CSharp.Syntax
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; Main &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&amp;lt;&lt;/span&gt;EntryPoint&lt;span style="color:#f92672"&gt;&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; main argv &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After you install the package and add your &lt;code&gt;open&lt;/code&gt; directives, we will hardcode the C# source code from above into the file, above the &lt;code&gt;main&lt;/code&gt; entrypoint function.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ... open directives
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;using System.Collections;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;using System.Linq;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;using System.Text;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;namespace FunWithSyntaxTrees
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; class Program
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; static void Main(string[] args)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; // ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;module&lt;/span&gt; Main &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&amp;lt;&lt;/span&gt;EntryPoint&lt;span style="color:#f92672"&gt;&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; main argv &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When you write a real program that uses the Syntax API, you will most likely be reading the C# source from files, like this &lt;code&gt;let code = File.ReadAllText &amp;quot;/path/to/file&amp;quot;&lt;/code&gt;, instead of hardcoding the string like we did, but for this tutorial it is fine for demonstration.&lt;/p&gt;
&lt;p&gt;So we will begin by passing the string of C# source code to the Syntax API to be parsed, in return we will get the Syntax Tree that we can begin analyzing.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&amp;lt;&lt;/span&gt;EntryPoint&lt;span style="color:#f92672"&gt;&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; main argv &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; syntaxTree&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxTree &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CSharpSyntaxTree.ParseText code
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Note: I will write out the &lt;code&gt;Type&lt;/code&gt;&amp;rsquo;s of all the variables, but it is unnecessary most of the time since F#&amp;rsquo;s type inference is very capable of inferring the type itself. Just like in C# when you use the &lt;code&gt;var&lt;/code&gt; keyword, it is capable of knowing the underlying type, in F# this inference is even more powerful and applies to arguments, functions and everything in-between.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now that the Syntax API has returned our needed Syntax Tree, we can begin travering it and exploring what it offers as data.&lt;/p&gt;
&lt;p&gt;First let us get all the &lt;code&gt;using&lt;/code&gt; directives in the file. We start by getting the root node of the file, then we iterate over all the child nodes inside the root node and find the ones that are the correct &lt;code&gt;UsingDirective&lt;/code&gt; type.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&amp;lt;&lt;/span&gt;EntryPoint&lt;span style="color:#f92672"&gt;&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; main argv &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; syntaxTree&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxTree &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CSharpSyntaxTree.ParseText code
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; rootNode&lt;span style="color:#f92672"&gt;:&lt;/span&gt; CompilationUnitSyntax &lt;span style="color:#f92672"&gt;=&lt;/span&gt; syntaxTree&lt;span style="color:#f92672"&gt;.&lt;/span&gt;GetCompilationUnitRoot()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; rootNodeChildren&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxNode seq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; rootNode&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ChildNodes()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;rootNodeChildren&lt;/code&gt; variable holds all the child &lt;code&gt;SyntaxNode&lt;/code&gt;&amp;rsquo;s of the root node. The root node is basically the first node of the &lt;code&gt;SyntaxTree&lt;/code&gt; which holds everything, and a &lt;code&gt;SyntaxNode&lt;/code&gt; is the most general type of node.&lt;/p&gt;
&lt;p&gt;We now need to iterate over these children to find the correct &lt;code&gt;SyntaxNode&lt;/code&gt; for &lt;code&gt;using&lt;/code&gt; directives since that is what we are looking for. We will declare a small helper function to help find them.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; usingDirectiveNode &lt;span style="color:#f92672"&gt;(&lt;/span&gt;node&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxNode&lt;span style="color:#f92672"&gt;):&lt;/span&gt; UsingDirectiveSyntax option &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; node &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;:?&lt;/span&gt; UsingDirectiveSyntax &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; usingDirective &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Some usingDirective
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; None
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&amp;lt;&lt;/span&gt;EntryPoint&lt;span style="color:#f92672"&gt;&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; main argv &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; syntaxTree&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxTree &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CSharpSyntaxTree.ParseText code
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; rootNode&lt;span style="color:#f92672"&gt;:&lt;/span&gt; CompilationUnitSyntax &lt;span style="color:#f92672"&gt;=&lt;/span&gt; syntaxTree&lt;span style="color:#f92672"&gt;.&lt;/span&gt;GetCompilationUnitRoot()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; rootNodeChildren&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxNode seq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; rootNode&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ChildNodes()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; usingDirectives&lt;span style="color:#f92672"&gt;:&lt;/span&gt; UsingDirectiveSyntax seq &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Seq.choose usingDirectiveNode rootNodeChildren
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The new helper function &lt;code&gt;usingDirectiveNode&lt;/code&gt; takes a generic &lt;code&gt;SyntaxNode&lt;/code&gt; and checks if it is of the &lt;code&gt;UsingDirectiveSyntax&lt;/code&gt; variety, if it is, it returns an F# Option type containing the &lt;code&gt;using&lt;/code&gt; directive node.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: An F# Option type is a way to represent a &lt;em&gt;&amp;ldquo;nullable&amp;rdquo;&lt;/em&gt; value, since there are no real null values in F#, nullable values are representated as Algebraic Data Types, such as the Option type.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We use the new helper function by mapping over every node and passing it to the function. We use &lt;code&gt;Seq.choose&lt;/code&gt; to filter out any &lt;code&gt;None&lt;/code&gt; types and keep all the &lt;code&gt;Some&lt;/code&gt; types. It also unwraps the &lt;code&gt;Some&lt;/code&gt; types so we can keep using them without Option mapping.&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;Seq.choose&lt;/code&gt; is just a fancy way of doing &lt;code&gt;Seq.map&lt;/code&gt; and then &lt;code&gt;Seq.filter&lt;/code&gt; specifically with Option types since the type signature is &lt;code&gt;('T -&amp;gt; 'U option) -&amp;gt; seq&amp;lt;'T&amp;gt; -&amp;gt; seq&amp;lt;'U&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Moving along, so now that we have a sequence of &lt;code&gt;using&lt;/code&gt; directives in a variable, we can get the specific properties of a &lt;code&gt;using&lt;/code&gt; directive. For now we wil just print them out as proof.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; usingDirectiveNode &lt;span style="color:#f92672"&gt;(&lt;/span&gt;node&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxNode&lt;span style="color:#f92672"&gt;):&lt;/span&gt; UsingDirectiveSyntax option &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; node &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;:?&lt;/span&gt; UsingDirectiveSyntax &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; usingDirective &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; Some usingDirective
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; None
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&amp;lt;&lt;/span&gt;EntryPoint&lt;span style="color:#f92672"&gt;&amp;gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; main argv &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; syntaxTree&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxTree &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CSharpSyntaxTree.ParseText code
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; rootNode&lt;span style="color:#f92672"&gt;:&lt;/span&gt; CompilationUnitSyntax &lt;span style="color:#f92672"&gt;=&lt;/span&gt; syntaxTree&lt;span style="color:#f92672"&gt;.&lt;/span&gt;GetCompilationUnitRoot()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; rootNodeChildren&lt;span style="color:#f92672"&gt;:&lt;/span&gt; SyntaxNode seq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; rootNode&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ChildNodes()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; usingDirectives&lt;span style="color:#f92672"&gt;:&lt;/span&gt; UsingDirectiveSyntax seq &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Seq.choose usingDirectiveNode rootNodeChildren
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; usingDirectives
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; List.ofSeq
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; List.map &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; u &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; printfn &lt;span style="color:#f92672"&gt;$&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{u.ToString()}&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; ignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output of running our program would be:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;using System.Collections;
using System.Linq;
using System.Text;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pretty cool right? We analyzed our C# code and found our using directives and printed them out.&lt;/p&gt;
&lt;p&gt;We can use that strategy to find anything in our code, including methods, method arguments, types, classes, interfaces, enums, comments, attributes, etc, everything!&lt;/p&gt;
&lt;p&gt;If you found this useful, feel free to follow me on twitter at &lt;a href="https://twitter.com/rametta"&gt;@rametta&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Simple Remote Data in Typescript</title><link>/posts/simple-remote-data-typescript/</link><pubDate>Thu, 05 Nov 2020 00:00:00 +0000</pubDate><guid>/posts/simple-remote-data-typescript/</guid><description>&lt;p&gt;Introducing &lt;a href="https://github.com/rametta/srd#-simple-remote-data"&gt;&lt;em&gt;Simple Remote Data&lt;/em&gt; (SRD)&lt;/a&gt;, a &lt;a href="https://github.com/fantasyland/static-land/blob/master/docs/spec.md"&gt;Static Land&lt;/a&gt; compliant TypeScript library for managing state from remote sources.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SRD&amp;rsquo;s&lt;/strong&gt; top features are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only &lt;strong&gt;549 bytes&lt;/strong&gt; minified and gzipped, that is ridiculously small!&lt;/li&gt;
&lt;li&gt;Built with &lt;strong&gt;Higher Kinded Types&lt;/strong&gt; (&lt;a href="https://en.wikipedia.org/wiki/Kind_%28type_theory%29"&gt;HKT&amp;rsquo;s&lt;/a&gt;) to allow Typescript to infer these complex disjoint union types.&lt;/li&gt;
&lt;li&gt;Static Land compliant!&lt;/li&gt;
&lt;li&gt;Made for React or any other JS based frontend framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-is-a-remote-data-type"&gt;What is a &lt;em&gt;Remote Data&lt;/em&gt; type?&lt;/h2&gt;
&lt;p&gt;A Remote Data type is a kind of &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions"&gt;discriminate union type&lt;/a&gt; in functional programming for managing the state of some data that is retrieved remotely and asynchronously, such as http response data, websockets, server sent events, reading a file, or any other async IO.&lt;/p&gt;</description><content>&lt;p&gt;Introducing &lt;a href="https://github.com/rametta/srd#-simple-remote-data"&gt;&lt;em&gt;Simple Remote Data&lt;/em&gt; (SRD)&lt;/a&gt;, a &lt;a href="https://github.com/fantasyland/static-land/blob/master/docs/spec.md"&gt;Static Land&lt;/a&gt; compliant TypeScript library for managing state from remote sources.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SRD&amp;rsquo;s&lt;/strong&gt; top features are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only &lt;strong&gt;549 bytes&lt;/strong&gt; minified and gzipped, that is ridiculously small!&lt;/li&gt;
&lt;li&gt;Built with &lt;strong&gt;Higher Kinded Types&lt;/strong&gt; (&lt;a href="https://en.wikipedia.org/wiki/Kind_%28type_theory%29"&gt;HKT&amp;rsquo;s&lt;/a&gt;) to allow Typescript to infer these complex disjoint union types.&lt;/li&gt;
&lt;li&gt;Static Land compliant!&lt;/li&gt;
&lt;li&gt;Made for React or any other JS based frontend framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-is-a-remote-data-type"&gt;What is a &lt;em&gt;Remote Data&lt;/em&gt; type?&lt;/h2&gt;
&lt;p&gt;A Remote Data type is a kind of &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions"&gt;discriminate union type&lt;/a&gt; in functional programming for managing the state of some data that is retrieved remotely and asynchronously, such as http response data, websockets, server sent events, reading a file, or any other async IO.&lt;/p&gt;
&lt;p&gt;Remote Data greatly simplifies the 4 states of any IO operation - &lt;strong&gt;initial&lt;/strong&gt; state, &lt;strong&gt;loading&lt;/strong&gt; state, &lt;strong&gt;failure&lt;/strong&gt; state or &lt;strong&gt;success&lt;/strong&gt; state, by combining them into one pure union so none of these states can overlap and cause &lt;a href="https://youtu.be/IcgmSRJHu_8"&gt;impossible states&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="why-would-i-use-a-remote-data"&gt;Why would I use a Remote Data?&lt;/h2&gt;
&lt;p&gt;To simplify your state model and prevent impossible states! SRD allows us to perform safe and pure computations on our data without redundant null checks.&lt;/p&gt;
&lt;p&gt;It also allows us to cleanly represent our state in our UI applications by providing functions such as &lt;code&gt;match&lt;/code&gt; which is our &lt;a href="https://en.wikipedia.org/wiki/Pattern_matching"&gt;pattern matcher&lt;/a&gt; utility.&lt;/p&gt;
&lt;h2 id="how-would-i-use-a-remote-data"&gt;How would I use a Remote Data?&lt;/h2&gt;
&lt;p&gt;Here is a popular use case in any React application - fetching data from somewhere and displaying it on screen, while also displaying loading states and error states if the fetch fails.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;useState&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;useEffect&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;SRD&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;notAsked&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;failure&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;success&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;srd&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; [&lt;span style="color:#a6e22e"&gt;rd&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;setRd&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;useState&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;notAsked&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;useEffect&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setRd&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;setRd&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;success&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;setRd&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;failure&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, [])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SRD&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;match&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;notAsked&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Empty&lt;/span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;...&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;failure&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;success&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, &lt;span style="color:#a6e22e"&gt;rd&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Without&lt;/em&gt; SRD, we would need to manually manage states for errors, loading and initial states separately - &lt;em&gt;with&lt;/em&gt; SRD the code is a lot smaller, easier to follow and most importantly, &lt;strong&gt;safer&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="what-else"&gt;What else?&lt;/h2&gt;
&lt;p&gt;SRD also provides a lot of great functions for accessing and modifying the data inside the Remote Data.&lt;/p&gt;
&lt;p&gt;If we needed to modify the data inside a &lt;code&gt;success&lt;/code&gt; we can use the popular &lt;code&gt;map&lt;/code&gt; function to do so, it will allow us to run a function on the inside data without worrying if it&amp;rsquo;s a &lt;code&gt;success&lt;/code&gt; or not.&lt;/p&gt;
&lt;p&gt;Here is a TypeScript React example for updating an object:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; [&lt;span style="color:#a6e22e"&gt;rdPerson&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;setPerson&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;useState&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;RD&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;string&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt;&amp;gt;&amp;gt;(&lt;span style="color:#a6e22e"&gt;notAsked&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;useEffect&lt;/span&gt;(() &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setPerson&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;...&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setPerson&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;success&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setPerson&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;failure&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}, [])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;doubleAge&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Person&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ({ ...&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;person.age&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;handleClick&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;setPerson&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;rd&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SRD&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;doubleAge&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;rd&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;SRD&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;match&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;notAsked&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Empty&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Please wait...&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;failure&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`There was a problem: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;success&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;person&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`My age is &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, &lt;span style="color:#a6e22e"&gt;rdPerson&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;handleClick&lt;/span&gt;}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;click&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;to&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;double&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And &lt;code&gt;map&lt;/code&gt; is not the only thing we can do, &lt;a href="https://github.com/rametta/srd#-simple-remote-data"&gt;SRD&lt;/a&gt; provides over a dozen more utilities for managing your SRD state!&lt;/p&gt;
&lt;p&gt;I hope this article clarified the advantages of using a Remote Data type and how to use SRD, I encourage you to try it out! If you do, feel free to &amp;ldquo;Star&amp;rdquo; 🌟 the repo &lt;a href="https://github.com/rametta/srd"&gt;on github&lt;/a&gt;!&lt;/p&gt;</content></item><item><title>5 reasons why Hugo is better than Gatsby</title><link>/posts/hugo-better-than-gatsby/</link><pubDate>Sun, 16 Aug 2020 00:00:00 +0000</pubDate><guid>/posts/hugo-better-than-gatsby/</guid><description>&lt;p&gt;Hugo is an amazingly underrated static site generator and this post is aimed to provide some examples on why it may be a better choice than Gatsby for your next static site!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TLDR;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hugo builds are way faster than Gatsby&lt;/li&gt;
&lt;li&gt;Hugo&amp;rsquo;s template system is simple&lt;/li&gt;
&lt;li&gt;Hugo&amp;rsquo;s built-in features are better than Gatsby&amp;rsquo;s plugin features&lt;/li&gt;
&lt;li&gt;Hugo doesn&amp;rsquo;t require any JS to be used, but supports JS with ESBuild&lt;/li&gt;
&lt;li&gt;Hugo has a small learning curve&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="1-build-times"&gt;1. Build Times&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Gatsby&lt;/strong&gt;&lt;/p&gt;</description><content>&lt;p&gt;Hugo is an amazingly underrated static site generator and this post is aimed to provide some examples on why it may be a better choice than Gatsby for your next static site!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TLDR;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hugo builds are way faster than Gatsby&lt;/li&gt;
&lt;li&gt;Hugo&amp;rsquo;s template system is simple&lt;/li&gt;
&lt;li&gt;Hugo&amp;rsquo;s built-in features are better than Gatsby&amp;rsquo;s plugin features&lt;/li&gt;
&lt;li&gt;Hugo doesn&amp;rsquo;t require any JS to be used, but supports JS with ESBuild&lt;/li&gt;
&lt;li&gt;Hugo has a small learning curve&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="1-build-times"&gt;1. Build Times&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Gatsby&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gatsby is notorious for having long build times that depend on which plugins you use and amount of data you have in each page.&lt;/p&gt;
&lt;p&gt;It is not unusual for Gatsby builds to take more than &lt;strong&gt;20+ minutes&lt;/strong&gt; to build a production site that only has a couple hundred pages. If you use popular plugins like &lt;code&gt;gatsby-image&lt;/code&gt;, then expect your build times to skyrocket even higher.&lt;/p&gt;
&lt;p&gt;If you use Gatsby&amp;rsquo;s internal GraphQL implementation for saving and querying data nodes inside your pages, then expect longer build times as well.&lt;/p&gt;
&lt;p&gt;Gatsby will promote their new incremental builds and cloud build capabilities, but they are marginally faster, buggy, and cause serious vendor lock-in to their &lt;code&gt;Gatsby Cloud&lt;/code&gt; CI service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hugo&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hugo on the other hand, is known for it&amp;rsquo;s extremely fast builds.&lt;/p&gt;
&lt;p&gt;On average every page can be generated in less than 1ms, so a site with 10,000 pages can take just 10 seconds to build, whereas a Gatsby site with 10,000 pages, with the same amount of data, would take 30+ minutes or even hours to build.&lt;/p&gt;
&lt;p&gt;Hugo also has &lt;strong&gt;native&lt;/strong&gt; image processing similar to &lt;code&gt;gatsby-image&lt;/code&gt; but is way faster and would marginally increase build time.&lt;/p&gt;
&lt;h2 id="2-templates"&gt;2. Templates&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Gatsby&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gatsby is built on top of React, and therefore uses &lt;code&gt;JSX&lt;/code&gt; as it&amp;rsquo;s template system.&lt;/p&gt;
&lt;p&gt;JSX is transformed into HTML at build time for the first page load and then re-rendered so Javascript can take control of all document nodes at runtime.
Using React and JSX for static sites, that don&amp;rsquo;t necessarily need complex interactions and logic, means that you ship large JS bundles &lt;em&gt;(that include the React library, Gatsby library, plugins, 3rd party npm libraries, polyfills and more)&lt;/em&gt; with every page - whereas the equivalent vanilla JS would most likely be a fraction of the size.&lt;/p&gt;
&lt;p&gt;Computers or phones with low processing power or memory can struggle to display sites with large JS bundles and can feel laggy and unresponsive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hugo&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hugo uses the Go Template language for it&amp;rsquo;s templates which has simple, easy to read syntax that doesn&amp;rsquo;t require knowledge of JS to be written.&lt;/p&gt;
&lt;p&gt;The Go Templates are converted to HTML at build time and if their is optional JS included on the page, it can be minified, inlined, and even compiled using &lt;a href="https://github.com/evanw/esbuild"&gt;ESBuild&lt;/a&gt; which is included in Hugo automatically.&lt;/p&gt;
&lt;h2 id="3-features"&gt;3. Features&lt;/h2&gt;
&lt;p&gt;Gatsby is marketed to have a large amount of features that other static site generators do not have, largely attributed to it&amp;rsquo;s plugin system. But even with Gatsby&amp;rsquo;s plugin system, Hugo has all the important features built-in to it&amp;rsquo;s core instead of needing to install it separately.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://www.gatsbyjs.com/features/jamstack/gatsby-vs-jekyll-vs-hugo"&gt;one&lt;/a&gt; of Gatsby&amp;rsquo;s thousands of marketing pages, they show a breakdown of Gatsby vs Hugo vs Jekyll and they show how Gatsby wins or ties in every category, but most of these comparisons don&amp;rsquo;t make any sense or are completely false.&lt;/p&gt;
&lt;p&gt;For example, Gatsby shows that Hugo has no &lt;code&gt;modern javascript syntax&lt;/code&gt; even though Hugo has ESBuild which is orders of magnitudes faster than Gatsby&amp;rsquo;s webpack implementation for compiling modern javascript syntax.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://dev-to-uploads.s3.amazonaws.com/i/dwaj4xsy0xok2lo3w9kb.png" alt="Gatsby marketing, falsely claiming that Hugo does not support modern JS"&gt;&lt;/p&gt;
&lt;p&gt;Another example is that Gatsby claims that Hugo does not have &lt;em&gt;declarative data queries or UI building&lt;/em&gt; which is completely false. Hugo has &lt;a href="https://gohugo.io/templates/data-templates/"&gt;data templates&lt;/a&gt;, &lt;a href="https://gohugo.io/templates/data-templates/#implementation-details"&gt;data queries&lt;/a&gt; and components in the form of &lt;a href="https://gohugo.io/templates/partials/"&gt;partials&lt;/a&gt;, inside of templates.
&lt;img src="https://dev-to-uploads.s3.amazonaws.com/i/xp32e3uoyrmrf0macpxw.png" alt="Gatsby lying about features of other static site generators"&gt;&lt;/p&gt;
&lt;p&gt;Also, Gatsby claims that Hugo doesn&amp;rsquo;t have pair programming in it&amp;rsquo;s community, &lt;strong&gt;which is false&lt;/strong&gt;, Hugo has a &lt;a href="https://discourse.gohugo.io/"&gt;discourse&lt;/a&gt;, and they say that Hugo has no &lt;em&gt;swag store&lt;/em&gt;&amp;hellip; Does that matter? who cares?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://dev-to-uploads.s3.amazonaws.com/i/z07hi4oz4xkw1j3zh0hw.png" alt="Gatsby showing that having a swag store is an advantage to a static site generator"&gt;&lt;/p&gt;
&lt;p&gt;There are more examples in that chart of Gatsby trying to make themselves seem better but are just lying, and it&amp;rsquo;ll take awhile to dispute all of them, so we will just move on.&lt;/p&gt;
&lt;h2 id="4-javascript-support"&gt;4. JavaScript Support&lt;/h2&gt;
&lt;p&gt;Gatsby is built on top of React so it of course has JS support by using Webpack and Babel to compile down for browser support.&lt;/p&gt;
&lt;p&gt;But as mentioned above, Hugo also has JS support by leveraging &lt;a href="https://github.com/evanw/esbuild"&gt;ESBuild&lt;/a&gt;, which is a JS bundler and minifier written in Go and is orders of magnitude faster than the Webpack and Babel combo.&lt;/p&gt;
&lt;p&gt;Hugo also makes it way easier to code-split your JS code by just declaring which files you want loaded in each template. You can even include &lt;strong&gt;React&lt;/strong&gt; if needed for more complex components.&lt;/p&gt;
&lt;p&gt;Details &lt;a href="https://gohugo.io/hugo-pipes/js/"&gt;here&lt;/a&gt; in their docs.&lt;/p&gt;
&lt;h2 id="5-learning-curve"&gt;5. Learning Curve&lt;/h2&gt;
&lt;p&gt;Gatsby has an incredibly large learning curve, to get started writing useful Gatsby sites, one must know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JS / NodeJS&lt;/li&gt;
&lt;li&gt;JSX&lt;/li&gt;
&lt;li&gt;NPM&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;Gatsby&amp;rsquo;s complicated build system, transform plugins, source plugins, Gatsby Themes, Gatsby Recipes, and Gatsby&amp;rsquo;s CLI&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;Markdown - &lt;em&gt;optional&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And some of those are very large topics, like React and GraphQL.&lt;/p&gt;
&lt;p&gt;To get started with Hugo, one must know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;Hugo Template Syntax and Template Lookup order&lt;/li&gt;
&lt;li&gt;Markdown - &lt;em&gt;optional&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is a lot easier to get started with Hugo and scale out Hugo for complicated and large sites.&lt;/p&gt;
&lt;h3 id="honorable-mention"&gt;Honorable Mention&lt;/h3&gt;
&lt;p&gt;Gatsby is a for-profit business and will push their products like &lt;code&gt;Gatsby Cloud&lt;/code&gt; on you even if there are better alternatives.&lt;/p&gt;</content></item><item><title>Using TypeScript ADT's to write more reliable React</title><link>/posts/react-typescript-unions/</link><pubDate>Tue, 28 Jul 2020 00:00:00 +0000</pubDate><guid>/posts/react-typescript-unions/</guid><description>&lt;p&gt;You may have heard of Algebraic Data Types (ADT&amp;rsquo;s) before but didn&amp;rsquo;t understand how they can be applied to everyday code - so this article will provide some examples and explanations of why you should start using them.&lt;/p&gt;
&lt;p&gt;Before we get into ADT&amp;rsquo;s, let&amp;rsquo;s go over the foundation of what ADT&amp;rsquo;s are made of.&lt;/p&gt;
&lt;h2 id="basic-types"&gt;Basic Types&lt;/h2&gt;
&lt;p&gt;In Javascript, you &lt;strong&gt;can not&lt;/strong&gt; declare a type that prevents other types from being assigned to it. The below example we see that anything can be assigned to the &lt;code&gt;language&lt;/code&gt; variable. We can assign a &lt;code&gt;number&lt;/code&gt; or a &lt;code&gt;boolean&lt;/code&gt; or an &lt;code&gt;object&lt;/code&gt; to it if we later wanted, but that may cause bugs in the future if we were not expecting the variable type to be something other than a string.&lt;/p&gt;</description><content>&lt;p&gt;You may have heard of Algebraic Data Types (ADT&amp;rsquo;s) before but didn&amp;rsquo;t understand how they can be applied to everyday code - so this article will provide some examples and explanations of why you should start using them.&lt;/p&gt;
&lt;p&gt;Before we get into ADT&amp;rsquo;s, let&amp;rsquo;s go over the foundation of what ADT&amp;rsquo;s are made of.&lt;/p&gt;
&lt;h2 id="basic-types"&gt;Basic Types&lt;/h2&gt;
&lt;p&gt;In Javascript, you &lt;strong&gt;can not&lt;/strong&gt; declare a type that prevents other types from being assigned to it. The below example we see that anything can be assigned to the &lt;code&gt;language&lt;/code&gt; variable. We can assign a &lt;code&gt;number&lt;/code&gt; or a &lt;code&gt;boolean&lt;/code&gt; or an &lt;code&gt;object&lt;/code&gt; to it if we later wanted, but that may cause bugs in the future if we were not expecting the variable type to be something other than a string.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;language&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In Typescript, we get more control over declaring types. See below, now we can only assign a &lt;code&gt;string&lt;/code&gt; to the &lt;code&gt;language&lt;/code&gt; variable, which is much better. Now when we access this variable in the future, we are pretty certain that the value will be a string and proceed accordingly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;language&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;But we can do better&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="union-types"&gt;Union Types&lt;/h2&gt;
&lt;p&gt;With Typescript Union Types, we can say something can be &lt;em&gt;more&lt;/em&gt; than one type. 😮 In the below example, we see that the &lt;code&gt;language&lt;/code&gt; variable can either be a &lt;code&gt;string&lt;/code&gt; OR a &lt;code&gt;number&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;language&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You might be saying to yourself, &amp;ldquo;cool, but why would I want two different types in one variable?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This is a great question, but before we figure out why we would need this, we need to understand that anything can be considered a type in Typescript, including specific string values.&lt;/p&gt;
&lt;p&gt;So now we can specify exactly which values can be assigned to the &lt;code&gt;language&lt;/code&gt; variable.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;language&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;en&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;fr&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;ru&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can only assign certain &lt;em&gt;values&lt;/em&gt; to &lt;code&gt;language&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The interesting question now is, &amp;ldquo;how do we know which type is currently stored?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;If we have a variable that can hold two different types, when we access that value, we must check to see what the type is before we do something with it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nameOrID&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Jason&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;typeof&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nameOrID&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something with string...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;typeof&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;nameOrID&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;number&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// do something with number...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is important, because if we do not check the value type then we do not know which one of the types is currently being used - so we might try to do math with a string, or do a string operation on a number&amp;hellip;&lt;/p&gt;
&lt;p&gt;Knowing these things, now we can explain Typescript&amp;rsquo;s &lt;strong&gt;Discriminated Union Type&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="discriminated-union-types"&gt;Discriminated Union Types&lt;/h2&gt;
&lt;p&gt;Using the things we learned about Union Types, we can construct a special union that obeys some rules.&lt;/p&gt;
&lt;p&gt;The rules that should be followed are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;All types in the union, share a common property.&lt;/li&gt;
&lt;li&gt;There needs to be a union type declared from the types.&lt;/li&gt;
&lt;li&gt;There must be type guards on the common propery.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HockeyGame&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hockey&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Rule 1 - common property &amp;#39;kind&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;homeScore&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;awayScore&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;clock&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;isDone&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;boolean&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BaseballGame&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;baseball&amp;#39;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Rule 1 - common property &amp;#39;kind&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;inning&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;isTop&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;boolean&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;stadium&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Rule 2 - Union type declared
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Game&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HockeyGame&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BaseballGame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;gameToString&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Game&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Rule 3 - Type guard on the common property
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hockey&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`Hockey game clock: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;clock&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toString&lt;/span&gt;()&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;baseball&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;frame&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;isTop&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;top&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bottom&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`Baseball game is in the &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;frame&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; of inning &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;inning&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example above, we see that we used what we learned about assigning specific strings to a type with the &lt;code&gt;kind&lt;/code&gt; property. The kind property can only ever be &lt;code&gt;hockey&lt;/code&gt; or &lt;code&gt;baseball&lt;/code&gt; and never anything else.&lt;/p&gt;
&lt;p&gt;This common property acts as an ID for the object and allows us to know what other properties are defined and available to be accessed.&lt;/p&gt;
&lt;p&gt;Following these rules will allow the Typescript compiler to know which fields are available. So if you have checked the guard and deemed it to be &lt;code&gt;hockey&lt;/code&gt; then the compiler will only allow you to access the fields from the &lt;code&gt;HockeyGame&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;This can prevent a lot &lt;code&gt;undefined&lt;/code&gt; errors you may get from accessing properties that &lt;em&gt;may or may not&lt;/em&gt; be there at different times.&lt;/p&gt;
&lt;h2 id="adts-with-react"&gt;ADT&amp;rsquo;s with React&lt;/h2&gt;
&lt;p&gt;Now let&amp;rsquo;s see how we can take advantage of this pattern in React.&lt;/p&gt;
&lt;p&gt;Using the Game types declared above, we can safely render different components based on the common property in the union.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-tsx" data-lang="tsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;HockeyGameBox&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;game&lt;/span&gt; }&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;HockeyGame&lt;/span&gt; }) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;homeScore&lt;/span&gt;} &lt;span style="color:#f92672"&gt;-&lt;/span&gt; {&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;awayScore&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BaseballGameBox&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;game&lt;/span&gt; }&lt;span style="color:#f92672"&gt;:&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;BaseballGame&lt;/span&gt; }) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;inning&lt;/span&gt;} &lt;span style="color:#f92672"&gt;-&lt;/span&gt; {&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stadium&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;renderGame&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Game&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;kind&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;hockey&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;HockeyGameBox&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;} /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;baseball&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;BaseballGameBox&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;game&lt;/span&gt;} /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GamePage&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; [&lt;span style="color:#a6e22e"&gt;games&lt;/span&gt;] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;useState&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;Game&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;[]&lt;/span&gt;&amp;gt;([
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;/* mix of different games */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;games&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;renderGame&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, using ADT&amp;rsquo;s can greatly reduce the amount of runtime bugs you get when using dynamic data. It&amp;rsquo;s not a silver bullet for preventing bugs, but it&amp;rsquo;s a step in the right direction.&lt;/p&gt;
&lt;p&gt;To learn more about ADT&amp;rsquo;s, check out my post about it in Elm: &lt;a href="/posts/elm-remote-data/"&gt;Elm&amp;rsquo;s Remote Data Type in Javascript&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Lessons learned from my first 10k LOC in Elm</title><link>/posts/elm-lessons/</link><pubDate>Thu, 24 Oct 2019 00:00:00 +0000</pubDate><guid>/posts/elm-lessons/</guid><description>&lt;p&gt;I have been working on a personal project of mine for the last couple of months that has the frontend written in Elm. So far everything is going great and the project is around 10k lines of code.&lt;/p&gt;
&lt;p&gt;I have noticed a few reoccurring patterns of mine that I have learned so far and want to share, so here are 5 things I have learned:&lt;/p&gt;
&lt;h2 id="1-decoding-empty-lists--strings"&gt;1. Decoding Empty Lists &amp;amp; Strings&lt;/h2&gt;
&lt;p&gt;When I first started the project, I had a lot of types with fields declared like this:&lt;/p&gt;</description><content>&lt;p&gt;I have been working on a personal project of mine for the last couple of months that has the frontend written in Elm. So far everything is going great and the project is around 10k lines of code.&lt;/p&gt;
&lt;p&gt;I have noticed a few reoccurring patterns of mine that I have learned so far and want to share, so here are 5 things I have learned:&lt;/p&gt;
&lt;h2 id="1-decoding-empty-lists--strings"&gt;1. Decoding Empty Lists &amp;amp; Strings&lt;/h2&gt;
&lt;p&gt;When I first started the project, I had a lot of types with fields declared like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;alias&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Something&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { name &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , stuff &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;List&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and the way I was decoding these values from my API was like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Json.Decode&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Json.Decode.Pipeline&lt;/span&gt; exposing (optional)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;succeed &lt;span style="color:#66d9ef"&gt;Something&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&amp;gt;&lt;/span&gt; optional &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;nullable &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;string) &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&amp;gt;&lt;/span&gt; optional &lt;span style="color:#e6db74"&gt;&amp;#34;stuff&amp;#34;&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;nullable (&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;list &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;string)) &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This was fine at first, but I noticed that after awhile I was repeating logic inside my update functions to check &lt;strong&gt;if the &lt;code&gt;name&lt;/code&gt; field was an empty string, or if the &lt;code&gt;stuff&lt;/code&gt; field was an empty list&lt;/strong&gt;, and if it was, change the value to &lt;code&gt;Nothing&lt;/code&gt; instead of &lt;code&gt;Just &amp;quot;&amp;quot;&lt;/code&gt; or &lt;code&gt;Just []&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So after awhile, I thought it would be more efficient to check for empty strings and empty lists during the decoding phase, so I came up with two decoder helper functions, &lt;code&gt;decodeNonEmptyString&lt;/code&gt; and &lt;code&gt;decodeNonEmptyList&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;decodeNonEmptyString &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Decoder&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;decodeNonEmptyString &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;andThen (notEmptyString &lt;span style="color:#a6e22e"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;succeed) &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;string
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;decodeNonEmptyList &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Decoder&lt;/span&gt; a &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Decoder&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;List&lt;/span&gt; a))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;decodeNonEmptyList l &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;andThen (notEmptyList &lt;span style="color:#a6e22e"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;succeed) (&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;maybe (&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;list l))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;notEmptyList &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;List&lt;/span&gt; a) &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;List&lt;/span&gt; a)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;notEmptyList &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;andThen (&lt;span style="color:#a6e22e"&gt;\&lt;/span&gt;l &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;List&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;isEmpty l &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Just&lt;/span&gt; l
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;notEmptyString &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Maybe&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;notEmptyString s &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;isEmpty s &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Just&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So now my original decoders use these new utilities like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;succeed &lt;span style="color:#66d9ef"&gt;Something&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&amp;gt;&lt;/span&gt; optional &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt; decodeNonEmptyString &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&amp;gt;&lt;/span&gt; optional &lt;span style="color:#e6db74"&gt;&amp;#34;stuff&amp;#34;&lt;/span&gt; (decodeNonEmptyList &lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;string) &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And I don&amp;rsquo;t need to check for emptiness anymore in my update functions 🎉&lt;/p&gt;
&lt;h2 id="2-flatter-pattern-matching"&gt;2. Flatter pattern matching&lt;/h2&gt;
&lt;p&gt;This one might seem really obvious, but took me awhile to realize that doing this results in flatter pattern matching functions.&lt;/p&gt;
&lt;p&gt;If I have a type like &lt;code&gt;RD.WebData (Maybe (List Person))&lt;/code&gt;, the way I original matched on it was like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; response &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;NotAsked&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Not Asked&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Loading&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Loading&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Failure&lt;/span&gt; e &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Error&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Success&lt;/span&gt; maybeData &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; maybeData &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;No data&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Just&lt;/span&gt; data &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Data!&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But I realized that I could flatten this into one case statement instead of 2 separate ones like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; response &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;NotAsked&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Not Asked&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Loading&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Loading&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Failure&lt;/span&gt; e &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Error&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Success&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Nothing&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;No data&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;RD&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Success&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;Just&lt;/span&gt; data) &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [text &lt;span style="color:#e6db74"&gt;&amp;#34;Data!&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See? Much nicer!&lt;/p&gt;
&lt;h2 id="3-select-wrapper"&gt;3. Select Wrapper&lt;/h2&gt;
&lt;p&gt;This is one of the first abstractions I made when I started because I wanted an easy reusable way to use &lt;code&gt;select [] []&lt;/code&gt; and found that the native one in Elm is not as nice as I hoped.&lt;/p&gt;
&lt;p&gt;So I wrote a small wrapper called &lt;code&gt;viewSelect&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;viewSelect &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Bool&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;String&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; msg) &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;List&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Html&lt;/span&gt; msg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;viewSelect disabled changeMsg options &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; select
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [ onChange changeMsg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , &lt;span style="color:#66d9ef"&gt;Html&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Styled&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Attributes&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;disabled disabled
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#66d9ef"&gt;List&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;map
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (&lt;span style="color:#a6e22e"&gt;\&lt;/span&gt;opt &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; option
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [ value opt&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;value
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , &lt;span style="color:#66d9ef"&gt;Html&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Styled&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Attributes&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;selected opt&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;selected
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , &lt;span style="color:#66d9ef"&gt;Html&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Styled&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Attributes&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;disabled opt&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;disabled
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [ text opt&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;text ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; options
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;alias&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Option&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { text &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , value &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , selected &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , disabled &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;onChange &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;String&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; msg) &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Html&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Styled&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Attribute&lt;/span&gt; msg
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;onChange tagger &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; on &lt;span style="color:#e6db74"&gt;&amp;#34;change&amp;#34;&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;D&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;map tagger &lt;span style="color:#66d9ef"&gt;Html&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Styled&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Events&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;targetValue)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now I use &lt;code&gt;viewSelect&lt;/code&gt; instead of the native &lt;code&gt;select&lt;/code&gt; and I just need to pass in a list of &lt;code&gt;Option&lt;/code&gt; instead. Every time a user changes the select box, the changeMsg fires with the new value.&lt;/p&gt;
&lt;h2 id="4-changefield-pattern"&gt;4. ChangeField Pattern&lt;/h2&gt;
&lt;p&gt;In my app, I have a lot of forms, and every form needs to modify some field inside my model. The way I originally started doing this was:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Msg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ChangeName&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ChangeAge&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ChangeHeight&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ChangeWeight&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;update msg model &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; msg &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ChangeName&lt;/span&gt; name &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; ({ model &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; name &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; name }, &lt;span style="color:#66d9ef"&gt;Cmd&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;none)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ChangeAge&lt;/span&gt; age &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; ({ model &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; age &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; age }, &lt;span style="color:#66d9ef"&gt;Cmd&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;none)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ChangeHeight&lt;/span&gt; height &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; ({ model &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; height &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; height }, &lt;span style="color:#66d9ef"&gt;Cmd&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;none)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ChangeWeight&lt;/span&gt; weight &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; ({ model &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; weight &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; weight }, &lt;span style="color:#66d9ef"&gt;Cmd&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;none)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This was also fine at first, but my app has A LOT of forms and this was not scaling well. So instead of creating a new Msg type for every field, I created &lt;strong&gt;one&lt;/strong&gt; Msg type for updating any field. And it works like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Msg&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ChangeField&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;String&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Person&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Person&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;update msg model &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; msg &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;ChangeField&lt;/span&gt; setter content &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; (setter content model, &lt;span style="color:#66d9ef"&gt;Cmd&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;none)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now every time a field needs to change, instead of calling &lt;code&gt;ChangeName &amp;quot;Jason&amp;quot;&lt;/code&gt;, I can now call &lt;code&gt;ChangeField setName &amp;quot;Jason&amp;quot;&lt;/code&gt; where setName equals:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;setName &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Person&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Person&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;setName content person &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { person &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; name &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; content }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This allows me to create individual setter functions for each field and do any data manipulations from String into any type I need.&lt;/p&gt;
&lt;p&gt;It simplifies my update function by reducing the amount of Msg types it can match on, and it nicely separates out my data manipulation logic for each field.&lt;/p&gt;
&lt;h2 id="5-posix-wrappers"&gt;5. Posix Wrappers&lt;/h2&gt;
&lt;p&gt;This one is pretty simple really. I use Elm&amp;rsquo;s &lt;code&gt;Time.Posix&lt;/code&gt; type a lot around my app, so I needed functions to format, manipulate and display Posix in my UI. I came up with a few helpers for this and call it my HumanTime module:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanDateTime &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanDateTime z p &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; humanDate z p &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; humanTime z p
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanTime &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanTime z p &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; humanHour z p &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;:&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; humanMinute z p
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanDate &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanDate z p &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; humanMonth z p &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34; &amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; humanDay z p &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;, &amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; humanYear z p
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanYear &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanYear z &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; toYear z &lt;span style="color:#a6e22e"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;fromInt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanDay &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanDay z &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; toDay z &lt;span style="color:#a6e22e"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;fromInt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanHour &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanHour z &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; toHour z &lt;span style="color:#a6e22e"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;fromInt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanMinute &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanMinute z &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; toMinute z
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;\&lt;/span&gt;m &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; m &lt;span style="color:#a6e22e"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;9&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;fromInt m
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;fromInt m
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanMonth &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Zone&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Posix&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;humanMonth z p &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; toMonth z p &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Jan&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Jan&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Feb&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Feb&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Mar&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Mar&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Apr&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Apr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;May&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;May&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Jun&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Jun&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Jul&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Jul&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Aug&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Aug&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Sep&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Sep&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Oct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Oct&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Nov&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Nov&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Dec&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Dec&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that is it so far! I am sure I will learn even more in the next 10k LOC that I write and might even figure out better ways of doing these things that I just mentioned.&lt;/p&gt;
&lt;p&gt;Elm is an amazing tool for creating frontends and I can&amp;rsquo;t ever see myself going back to React or any other non-functional frameworks for personal projects.&lt;/p&gt;</content></item><item><title>Pratica, now fully in Typescript!</title><link>/posts/ts-pratica/</link><pubDate>Fri, 18 Oct 2019 00:00:00 +0000</pubDate><guid>/posts/ts-pratica/</guid><description>&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/rametta/pratica"&gt;Pratica&lt;/a&gt; is now written completely in Typescript!&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="what-is-pratica"&gt;What is Pratica?&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/rametta/pratica"&gt;Pratica&lt;/a&gt; is a super tiny &lt;em&gt;720B&lt;/em&gt; monadic library, comparable to Crocks or Monet JS.&lt;/p&gt;
&lt;h3 id="why-would-i-use-pratica"&gt;Why would I use Pratica?&lt;/h3&gt;
&lt;p&gt;If you want to start writing more functional code in Javascript or Typescript, this is a great library for learning some FP fundamentals, while also making your code safer and more resilient to runtime bugs. It&amp;rsquo;s super tiny size and easy to read dot-chaining syntax makes it easy to get started in any project.&lt;/p&gt;</description><content>&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/rametta/pratica"&gt;Pratica&lt;/a&gt; is now written completely in Typescript!&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="what-is-pratica"&gt;What is Pratica?&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/rametta/pratica"&gt;Pratica&lt;/a&gt; is a super tiny &lt;em&gt;720B&lt;/em&gt; monadic library, comparable to Crocks or Monet JS.&lt;/p&gt;
&lt;h3 id="why-would-i-use-pratica"&gt;Why would I use Pratica?&lt;/h3&gt;
&lt;p&gt;If you want to start writing more functional code in Javascript or Typescript, this is a great library for learning some FP fundamentals, while also making your code safer and more resilient to runtime bugs. It&amp;rsquo;s super tiny size and easy to read dot-chaining syntax makes it easy to get started in any project.&lt;/p&gt;
&lt;h3 id="how-do-i-start"&gt;How do I start?&lt;/h3&gt;
&lt;p&gt;You can install it with: &lt;code&gt;yarn add pratica&lt;/code&gt; or &lt;code&gt;npm i pratica&lt;/code&gt;. Then you can import the main functions like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;nullable&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pratica&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create small, safe and easy to read programs by composing functions together, like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ts" data-lang="ts"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Typescript
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;nullable&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;parseDate&lt;/span&gt; } &lt;span style="color:#66d9ef"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pratica&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getPersonAge&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;person?&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;Person&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;number&lt;/span&gt;&amp;gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;nullable&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;string&lt;/span&gt;&amp;gt;([&lt;span style="color:#e6db74"&gt;&amp;#39;birthday&amp;#39;&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;parseDate&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;birthday&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; Date.&lt;span style="color:#a6e22e"&gt;now&lt;/span&gt;() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;birthday&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getTime&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;parseDate&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;date&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; Math.&lt;span style="color:#a6e22e"&gt;abs&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;getUTCFullYear&lt;/span&gt;() &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1970&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;getPersonAge&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;birthday&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;1994-06-08&amp;#39;&lt;/span&gt; }) &lt;span style="color:#75715e"&gt;// -&amp;gt; Just(25)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;getPersonAge&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;birthday&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;771033600000&lt;/span&gt; }) &lt;span style="color:#75715e"&gt;// -&amp;gt; Just(25)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;getPersonAge&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;birthday&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt; }) &lt;span style="color:#75715e"&gt;// -&amp;gt; Nothing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;getPersonAge&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// -&amp;gt; Nothing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pratica works great with React too! Use it in your JSX for handling cases with missing data.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;viewPersonAge&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; }) =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;getPersonAge&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt; =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;No&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;available&lt;/span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="try-it-out"&gt;Try it out&lt;/h3&gt;
&lt;p&gt;Try it out in an online browser sandbox &lt;a href="https://fpjs.surge.sh/?script=const%20%7B%20nullable%20%7D%20%3D%20P%0A%0Anullable%2812%29%0A%20%20.map%28x%20%3D%3E%20x%20%2B%208%29%0A%20%20.cata%28%7B%0A%20%20%20%20Just%3A%20x%20%3D%3E%20x%2C%0A%20%20%20%20Nothing%3A%20%28%29%20%3D%3E%20%27%F0%9F%A7%A8%27%0A%20%20%7D%29"&gt;here!&lt;/a&gt;&lt;/p&gt;</content></item><item><title>Elm's Remote Data Type in Javascript</title><link>/posts/elm-remote-data/</link><pubDate>Fri, 26 Jul 2019 00:00:00 +0000</pubDate><guid>/posts/elm-remote-data/</guid><description>&lt;p&gt;Often in web development there is this recurring pattern of having to fetch some data from some server through a rest api, and then show it someway in the UI.&lt;/p&gt;
&lt;p&gt;This often includes storing this data somewhere on the client side, either in a store or just a variable you can reference, and this is where the Remote Data type can help.&lt;/p&gt;
&lt;p&gt;Usually saving the data would look something like this in JS:&lt;/p&gt;</description><content>&lt;p&gt;Often in web development there is this recurring pattern of having to fetch some data from some server through a rest api, and then show it someway in the UI.&lt;/p&gt;
&lt;p&gt;This often includes storing this data somewhere on the client side, either in a store or just a variable you can reference, and this is where the Remote Data type can help.&lt;/p&gt;
&lt;p&gt;Usually saving the data would look something like this in JS:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Javascript
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/api/data&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and showing it on screen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// React
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyComp&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; }) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;className&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But there are a few problems with this approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What do we show on screen when the data is loading from the server?&lt;/li&gt;
&lt;li&gt;What do we show on screen before we even request the data from the server?&lt;/li&gt;
&lt;li&gt;Do we properly clear the previous error if the data is a success?&lt;/li&gt;
&lt;li&gt;Do we properly clear the previous data if we get an error?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So how can we solve this?&lt;/p&gt;
&lt;p&gt;Some might recommend we can add more fields to our state to help represent all the cases, like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Javascript
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;isAsked&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and in the UI would be similar to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// React
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyComp&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;isAsked&lt;/span&gt; }) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;isAsked&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;asked&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;yet&lt;/span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;loading&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;...&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;className&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Some&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fallback&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;to&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;be&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;safe&lt;/span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But the problem with this is that it becomes too easy for our UI to accidently show the wrong case by forgetting to set loading to false after the data comes back as an error, or forgetting to clear the error if a retry returned a success.&lt;/p&gt;
&lt;p&gt;Infact, optimistically the structure above can have a cardinality of &lt;code&gt;2 x 2 x 2 x 2&lt;/code&gt; which is 16 possible different combinations of states we can be in at any given time. That is a lot of cases to represent.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at how Elm simplifies this process with needing only 4 cases.&lt;/p&gt;
&lt;h2 id="remote-data-in-elm"&gt;Remote Data in Elm&lt;/h2&gt;
&lt;p&gt;The Remote Data type can be created manually by writing a custom type like below, or by using a pre-made version from a library like &lt;a href="https://package.elm-lang.org/packages/krisajenkins/remotedata/latest/RemoteData"&gt;krisajenkins/remotedata&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Elm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;RemoteData&lt;/span&gt; e a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NotAsked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Loading&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Error&lt;/span&gt; e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Success&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and then using this type as your model:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Elm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;alias&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Model&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;RemoteData&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;MyData&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- and set the initial model value as NotAsked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;init &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NotAsked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What we need to understand is that our state can only be one of these 4 types at any time. We can not both be in a Loading state and in a Success state at the same time, or else our UI will be showing 2 different things. This is why our cardinality is only &lt;strong&gt;4&lt;/strong&gt; now instead of &lt;strong&gt;16&lt;/strong&gt;, because there is no way to represent our state more than that.&lt;/p&gt;
&lt;p&gt;Using this model we can now create a UI for each case like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;-- Elm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;view model &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; model &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;NotAsked&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [ text &lt;span style="color:#e6db74"&gt;&amp;#34;Not asked yet&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Loading&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [ text &lt;span style="color:#e6db74"&gt;&amp;#34;Loading...&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Error&lt;/span&gt; err &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [ text err ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Success&lt;/span&gt; data &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt; div [] [ text &lt;span style="color:#a6e22e"&gt;&amp;lt;|&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Here is my data: &amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;++&lt;/span&gt; data ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now whenever we update our state, we never need to worry about clearing previous state or forgetting to flip one field to null - because there is only one field in our model.&lt;/p&gt;
&lt;p&gt;This is a great pattern for handling remote data fetching in Elm, but how do we take advantage of this pattern in Javascript? Daggy.&lt;/p&gt;
&lt;h2 id="daggy"&gt;Daggy&lt;/h2&gt;
&lt;p&gt;There are a few different libraries in Javascript that can help model your application with Algebraic Data Types like we have in Elm with the &lt;code&gt;type&lt;/code&gt; keyword. One popular library is &lt;a href="https://www.npmjs.com/package/daggy"&gt;Daggy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To represent remote data in Daggy, we would create a type like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Javascript
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;taggedSum&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;daggy&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RemoteData&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;taggedSum&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;RemoteData&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;NotAsked&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Error&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;e&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Success&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then once we have our type, the implementation is almost identical to how we would work in Elm.&lt;/p&gt;
&lt;p&gt;Our state would only have one field instead of 4, and a cardinality of 4 instead of 16.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Javascript
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RemoteData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NotAsked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Fetch some data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RemoteData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/api/data&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RemoteData&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Success&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RemoteData&lt;/span&gt;.Error(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And in our UI, like React, we would have:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// React
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyComp&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;}) =&amp;gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;NotAsked&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Not&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;asked&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;yet&lt;/span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;...&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Error&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Success&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;d&lt;/span&gt; =&amp;gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;span style="color:#a6e22e"&gt;Here&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;is&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;my&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {&lt;span style="color:#a6e22e"&gt;d&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using this pattern actually helps move a lot of render logic out of your components in React, like checking fields with &lt;code&gt;if (field) {...}&lt;/code&gt; and instead moves that responsibility to something like a reducer, which will make it a lot easier to run unit tests on.&lt;/p&gt;
&lt;p&gt;If you would like to learn more about Algebraic Data Types in Javascript, check out these links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/fullstack-academy/better-js-cases-with-sum-types-92876e48fd9f"&gt;Better JS with Sum Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html"&gt;How Elm slays a UI antipattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/daggy"&gt;Daggy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/pratica"&gt;Pratica&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you like this article, be sure to &lt;a href="https://dev.to/rametta"&gt;follow me&lt;/a&gt;!&lt;/p&gt;</content></item><item><title>Comparing Elm to React/Redux</title><link>/posts/elm-react-redux/</link><pubDate>Thu, 11 Jul 2019 00:00:00 +0000</pubDate><guid>/posts/elm-react-redux/</guid><description>&lt;p&gt;I have recently been exploring creating web apps in &lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt; and found it to be a breath of fresh air compared to the usual React/Redux projects I have worked on in the past.&lt;/p&gt;
&lt;p&gt;*&lt;em&gt;Disclaimer: I still think React/Redux is great and viable for large teams if done correctly. This article will just explain my pain points with it while working on large teams at various companies, and why I think Elm can be a better alternative in some cases.&lt;/em&gt;&lt;/p&gt;</description><content>&lt;p&gt;I have recently been exploring creating web apps in &lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt; and found it to be a breath of fresh air compared to the usual React/Redux projects I have worked on in the past.&lt;/p&gt;
&lt;p&gt;*&lt;em&gt;Disclaimer: I still think React/Redux is great and viable for large teams if done correctly. This article will just explain my pain points with it while working on large teams at various companies, and why I think Elm can be a better alternative in some cases.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="pain-points"&gt;Pain Points&lt;/h2&gt;
&lt;p&gt;After awhile many of the React/Redux projects I have worked on become massive, with hundreds of reducers, hundreds of components, mixtures of epics, thunks, reselect selectors, sagas and custom middlewares. Hot module replacement becomes slow, build times become slow, runtime performance gets slow, audit scores get low scores, bundle size gets big and the app gets an increasingly large amount of runtime errors with every push.&lt;/p&gt;
&lt;p&gt;I know this is not everyone&amp;rsquo;s experience, and if you work somewhere that enforces strict rules during development, then you will not have all these problems. But chances are you have experienced a few of these pain points too. (And if you haven&amp;rsquo;t experienced any of these pains, then good work, it&amp;rsquo;s a difficult feat)&lt;/p&gt;
&lt;p&gt;When I speak of development &amp;ldquo;rules&amp;rdquo;, I don&amp;rsquo;t mean linter rules and prettier. I mean things like not installing too many third party libraries, having proper code splitting for your modules, and performing weekly or monthly lighthouse audits to see where your team can improve.&lt;/p&gt;
&lt;h2 id="the-solution"&gt;The Solution&lt;/h2&gt;
&lt;p&gt;Elm has a beautiful ecosystem meant to prevent a lot of these pains. It comes with its own struggles too for sure, but worth it, in my opinion.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advantages of Elm:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No runtime exceptions&lt;/li&gt;
&lt;li&gt;Everything is immutable&lt;/li&gt;
&lt;li&gt;Small bundle sizes&lt;/li&gt;
&lt;li&gt;Built-in event emitter and global state store similar to Redux&lt;/li&gt;
&lt;li&gt;Built-in router for single page apps&lt;/li&gt;
&lt;li&gt;Built-in code formatter (like prettier)&lt;/li&gt;
&lt;li&gt;Strong type system&lt;/li&gt;
&lt;li&gt;Easy interop with JS&lt;/li&gt;
&lt;li&gt;Amazing compiler error messages and fast compile times&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These advantages lead to more reliable webapps, better DX, and a better experience for end users.&lt;/p&gt;
&lt;h2 id="comparing-the-elm-architecture-to-reactredux"&gt;Comparing the Elm architecture to React/Redux&lt;/h2&gt;
&lt;p&gt;Learning Elm can seem like a daunting task, especially with all the new syntax and concepts, but this is what this article is aimed to help with and explain that it&amp;rsquo;s really not that different to React.&lt;/p&gt;
&lt;p&gt;Below, I have written the same app in Elm and React/Redux to show their similarities.&lt;/p&gt;
&lt;h3 id="state"&gt;State&lt;/h3&gt;
&lt;p&gt;In Redux there is a global store used for saving application state, Elm has a similar concept called the Model, it is a strongly typed version of a store.&lt;/p&gt;
&lt;p&gt;Redux initial state for a reducer&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initialState&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Elm initial model and typings&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;alias&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Model&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { count &lt;span style="color:#a6e22e"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Int&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;initialModel &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { count &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The type alias in Elm ensures that nothing other than a number will ever be assigned in the count property.&lt;/p&gt;
&lt;h3 id="actions"&gt;Actions&lt;/h3&gt;
&lt;p&gt;In Redux, you need to write actions for triggering some state changes or side effects. Elm has Messages which are very similar, but typed!&lt;/p&gt;
&lt;p&gt;Redux Actions&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// action types
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;INCREMENT&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;INCREMENT&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DECREMENT&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;DECREMENT&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// actions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;increase&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () =&amp;gt; ({ &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;INCREMENT&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;decrease&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () =&amp;gt; ({ &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DECREMENT&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Elm Messages&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Msg&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Increase&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Decrease&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="reducers"&gt;Reducers&lt;/h3&gt;
&lt;p&gt;For every redux action you create, you normally have a corresponding reducer. In Elm it is almost the same except you are forced to always have an update function (reducer) for every message (action).&lt;/p&gt;
&lt;p&gt;Redux Reducers&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;myReducer&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;initialState&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;action&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;action&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;INCREMENT&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DECREMENT&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Elm Update&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;update msg model &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; msg &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Increase&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { model &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; count &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; model&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;count &lt;span style="color:#a6e22e"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Decrease&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;-&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { model &lt;span style="color:#a6e22e"&gt;|&lt;/span&gt; count &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; model&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;count &lt;span style="color:#a6e22e"&gt;-&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Everything is immutable in Elm, so to update a record (object) you must use the pipe | and new record syntax to return a new copy of the state with the updated property.&lt;/p&gt;
&lt;h3 id="components"&gt;Components&lt;/h3&gt;
&lt;p&gt;Components in React are what create the view that will be rendered for users to see. Elm does not have components but just a single view function that will render.&lt;/p&gt;
&lt;p&gt;React JSX&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-redux&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;increase&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;decrease&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./reducer&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;increase&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;decrease&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt; }) =&amp;gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;button&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;increase&lt;/span&gt;}&amp;gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;{&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;}&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;button&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;decrease&lt;/span&gt;}&amp;gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Connect to redux
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mapStateToProps&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ({ &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt; }) =&amp;gt; ({ &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mapDispatchToProps&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;increase&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;decrease&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mapStateToProps&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;mapDispatchToProps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)(&lt;span style="color:#a6e22e"&gt;App&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Elm view function&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;view model &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; div []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [ button [ onClick &lt;span style="color:#66d9ef"&gt;Increment&lt;/span&gt; ] [ text &lt;span style="color:#e6db74"&gt;&amp;#34;+1&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , div [] [ text &lt;span style="color:#a6e22e"&gt;&amp;lt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;String&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;fromInt model&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;count ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , button [ onClick &lt;span style="color:#66d9ef"&gt;Decrement&lt;/span&gt; ] [ text &lt;span style="color:#e6db74"&gt;&amp;#34;-1&amp;#34;&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="connecting"&gt;Connecting&lt;/h3&gt;
&lt;p&gt;In React/Redux, components do not automatically have access to the redux store or actions/reducers, they must explicitly be connected. Connecting can be done nicely with another library called react-redux. In Elm, everything automatically has access to all the message types and data in the store.&lt;/p&gt;
&lt;p&gt;React/Redux&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-dom&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Provider&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react-redux&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;createStore&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;redux&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;myReducer&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./reducers&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;App&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./App&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;store&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;createStore&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;myReducer&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;Provider&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;store&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;store&lt;/span&gt;}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;App&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;Provider&lt;/span&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; document.&lt;span style="color:#a6e22e"&gt;getElementById&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;root&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Elm&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-elm" data-lang="elm"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;main &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Browser&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.&lt;/span&gt;sandbox
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { init &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; initialModel
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , update &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , view &lt;span style="color:#a6e22e"&gt;=&lt;/span&gt; view
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So we created a simple counter app. Overall it was pretty painless, didn&amp;rsquo;t require any of the boilerplate that redux needs, and had typed payloads! If you want to play with this example, check it out on &lt;a href="https://ellie-app.com"&gt;ellie-app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If this article intrigued you and you want to learn more about Elm, check out these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://guide.elm-lang.org/"&gt;Official Elm Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elmprogramming.com/"&gt;Elm Programming Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elm-lang.org/docs/syntax"&gt;Elm Syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elm-lang.org/docs/from-javascript"&gt;Elm Syntax VS Javascript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Follow me on twitter! &lt;a href="https://twitter.com/rametta"&gt;@rametta&lt;/a&gt;&lt;/p&gt;</content></item><item><title>F# for JS Devs</title><link>/posts/fsharp-js/</link><pubDate>Fri, 15 Mar 2019 00:00:00 +0000</pubDate><guid>/posts/fsharp-js/</guid><description>&lt;p&gt;I recently gave an internal talk at my work about the similarities of F# compared to JS. It was generally well received, and I would like to convert that talk into a blog post for others who may be interested.&lt;/p&gt;
&lt;p&gt;This is by no means an exhaustive list of features in F#, but the point of this post is to show familiar JS code and how it can be written equivalently in F#, because I believe showing examples like this is the best way of learning a new language and has a better chance of adoption.&lt;/p&gt;</description><content>&lt;p&gt;I recently gave an internal talk at my work about the similarities of F# compared to JS. It was generally well received, and I would like to convert that talk into a blog post for others who may be interested.&lt;/p&gt;
&lt;p&gt;This is by no means an exhaustive list of features in F#, but the point of this post is to show familiar JS code and how it can be written equivalently in F#, because I believe showing examples like this is the best way of learning a new language and has a better chance of adoption.&lt;/p&gt;
&lt;h2 id="intro"&gt;Intro&lt;/h2&gt;
&lt;p&gt;F# is a functional language that runs on the .NET runtime. It is cross platform now with the intro of .NET Core so it can be written and ran on any machine. It is immutable by default, but is completely interoperable with C# or VB. It is inspired by Haskell, Scala, Erlang, C# and Python.&lt;/p&gt;
&lt;p&gt;F# can be used for creating servers, scripts, desktop apps and mobile apps. (Even webapps, by compiling to JS directly with tools like &lt;a href="https://fable.io/"&gt;fable&lt;/a&gt;)&lt;/p&gt;
&lt;h2 id="functions"&gt;Functions&lt;/h2&gt;
&lt;p&gt;Functions are the core of F#. There are essentially two types of functions, named and anonymous. The syntax is similar to JS but slightly shorter. In F#, all functions are curried automatically, which means all functions can be partially applied without any extra work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mul&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; &lt;span style="color:#75715e"&gt;// curried
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;mul&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;)(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 16
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; add x y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; mul x y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;add 4 4 &lt;span style="color:#75715e"&gt;// 8
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mul 4 4 &lt;span style="color:#75715e"&gt;// 16
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// anonymous
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; sub &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; x y &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; x &lt;span style="color:#f92672"&gt;-&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sub 8 4 &lt;span style="color:#75715e"&gt;// 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="composition"&gt;Composition&lt;/h2&gt;
&lt;p&gt;Function composition is the process of passing the output of one function as the input to another function. In JS, one would need to nest their functions, or use a pipe or compose function as a helper to achieve this. In F# there is the pipeline operator &lt;code&gt;|&amp;gt;&lt;/code&gt;, the forward composition operator &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; and backwards composition operator &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="pipeline-operator"&gt;Pipeline Operator&lt;/h3&gt;
&lt;p&gt;The pipeline operator just allows having the function argument be infront of the function instead of after it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add3&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mul5&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;div2&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;div2&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;mul5&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;add3&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;97&lt;/span&gt;))) &lt;span style="color:#75715e"&gt;// 250
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; add3 x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; mul5 x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; div2 x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;/&lt;/span&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;97 &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; add3 &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; mul5 &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; div2 &lt;span style="color:#75715e"&gt;// 250
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="composition-operator"&gt;Composition Operator&lt;/h3&gt;
&lt;p&gt;The composition operator allows combining functions into one. The difference between this and the pipeline is that only functions can be composed together, whereas the pipeline can take any value and pass it to the next function.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;compose&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;..&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;add3&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mul5&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;div2&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;doMath&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;compose&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;div2&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;mul5&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;add3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;doMath&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;97&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// 250
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; add3 x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; mul5 x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; div2 x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;/&lt;/span&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; doMath &lt;span style="color:#f92672"&gt;=&lt;/span&gt; add3 &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; mul5 &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; div2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// or backwards
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; doMath &lt;span style="color:#f92672"&gt;=&lt;/span&gt; div2 &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; mul5 &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; add3
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;doMath 97 &lt;span style="color:#75715e"&gt;// 250
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="lists"&gt;Lists&lt;/h2&gt;
&lt;p&gt;F# lists are pretty similar to JS arrays. Although F# has 3 types of array-like collections. Lists, Arrays, and Sequences. But I&amp;rsquo;ll just focus on Lists because they are the richest.&lt;/p&gt;
&lt;h3 id="list-mapping"&gt;List Mapping&lt;/h3&gt;
&lt;p&gt;List mapping looks almost the same in F# as it does in JS, except for the fact that you must use the &lt;code&gt;List.map&lt;/code&gt; function instead of using the array prototype to dot chain like you do in JS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// [2, 4, 6]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;;&lt;/span&gt; 2&lt;span style="color:#f92672"&gt;;&lt;/span&gt; 3&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;List.map &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; x &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; 2&lt;span style="color:#f92672"&gt;)&lt;/span&gt; data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// [2, 4, 6]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="list-transformations"&gt;List Transformations&lt;/h3&gt;
&lt;p&gt;JS is praised for it&amp;rsquo;s rich array prototype functions like map, filter, find, reduce. F# has all of those, and more than 60 others! Such as List.sum, List.average, List.distict, List.isEmpty, List.chunkBySize and &lt;a href="https://msdn.microsoft.com/visualfsharpdocs/conceptual/collections.list-module-%5bfsharp%5d"&gt;many many more&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;reduce&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;acc&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;acc&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;;&lt;/span&gt; 2&lt;span style="color:#f92672"&gt;;&lt;/span&gt; 3&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; List.map &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; x &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; x &lt;span style="color:#f92672"&gt;*&lt;/span&gt; 2&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; List.filter &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; x &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; x &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; 3&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; List.sum
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conditionals"&gt;Conditionals&lt;/h2&gt;
&lt;p&gt;JS has the classic if-else syntax and also the ternary operators. F# does NOT have a ternary operator, but it does have if-else. Ternary is not really needed in F# because everything is implicitly returned anyways. The great thing about F# is that you will rarely need the if-else syntax because of pattern matching (explained below). Regardless, here is an example.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bigify&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;big&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;small&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;bigify&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#39;small&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;bigify&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// &amp;#39;big&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; bigify x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; x &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; 4 &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;big&amp;#34;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;small&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bigify 2 &lt;span style="color:#75715e"&gt;// &amp;#34;small&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bigify 5 &lt;span style="color:#75715e"&gt;// &amp;#34;big&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="objects--records"&gt;Objects / Records&lt;/h2&gt;
&lt;p&gt;The equivalent of JS objects would be the F# records. Notable differences are that records always need to be associated to a type, they are reference types by default, and they are immutable. So you can not update an existing record, you would need to create a new one and copy the values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;jason&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// immutably update an object by creating a new object
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data2&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2.16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;   *&lt;em&gt;Needs a type&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;jason&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cool &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; age &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;14 &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// immutably update a record by creating a new record
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; data &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; age &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;16 &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="record-types"&gt;Record Types&lt;/h2&gt;
&lt;p&gt;The above examples are not exactly possible in F# without specifying a type first.&lt;/p&gt;
&lt;p&gt;A record type defines the structure of a record. You do not need to assign the type to the variable holding the data because of F#&amp;rsquo;s strong type inference. The compiler will infer data types based on the properties defined. So in the example below, the compiler knows that &lt;code&gt;data&lt;/code&gt; is a Person type because it has all the exact same fields defined.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; name&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cool&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; age&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;jason&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cool &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; age &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;14 &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="enum-types"&gt;Enum Types&lt;/h2&gt;
&lt;p&gt;There are no direct comparisons in JS for enums, unless you use an objects with ints, but it is not exactly the same.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// enum
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CoolLevel&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Good
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Medium
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Bad
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; name&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; age&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cool&lt;span style="color:#f92672"&gt;:&lt;/span&gt; CoolLevel &lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#75715e"&gt;// requires a value from the enum
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lyagushka&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; age &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;14
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cool &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Good &lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#75715e"&gt;// assign Good because it is in the enum
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="discriminated-unions-types"&gt;Discriminated Unions Types&lt;/h2&gt;
&lt;p&gt;To get the equivalent of Union Types in JS, you would have to use some 3rd party module to get a consistent declaration of types, such as &lt;a href="https://github.com/fantasyland/daggy"&gt;DaggyJS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Although Daggy is great in JS, it&amp;rsquo;s pattern matching capabilities are only as good as JS can allow. This is where F# starts to shine.&lt;/p&gt;
&lt;p&gt;If you need an explanation of union types, &lt;a href="https://fsharpforfunandprofit.com/posts/discriminated-unions/"&gt;see this article&lt;/a&gt;, it will explain it much better than I can.&lt;/p&gt;
&lt;p&gt;Below is an example of an equivalent JS daggy type vs a native F# union type, and a peak of pattern matching at the bottom.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;taggedSum&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;daggy&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ProductPage&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;taggedSum&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;ProductPage&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Error&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;msg&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Success&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;product&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;product&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Red Shoe&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;price&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ProductPage&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Success&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;product&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// pattern match
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Loading&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &lt;span style="color:#e6db74"&gt;`&amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Error&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;`&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Success&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; =&amp;gt; &lt;span style="color:#e6db74"&gt;`&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Product&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; name&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; price&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ProductPage&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Loading
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Error &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; Success &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; Product
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; product &lt;span style="color:#f92672"&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Red Shoe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; price &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 3&lt;span style="color:#f92672"&gt;.&lt;/span&gt;14 &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; state &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Success product
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// pattern match
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; state &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Loading &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Error msg &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;div&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; msg &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;/div&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Success p &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;div&amp;gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; p&lt;span style="color:#f92672"&gt;.&lt;/span&gt;name &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;/div&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="pattern-matching"&gt;Pattern Matching&lt;/h2&gt;
&lt;p&gt;Pattern matching is popular in ML style languages because of how powerful they can be. Think of it as a switch-case statement on steroids. In F#, using the syntax of &lt;code&gt;match [anything] with&lt;/code&gt; you can successfully figure out what the type OR value is of anything. Completely avoiding if-else or switch-case statements.&lt;/p&gt;
&lt;h3 id="booleans"&gt;Booleans&lt;/h3&gt;
&lt;p&gt;Booleans are straight forward because they can only be 1 of 2 things, true or false.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; age &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; age &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; 12 &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; printf &lt;span style="color:#e6db74"&gt;&amp;#34;Teen&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; printf &lt;span style="color:#e6db74"&gt;&amp;#34;Not teen&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="numbers"&gt;Numbers&lt;/h3&gt;
&lt;p&gt;Numbers are not as straight forward as booleans because there are potentially an infinite amount of matching possibilities, so when trying to match numbers, you will be forced to provide a default pattern by using an underscore incase no pattern is matched.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; age &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; age &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 13 &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;teen&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 1 &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;One Year Old&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; 4 &lt;span style="color:#f92672"&gt;|&lt;/span&gt; 5 &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;little&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 4 or 5 will match here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; x &lt;span style="color:#66d9ef"&gt;when&lt;/span&gt; x &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; 0 &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;not alive&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// conditional logic
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;any other age&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// default incase age is not matched with anything
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="lists-1"&gt;Lists&lt;/h3&gt;
&lt;p&gt;Matching with lists is even cooler because you can use the underscore as a wildcard for any value inside the list.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; myList &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;1&lt;span style="color:#f92672"&gt;;&lt;/span&gt; 2&lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; myList &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; [] &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;empty list&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; &lt;span style="color:#f92672"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;list has 1 item&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; &lt;span style="color:#f92672"&gt;_;&lt;/span&gt; 5 &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;list has 2 items, 2nd item is 5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; &lt;span style="color:#f92672"&gt;_;&lt;/span&gt; &lt;span style="color:#f92672"&gt;_;&lt;/span&gt; &lt;span style="color:#f92672"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;list has 3 items&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;list does not match any of the above patterns&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="monads"&gt;Monads&lt;/h2&gt;
&lt;p&gt;Monads are a big topic, I even wrote an &lt;a href="https://dev.to/rametta/basic-monads-in-javascript-3el3"&gt;entire article&lt;/a&gt; about monads in JS.&lt;/p&gt;
&lt;p&gt;In F#, some monads are built in, such as the Option type, and no further work is needed to use besides typing Some or None.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;taggedSum&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;daggy&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;taggedSum&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Maybe&amp;#39;&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;value&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt; } &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`Value: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// 50
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;warn&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Nothing here&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Some&lt;span style="color:#f92672"&gt;(&lt;/span&gt;50&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;match&lt;/span&gt; data &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; Some x &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; printf &lt;span style="color:#e6db74"&gt;&amp;#34;Value: %i&amp;#34;&lt;/span&gt; x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&lt;/span&gt; None &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; printf &lt;span style="color:#e6db74"&gt;&amp;#34;Nothing here&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="typing"&gt;Typing&lt;/h2&gt;
&lt;p&gt;A brief note about typing functions in F#. Below I wrote the exact same function 4 times, each with a different way of defining the types.&lt;/p&gt;
&lt;p&gt;The first one has implicit types, letting the compiler infer the types based on the callers and the data passed to it.&lt;/p&gt;
&lt;p&gt;The second defines types for each parameter and then defines the return type.&lt;/p&gt;
&lt;p&gt;The third and fourth use a type signature and an anonymous function to define the types.&lt;/p&gt;
&lt;p&gt;All of these are valid and each can be used for different use cases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// inferred types
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; add x y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// explicit types
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; add &lt;span style="color:#f92672"&gt;(&lt;/span&gt;x&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;y&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt;&lt;span style="color:#f92672"&gt;):&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// explicit inline type signature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; add&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; x y &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// explicit separate type signature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Add&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;float&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; add&lt;span style="color:#f92672"&gt;:&lt;/span&gt; Add &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;fun&lt;/span&gt; x y &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; x &lt;span style="color:#f92672"&gt;+&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="http-requests"&gt;HTTP Requests&lt;/h2&gt;
&lt;p&gt;A great part of JS is the easy to work with Promise type for doing async actions, such as HTTP requests.&lt;/p&gt;
&lt;p&gt;Async is built into F# aswell, by using the &lt;code&gt;async&lt;/code&gt; keyword. Here is an example of an equivalent http request of getting the html of a page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JS&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;axios&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;axios&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;axios&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;https://github.com/rametta&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(({ &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; }) =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`HTML: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;F#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// sync
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; html &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Http.RequestString&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://github.com/rametta&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// async
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;async &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;let!&lt;/span&gt; html &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Http.AsyncRequestString&lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://github.com/rametta&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; printfn &lt;span style="color:#e6db74"&gt;&amp;#34;%d&amp;#34;&lt;/span&gt; html&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Length &lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; Async.Start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="other-cool-f-stuff"&gt;Other cool F# stuff&lt;/h2&gt;
&lt;p&gt;Briefs snippets of other neat F# features.&lt;/p&gt;
&lt;h3 id="range-operator"&gt;Range operator&lt;/h3&gt;
&lt;p&gt;Use two dots to define a range quickly.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; myList &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; 1&lt;span style="color:#f92672"&gt;..&lt;/span&gt;5 &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// [1; 2; 3; 4; 5]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="mutable-keyword"&gt;Mutable Keyword&lt;/h3&gt;
&lt;p&gt;Use the mutable keyword as an escape hatch when wanting to mutate variables.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; mutable data &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;data &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt; 8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="yield-keyword"&gt;Yield Keyword&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; mySeq &lt;span style="color:#f92672"&gt;=&lt;/span&gt; seq &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; i &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; 1&lt;span style="color:#f92672"&gt;..&lt;/span&gt;10 &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; j &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; 10&lt;span style="color:#f92672"&gt;..&lt;/span&gt;15 &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;yield&lt;/span&gt; i &lt;span style="color:#f92672"&gt;*&lt;/span&gt; j
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="tuples"&gt;Tuples&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fsharp" data-lang="fsharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; myTuple &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;5&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; typedTuple&lt;span style="color:#f92672"&gt;:&lt;/span&gt; int &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;5&lt;span style="color:#f92672"&gt;,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I hope this article shed some light on how similar F# is to JS, and I hope it encourages you to use it in future projects.&lt;/p&gt;</content></item><item><title>Basic monads in Javascript</title><link>/posts/js-basic-monads/</link><pubDate>Mon, 03 Sep 2018 00:00:00 +0000</pubDate><guid>/posts/js-basic-monads/</guid><description>&lt;p&gt;I&amp;rsquo;m going to explain some common monads that you can start using in your javascript today. Monads will help make your code easier to read, more maintainable and most importantly - safer.&lt;/p&gt;
&lt;h2 id="maybe"&gt;Maybe&lt;/h2&gt;
&lt;p&gt;The Maybe monad is used for dealing with nullable data. Often we like to process data in javascript, like formatting, doing calculations, filtering and sorting. But often we need to make sure the data is there before doing anything. This is where Maybe can help.&lt;/p&gt;</description><content>&lt;p&gt;I&amp;rsquo;m going to explain some common monads that you can start using in your javascript today. Monads will help make your code easier to read, more maintainable and most importantly - safer.&lt;/p&gt;
&lt;h2 id="maybe"&gt;Maybe&lt;/h2&gt;
&lt;p&gt;The Maybe monad is used for dealing with nullable data. Often we like to process data in javascript, like formatting, doing calculations, filtering and sorting. But often we need to make sure the data is there before doing anything. This is where Maybe can help.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to be using a small friendly helper library called &lt;a href="https://github.com/rametta/pratica"&gt;Pratica&lt;/a&gt; for providing an implementation of the monads in this article.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at a snippet that can benefit from the Maybe monad.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Hello my name is Jason&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toUpperCase&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// HELLO MY NAME IS JASON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now lets see how that can be refactored with a Maybe.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pratica&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Hello my name is Jason&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toUpperCase&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// HELLO MY NAME IS JASON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;No data available&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See we don&amp;rsquo;t need to check if the data exists, because Maybe will automatically not run any functions afterwards if the data is null. Avoiding error&amp;rsquo;s like &lt;code&gt;Uncaught TypeError: Cannot read property 'toUpperCase' of undefined&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now you might not see the advantage right away, but this isn&amp;rsquo;t where Maybe shines. Let&amp;rsquo;s look at another example with more steps.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Step 1: Filter cool people
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Step 2: Find the first cool person
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Step 3: Log their uppercased name if there is one
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Jason&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;level&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Blanche&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;level&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;coolPeople&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;coolPeople&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;firstCoolPerson&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;coolPeople&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;firstCoolPerson&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;firstCoolPerson&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;firstCoolPerson&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toUpperCase&lt;/span&gt;()) &lt;span style="color:#75715e"&gt;// JASON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s see the Maybe alternative.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pratica&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;people&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;people&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;people&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;people&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toUpperCase&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// JASON
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;No data available&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If data was actually null or undefined, then none of the .map functions would run and the Nothing function would be executed in the cata.&lt;/p&gt;
&lt;p&gt;But let&amp;rsquo;s say we also wanted to return a default value if the data was null. Then we can use the &lt;code&gt;.default()&lt;/code&gt; method.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pratica&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;Maybe&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;people&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;people&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;filter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;people&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;people&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toUpperCase&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;default&lt;/span&gt;(() =&amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#39;No cool people yo&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Just&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// No cool people yo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Nothing&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; () =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;No data available&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wow such clean, much flat.&lt;/p&gt;
&lt;h2 id="result"&gt;Result&lt;/h2&gt;
&lt;p&gt;So we learned that the Maybe monad is good for dealing with nullable data, but what if we want to check the value of the data and do different things depending on the values.&lt;/p&gt;
&lt;p&gt;Enter the Result monad (or sometimes called the Either monad).&lt;/p&gt;
&lt;p&gt;Result is used for &amp;ldquo;branching&amp;rdquo; your logic. Let&amp;rsquo;s take a look at an example without Result first.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Jason&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;level&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;level&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;This person is level 7, ew&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;This person is some other level, but not 7&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ok, now with Result.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pratica&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Jason&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;level&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;lvl&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;person&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;level&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;This person is level 7, ew&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;This person is some other level, but not 7&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;lvl&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// This person is level 7, ew
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) &lt;span style="color:#75715e"&gt;// This person is some other level, but not 7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Humm, I don&amp;rsquo;t see the point of this. What is Ok and Err? How is this better?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s do one more example before explaining it.&lt;/p&gt;
&lt;p&gt;In this example, we&amp;rsquo;ll have some data we need to validate before proceeding.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;first&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Jason&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;level&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;85&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;cool&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;size&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;m&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;color1&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#abc123&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;color2&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;#somehexcolor&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color1&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;black&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Color1 is valid, now lets continue
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;Color1 is black&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;No logo&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;No shirt&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;error&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;No data&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That looks a bit messy. Let&amp;rsquo;s see how we can improve that with Result.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; { &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt; } &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;pratica&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hasData&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;No data&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hasShirt&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;shirt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;No shirt&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hasLogo&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;logo&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;color1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;No logo&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;isNotBlack&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;color&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;color&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;black&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#39;Color is black&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;hasData&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;data2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;hasShirt&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;hasLogo&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;chain&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;isNotBlack&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;cata&lt;/span&gt; ({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Ok&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;color&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;color&lt;/span&gt;), &lt;span style="color:#75715e"&gt;// #abc123
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Interesting, it&amp;rsquo;s a lot flatter, but I still don&amp;rsquo;t understand what&amp;rsquo;s going on.&lt;/p&gt;
&lt;p&gt;Ok, here&amp;rsquo;s what&amp;rsquo;s happening.&lt;/p&gt;
&lt;p&gt;We start with the hasData function. That takes the initial data that needs to be validated and returns the next data that needs to be validated, but returns it wrapped inside the Result monad, more specifically, the Ok or the Err type. Both of those are what makes the Result monad, and those are how our application will branch the logic.&lt;/p&gt;
&lt;p&gt;Why is there &lt;code&gt;.chain()&lt;/code&gt; for every line?&lt;/p&gt;
&lt;p&gt;Well each function is returning either an Ok or an Err data type. But every function is also expecting it&amp;rsquo;s input to be just data, and not data wrapped inside of a monad. So calling chain on each function will unwrap the data from the monad so the function can read what&amp;rsquo;s inside.&lt;/p&gt;
&lt;p&gt;Why is this better?&lt;/p&gt;
&lt;p&gt;Well, better is subjective, but in functional programming this is considered better because it pushes the IO (IO being the console logging statements) to the edges of the program. That means that there are more pure functions that can be unit tested and don&amp;rsquo;t have IO mixed inside of them. Having IO inside of pure functions don&amp;rsquo;t make them pure anymore, which means they would be harder to unit test and be a source of bugs. Console logging is not a big deal in javascript, but if the IO was making a network request, then this type of programming makes a big difference, because all logic/validation would be independent of IO and easier to test and maintain.&lt;/p&gt;
&lt;p&gt;So those are 2 popular monads you can start using today.&lt;/p&gt;
&lt;p&gt;This is my first article of dev.to so let me know what you think in the comments!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to learn more about monads, check out these cool articles and libraries.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/rametta/pratica"&gt;Pratica&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html#monads"&gt;Monads in pictures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/fantasyland/fantasy-land"&gt;Fantasy Land&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sanctuary-js/sanctuary"&gt;Sanctuary JS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://learnyouahaskell.com/a-fistful-of-monads"&gt;Fistful of monads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content></item><item><title>About</title><link>/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/about/</guid><description>&lt;p&gt;Jason is a Software Engineer from Montreal, Canada.&lt;/p&gt;
&lt;p&gt;He currently works at Zapier on AI orchestration and is the author of the &lt;a href="/posts/typescript-compiler-api-book/"&gt;Typescript Compiler API&lt;/a&gt; book.&lt;/p&gt;
&lt;p&gt;Check out his &lt;a href="https://github.com/rametta"&gt;Github&lt;/a&gt;.&lt;/p&gt;</description><content>&lt;p&gt;Jason is a Software Engineer from Montreal, Canada.&lt;/p&gt;
&lt;p&gt;He currently works at Zapier on AI orchestration and is the author of the &lt;a href="/posts/typescript-compiler-api-book/"&gt;Typescript Compiler API&lt;/a&gt; book.&lt;/p&gt;
&lt;p&gt;Check out his &lt;a href="https://github.com/rametta"&gt;Github&lt;/a&gt;.&lt;/p&gt;</content></item><item><title>Contact</title><link>/contact/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>/contact/</guid><description>&lt;p&gt;Contact Jason by sending an end-to-end encrypted email to &lt;code&gt;public@rametta.org&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If the email is not encrypted using the following PGP public key then it will not be delivered.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;-----BEGIN PGP PUBLIC KEY BLOCK-----
xjMEZz66SRYJKwYBBAHaRw8BAQdAflcWdHpv0kYfxPYoYUmUhVRimyAKYf2I
aTpQ93DSrtzNJXJhbWV0dGFAcHJvdG9uLm1lIDxyYW1ldHRhQHByb3Rvbi5t
ZT7CjwQTFggAQQUCZz66SQkQqjI7m6fO83gWIQTAjResHXFNiBHxsGGqMjub
p87zeAIbAwIeAQIZAQMLCQcCFQgDFgACBScJAgcCAABXMwEA4aHW1AFwV6ia
e5DgHjT42922G79bjCQDjQ3Yax3ztLEBAKzyER9q7kFSv5vh11pRozIRqAVr
qHA/VZ/2hWxWCZQFzjgEZz66SRIKKwYBBAGXVQEFAQEHQPon9gBr1hH2Xrsa
D5kpV2rH3Xolrt/6jQNu15T3NwAQAwEKCcJ4BBgWCAAqBQJnPrpJCRCqMjub
p87zeBYhBMCNF6wdcU2IEfGwYaoyO5unzvN4AhsMAAC8wwEA+j8aUnkiG5iL
ryJOZHAXWjOUtEWOFYOfN90M3TTdc78A/1LCsmnpoemPg6ZtJI9Te47gpIPP
p7lY2RsqTd5+RysH
=O+0f
-----END PGP PUBLIC KEY BLOCK-----
&lt;/code&gt;&lt;/pre&gt;</description><content>&lt;p&gt;Contact Jason by sending an end-to-end encrypted email to &lt;code&gt;public@rametta.org&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If the email is not encrypted using the following PGP public key then it will not be delivered.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;-----BEGIN PGP PUBLIC KEY BLOCK-----
xjMEZz66SRYJKwYBBAHaRw8BAQdAflcWdHpv0kYfxPYoYUmUhVRimyAKYf2I
aTpQ93DSrtzNJXJhbWV0dGFAcHJvdG9uLm1lIDxyYW1ldHRhQHByb3Rvbi5t
ZT7CjwQTFggAQQUCZz66SQkQqjI7m6fO83gWIQTAjResHXFNiBHxsGGqMjub
p87zeAIbAwIeAQIZAQMLCQcCFQgDFgACBScJAgcCAABXMwEA4aHW1AFwV6ia
e5DgHjT42922G79bjCQDjQ3Yax3ztLEBAKzyER9q7kFSv5vh11pRozIRqAVr
qHA/VZ/2hWxWCZQFzjgEZz66SRIKKwYBBAGXVQEFAQEHQPon9gBr1hH2Xrsa
D5kpV2rH3Xolrt/6jQNu15T3NwAQAwEKCcJ4BBgWCAAqBQJnPrpJCRCqMjub
p87zeBYhBMCNF6wdcU2IEfGwYaoyO5unzvN4AhsMAAC8wwEA+j8aUnkiG5iL
ryJOZHAXWjOUtEWOFYOfN90M3TTdc78A/1LCsmnpoemPg6ZtJI9Te47gpIPP
p7lY2RsqTd5+RysH
=O+0f
-----END PGP PUBLIC KEY BLOCK-----
&lt;/code&gt;&lt;/pre&gt;</content></item></channel></rss>