<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Maina Wycliffe</title>
        <link>https://mainawycliffe.dev/blog</link>
        <description>Hi 👋, I am Maina Wycliffe, A Software Engineer, Open Source Contributor, Technical Writer and Speaker and Mentor.</description>
        <lastBuildDate>Tue, 08 Aug 2023 18:44:42 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en-us</language>
        <copyright>Maina Wycliffe</copyright>
        <item>
            <title><![CDATA[Looking Up React Components Props Types]]></title>
            <link>https://mainawycliffe.dev/blog/looking-up-react-components-props-types</link>
            <guid>https://mainawycliffe.dev/blog/looking-up-react-components-props-types</guid>
            <pubDate>Tue, 13 Jun 2023 21:27:31 GMT</pubDate>
            <content:encoded><![CDATA[<p>In an earlier post, in my <a href="https://www.allthingstypescript.dev/?ref=content.mainawycliffe.dev">All Things Typescript</a> newsletter, we covered how we can look up types for functions in Typescript using the <a href="https://www.allthingstypescript.dev/p/looking-up-the-types-of-a-functions?ref=content.mainawycliffe.dev">Parameters and ReturnType</a> utility types.</p><p>In this short post, I wanted to go a little bit further and look at doing the same for react components. It's a common need for React developers to occasionally create wrappers for third-party components, to customize behavior that's re-usable within their applications.</p><p>But from time to time, you will come across third-party libraries that do not export types for their own component props, despite their existence. </p><p>What do you do in this case? You could manually annotate the types, but you run the risk of your types getting out of sync with the library's types if the library authors introduce breaking changes.</p><p>Fortunately for us, we have a better solution on our hands - the <code>React.ComponentProps</code> utility type. Let's see it in action.</p><p>Let's take the following component:</p><pre><code class="language-ts">function HelloWorld({ name }: { name: string}) {
  // content of the component here, doesn't matter for the purpose of this article
}</code></pre><p>As you can see, the types of props are inlined. Since this is in our control, we can refactor the props types to a reusable Typescript Type, but let's assume we can't and we wanted to re-use the prop types. </p><p>This is where React.CompoentProps comes in, and we can use it in combination with the <code>typeof</code> operator to  get the props type, as shown below:</p><pre><code class="language-typescript">type HelloWorldProps = React.ComponentProps&lt;typeof HelloWorld&gt;;</code></pre><p>And in return, we get the following type back:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2023/06/image.png" class="kg-image" alt loading="lazy" width="737" height="85" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2023/06/image.png 600w, https://content.mainawycliffe.dev/content/images/2023/06/image.png 737w" sizes="(min-width: 720px) 720px"></figure><p>If you are interested, I wrote about the <code>typeof</code> operator, a while back in my <a href="https://allthingstypescript.dev/?ref=content.mainawycliffe.dev">All Things Typescript</a> newsletter, you can find the article <a href="https://www.allthingstypescript.dev/p/the-typeof-and-keyof-operators-referencing?ref=content.mainawycliffe.dev">here</a>.</p><p>And that's it. With a single Utility type - <code>React.ComponentProps</code>, we are able to fetch types from React Components and re-use them within our code with ease, giving us the flexibility to extend components as we need to. </p><h3 id="resources">Resources</h3><ul><li><a href="https://www.allthingstypescript.dev/p/looking-up-the-types-of-a-functions?ref=content.mainawycliffe.dev">Looking up the Input and Output Types of a Function using the Parameters &amp; ReturnType Utility Types</a></li><li><a href="https://www.allthingstypescript.dev/p/indexed-access-types-in-typescript?ref=content.mainawycliffe.dev">Indexed Access Types in Typescript</a></li><li><a href="https://www.allthingstypescript.dev/p/using-zod-schemas-as-source-of-truth?ref=content.mainawycliffe.dev">Using Zod Schemas as a Source of Truth for Typescript Types</a></li><li><a href="https://www.allthingstypescript.dev/p/typescript-how-do-you-provide-types?ref=content.mainawycliffe.dev">Typescript: How do you provide types for data from external sources?</a></li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>React</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Organize Your Firebase Functions For Easier Deployments and Maintenance]]></title>
            <link>https://mainawycliffe.dev/blog/organize-firebase-functions-easier-deployments-maintenance</link>
            <guid>https://mainawycliffe.dev/blog/organize-firebase-functions-easier-deployments-maintenance</guid>
            <pubDate>Mon, 05 Jun 2023 12:40:02 GMT</pubDate>
            <content:encoded><![CDATA[<p>When developing Firebase functions, it's common to have everything in a single repository - all the Firebase Functions for your project. This is usually fine when you are starting out.</p><p>But as your project grows, this can start to have negative impacts, for instance, slow deployment as Firebase has to build large functions, upload and figure out what changed and didn't change. </p><p>On top of that, it also makes it very difficult for multiple teams to work on the same project, making it hard to deploy and maintain, as teams work on their features.</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2023/06/7o55wn.jpg" class="kg-image" alt loading="lazy" width="507" height="500"></figure><h2 id="firebase-functions-codebases">Firebase Functions Codebases</h2><p>So, how do you manage this? Firebase provides the concept of Firebase Functions Codebases, where Firebase functions can be organized into a collection in a way that makes sense to an organization, say a team owns them or by feature, and maintained and deployed together.</p><p>The functions collections can be in different repositories or in the same repository, in a mono-repo setup using something like <a href="https://nx.dev/?ref=content.mainawycliffe.dev">NX</a> in combination with the <a href="https://github.com/mainawycliffe/nx-toolkits?ref=content.mainawycliffe.dev">NX generator for Firebase</a> that I built earlier this year.</p><p>Firebase codebase allows you to organize your Firebase functions collection in a way that makes sense to your organization. This could be by functionality or teams and so, allowing you to maintain and deploy them together.</p><p>By default, firebase has a single, default codebase, and your Firebase config file - <code>firebase.json</code> - looks like this. </p><pre><code class="language-json">{
  // ... other firebase services configurations i.e. hosting etc.
  "functions": [
    {
      "source": "dist/apps/functions",
      // default codebase
      "codebase": "default",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log"
      ],
      "predeploy": [
        "pnpm nx run functions:build"
      ]
    }
  ],
  "extensions": {}
}
</code></pre><p>We can configure a different codebase for our Firebase functions, for a second collection of functions by modifying the codebase property of one of our functions. </p><p>For instance, in the above example, we can add a second functions collection, with a different codebase, by adding a second config option to the functions property inside our <code>firebase.json</code> config file. </p><pre><code class="language-json">{
  // ... other firebase services configs
  "functions": [
    {
      "source": "dist/apps/functions",
      "codebase": "default",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log"
      ],
      "predeploy": [
        "pnpm nx run functions:build"
      ]
    },
     {
      "source": "dist/apps/functions",
      "codebase": "codebase-2",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log"
      ],
      "predeploy": [
        "pnpm nx run functions:build"
      ]
    }
  ]
}
</code></pre><p>In the case above, our different functions collections exist in the same repository - a mono-repo. We could have our functions collection exist in multiple repositories and in such cases, we would just need the only codebase inside the repository to be configured in our <code>firebase.json</code> config file.</p><pre><code class="language-json">{
  // ... other firebase services configs
  "functions": [
     {
      "source": "dist/apps/functions",
      "codebase": "codebase-2",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log"
      ],
      "predeploy": [
        "pnpm nx run functions:build"
      ]
    }
  ]
}
</code></pre><blockquote>NB: Ensure that the codebase property is correct, as this could have unforeseen consequences, such as deleting other functions in the codebase that weren't found inside the repository.</blockquote><h3 id="deploying-your-functions">Deploying your Functions</h3><p>As always, <code>firebase deploy</code> and <code>firebase deploy functions</code> will deploy all Firebase functions within the current directory, in all codebases. On top of that, you can specify which codebase to deploy, by using the <code>firebase deploy functions:codebase</code> command.</p><pre><code class="language-sh">firebase deploy functions:codebase</code></pre><p>If your function collections are distributed in multiple repos, you can just use the <code>firebase deploy</code> command. Firebase CLI will not prompt you to delete existing Firebase function collections from other codebases.</p><p>But if your function collections are in a mono repo setup, you might find it beneficial to have your target to a specific codebase, instead of deploying all codebases within the mono repo.</p><pre><code class="language-sh">firebase deploy functions:codebase</code></pre><h3 id="firebase-functions-nx-generator">Firebase Functions NX Generator</h3><p>For those of you using <a href="https://nx.dev/?ref=content.mainawycliffe.dev">nx</a> or want to use nx to manage your Firebase project, you might find it beneficial to try out the generator I created to create Firebase functions as NX apps. with full support for codebase - <a href="https://github.com/mainawycliffe/nx-toolkits/blob/main/packages/firebase/README.md?ref=content.mainawycliffe.dev">@nx-toolkits/firebase</a>.  </p><p>Each Firebase functions codebase lives as an nx application, with all the benefits of NX such as codesharing between codebases and caching. For more information, check out this <a href="https://mainawycliffe.dev/blog/supercharge-your-firebase-app-development-using-nx/?ref=content.mainawycliffe.dev">post</a> about my motivations as to why I built the generator.</p><h3 id="how-it-works">How it works</h3><p>First, install the @nx-toolkits/firebase generator, using your favorite package manager.</p><pre><code class="language-sh">// npm
npm i  @nx-toolkits/firebase

// yarn
yarn add @nx-toolkits/firebase

//pnpm
pnpm add  @nx-toolkits/firebase</code></pre><p>To generate a function in the default codebase, just run the following command:</p><pre><code class="language-sh">nx g @nx-toolkits/firebase:functions</code></pre><blockquote><strong>NB:</strong> Please ensure that you have run Firebase initialization in the root directory of your project. In the future, I would like to be able to handle this as well.</blockquote><p>This will create or override the default codebase application. To create an nx application, with a different codebase, just run the following command:</p><pre><code class="language-sh">nx g @nx-toolkits/firebase:functions --codebase codebase-2</code></pre><p>And that's it. Running the <code>nx deploy</code> command targeting the app you just generated, will only deploy functions of the correct codebase.</p><pre><code class="language-sh">nx run my-functions-app:deploy</code></pre><p>And that's it.</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2023/06/7nzcu7.jpg" class="kg-image" alt loading="lazy" width="620" height="413" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2023/06/7nzcu7.jpg 600w, https://content.mainawycliffe.dev/content/images/2023/06/7nzcu7.jpg 620w"></figure><h2 id="conclusion">Conclusion</h2><p>In this post, we looked at how we can use codebases in Firebase functions to organize our Firebase functions making it easy to maintain and deploy, as our app grows. </p><p>It's important for any project, to be able to enhance effectiveness and ensure different features can be developed and maintained with minimal conflicts and with speed. </p><p>Codebases make it easy for organizations to be able to decide how to organize Firebase functions as it makes sense to them, be it in a mono repo setup or even multiple repositories, so as to achieve business goals.</p><h3 id="resources">Resources</h3><ul><li><a href="https://mainawycliffe.dev/blog/supercharge-your-firebase-app-development-using-nx/?ref=content.mainawycliffe.dev">Supercharge your Firebase App Development using NX</a></li><li><a href="https://www.allthingstypescript.dev/p/the-typeof-and-keyof-operators-referencing?ref=content.mainawycliffe.dev">The typeof and keyof operators - referencing variable types in Typescript</a></li><li><a href="https://firebase.google.com/docs/functions/organize-functions?gen=2nd&ref=content.mainawycliffe.dev">Organize multiple functions</a></li><li><a href="https://www.allthingstypescript.dev/p/using-zod-schemas-as-source-of-truth?ref=content.mainawycliffe.dev">Using Zod Schemas as a Source of Truth for Typescript Types</a></li><li><a href="https://mainawycliffe.dev/blog/my-blog-is-over-engineered/?ref=content.mainawycliffe.dev">My Blog is Overengineered</a></li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Firebase</category>
        </item>
        <item>
            <title><![CDATA[Supercharge your Firebase App Development using NX]]></title>
            <link>https://mainawycliffe.dev/blog/supercharge-your-firebase-app-development-using-nx</link>
            <guid>https://mainawycliffe.dev/blog/supercharge-your-firebase-app-development-using-nx</guid>
            <pubDate>Tue, 27 Dec 2022 19:42:09 GMT</pubDate>
            <content:encoded><![CDATA[<p>One of the pain points that I am sure some of us have come across when using Firebase projects that have been generated with Firebase CLI is code sharing between the frontend and Firebase functions, the backend. </p><p>This is because when using Firebase CLI to scaffold Firebase functions, it usually creates a new Firebase directory with its dependencies isolated from the rest of the repository. There are good reasons for this, as Firebase needs to install packages consumed by your Firebase functions in the Firebase. </p><p>Installing NPM packages not being consumed by your functions would be less than ideal as it would slow down your deployments if they are too many. Imagine installing the dependencies for your Angular app to deploy your firebase functions. The impact wouldn't be negligible. Another disadvantage would be storage consumption, which could have unforeseen circumstances.</p><h2 id="disadvantages-of-the-default-setup">Disadvantages of The Default Setup</h2><p>This kind of setup has a few disadvantages; the common one which I alluded to earlier, is code sharing between your frontend app and your Firebase functions. It's not impossible, but it may require you to do some work before making it work. Think of things like Types, Schemas, etc., which don't change whether they are consumed on the backend or the frontend. This can have unforeseen circumstances if they are out of sync.</p><p>The second is a smaller one; managing two sources of dependencies within your application will negatively impact the developer experience (DevX). You must ensure you switch to the correct directory to install dependencies, which requires some mental load. It would be much faster if we had a single source of truth.</p><p>And lastly has to do with caching build, lining, and testing results. For small applications, this doesn't matter, but for large applications, this could save you hours and hours, as a correct caching mechanism such as NX can allow you never to build, test, or lint on code that hasn't changed. </p><h2 id="nx-generator-for-firebasenx-toolkitsfirebase">Nx Generator for Firebase - @nx-toolkits/firebase</h2><p>Considering the above disadvantages, I have spent the last few days working on an NX generator for Firebase Functions - <a href="https://www.npmjs.com/package/@nx-toolkits/firebase?ref=content.mainawycliffe.dev"><strong>@nx-toolkits/firebase</strong></a>. I will expand this to include setting up hosting for NX apps in the future.</p><figure class="kg-card kg-image-card"><a href="https://www.npmjs.com/package/@nx-toolkits/firebase?ref=content.mainawycliffe.dev"><img src="https://content.mainawycliffe.dev/content/images/2022/12/nx-toolkits.png" class="kg-image" alt loading="lazy" width="1200" height="600" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2022/12/nx-toolkits.png 600w, https://content.mainawycliffe.dev/content/images/size/w1000/2022/12/nx-toolkits.png 1000w, https://content.mainawycliffe.dev/content/images/2022/12/nx-toolkits.png 1200w" sizes="(min-width: 720px) 720px"></a></figure><p>My goal was simple when using my NX generator; it would create a new NX app for Firebase functions, just like you would have an Express, React, NestJS, or Angular application. On top of creating an NX app, we would benefit from caching of linting, testing, and builds, and on top of that code, sharing that is enabled by NX mono repo, allowing you to share code between all your apps and libs.</p><p>In short, I am implying it needed to behave like any other NX app within your NX mono repo. Another goal I had in mind is to ensure that you can still use Firebase CLI as you would normally do, commands such as <code>firebase deploy --only functions</code> should work without you having to think. </p><p>And with those goals in mind, I went ahead and developed <code>@nx-toolkits/firebase</code>. </p><div class="kg-card kg-button-card kg-align-center"><a href="https://www.npmjs.com/package/@nx-toolkits/firebase?ref=content.mainawycliffe.dev" class="kg-btn kg-btn-accent">@nx-toolkits/firebase on NPM</a></div><h2 id="how-does-it-work">How does it work?</h2><p>Just like any other NX plugin, we start by installing the plugin using NPM.</p><pre><code class="language-bash">npm install -D @nx-toolkits/firebase</code></pre><p>And once that has been installed, we can then go ahead and generate a Firebase functions app:</p><pre><code class="language-bash">npx nx g @nx-toolkits/firebase:functions</code></pre><p>You will need to provide the following options:</p><ul><li><code>name</code> - Name of the NX App</li><li><code>firebaseProject</code> - the Firebase project id. This is optional if you already ran <code>firebase init</code> command in your project directory. </li><li><code>codebase</code> - This is a firebase config to organize Firebase functions collection when there are too many; please read the docs here for more information.</li><li><code>nodeVersion</code> - the runtime version of NodeJS for your Firebase function.</li></ul><p>After generating the functions app, you can run the usual command with nx such as linting, testing, and building.</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">nx run my-functions-app:lint</code></pre><figcaption>This assumes <code>my-functions-app</code> as the name of the app</figcaption></figure><p>And finally, you can deploy your Firebase app once you are done. There are two ways of doing this:</p><ol><li>The first one is the common way to deploy firebase apps, using the <code>firebase deploy</code> command</li></ol><pre><code class="language-bash">firebase deploy --only functions</code></pre><ol><li>Or the second one is to run the NX executor to deploy the command.</li></ol><pre><code class="language-bash">npx nx run my-functions-app:deploy
</code></pre><p>Both of these commands work exactly the same way now, and none of them has an advantage over the other.</p><p>That's it; you have an NX app Firebase functions with all the benefits of NX at your Fingertips.</p><h3 id="so-whats-next-for-you">So, what's next for you</h3><p>Try out the generator, and if you come across any bugs or have any ideas on areas of improvement, I would appreciate any feedback to improve this NX generator. You can find the source code <a href="https://github.com/mainawycliffe/nx-toolkits?ref=content.mainawycliffe.dev">here</a>.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/mainawycliffe/nx-toolkits?ref=content.mainawycliffe.dev" class="kg-btn kg-btn-accent">@nx-toolkits/firebase</a></div><h2 id="conclusion">Conclusion</h2><p>In this post, we saw how to supercharge your Firebase development experience using NX, and how we can bring the benefits of NX to Firebase app development and rip the benefits of NX. In the next few weeks, I will work on improving a few feature sets around hosting and functions, and if you have any feedback, please feel free to open an issue <a href="https://github.com/mainawycliffe/nx-toolkits/issues?ref=content.mainawycliffe.dev">here</a>.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Firebase</category>
            <category>NX</category>
        </item>
        <item>
            <title><![CDATA[I created a VS Code Extension - NPM Imported Packages Lens]]></title>
            <link>https://mainawycliffe.dev/blog/npm-imported-packages-lens</link>
            <guid>https://mainawycliffe.dev/blog/npm-imported-packages-lens</guid>
            <pubDate>Mon, 18 Jul 2022 08:23:51 GMT</pubDate>
            <content:encoded><![CDATA[<p>When you read JavaScript/Typescript code, have you ever encountered an imported package and wanted to learn more about it? For instance, go to the NPM or GitHub Repo, where you can get more information. When I find myself in this situation, my process always involves copying the package name, Googling it, and finally getting to my destination, either NPM, GitHub Repo, or the website for the package. This can also be not as straightforward as you might think, as it could involve several packages that are closely named, and you have to figure out which one is the correct one.</p><h2 id="npm-imported-packages-lens-extension">NPM Imported Packages Lens Extension</h2><figure class="kg-card kg-video-card"><div class="kg-video-container"><video src="https://content.mainawycliffe.dev/content/media/2022/08/npm-link-2.mp4" poster="https://img.spacergif.org/v1/1280x720/0a/spacer.png" width="1280" height="720" loop autoplay muted playsinline preload="metadata" style="background: transparent url('https://content.mainawycliffe.dev/content/images/2022/08/media-thumbnail-ember439.jpg') 50% 50% / cover no-repeat;"></video><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container kg-video-hide"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"></span></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#215;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"></div></div></div></figure><p>Last week, I decided to do something about this. I created a VS Code Extension that will show you links to NPM, Github, and the Homepage (usually a docs site or GitHub ReadMe of the project) for an imported package right there in the Typescript/Javascript file. Click on whichever you want to open, and you will land on the correct page without the mental model involved in my previous process.</p><p>The extension currently shows three links: NPM, GitHub, and Homepage, and all of these are pulled from NPM for the latest version of the package - I will try and address the versioning issue as time goes on especially for the link to the Homepage. And the extension currently works for ES modules for Typescript, Javascript, and JSX/TSX files; I hope to add support for other frameworks such as Vue, Svelte, and Astro in the near future.</p><p>You can install the extension from <a href="https://marketplace.visualstudio.com/items?itemName=MainaWycliffe.view-package-on-npm&ref=content.mainawycliffe.dev">here</a> and find the Github repository <a href="https://github.com/mainawycliffe/npm-imported-packages-lens?ref=content.mainawycliffe.dev">here </a>(please leave a star ⭐). Thank you.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Island Architecture]]></title>
            <link>https://mainawycliffe.dev/blog/island-architecture</link>
            <guid>https://mainawycliffe.dev/blog/island-architecture</guid>
            <pubDate>Wed, 20 Apr 2022 18:06:26 GMT</pubDate>
            <content:encoded><![CDATA[<p>There are different ways to build a website. One of them was Multi-Page Applications (MPAs) which went out of fashion about a decade ago and are having a comeback. MPAs had been replaced by the Single Page Applications (SPAs) approach popularized by Angular and React, among other modern frameworks.</p><p>Due to how trends work, it is easy for methods/tools to go out of fashion. This is not because it is less effective but because developers stop using them in favor of something else. This is what happened with Multi-Page Applications (MPAs), as developers started adopting popular web frameworks such as Angular, React, Vue, etc. This led to an uptick in SPA usage as the frameworks became more popular.</p><p>Due to how SPAs work, the impact has been that the amount of Javascript we ship to the browser has increased. i.e., you can't have a react web app without React to manage state and rendering. SPAs use Javascript to render the HTML to be displayed in the browser. In many cases, this makes sense, for instance, in web apps such as Facebook or YouTube, where managing the state is paramount. But in other cases, this does not make sense, for example, blogs, personal portfolios, etc.</p><h2 id="server-side-rendering">Server-Side Rendering</h2><p>When using a framework such as Angular or React and SPAs in general, the server does very little; all the rendering is done on the Client-Side, in what is known as Client-Side Rendering. To see the content, you first have to download the framework's runtime (JS needed to scaffold your web app) and also need an environment to render the content, i.e., the browser.</p><p>This has a few downsides, the notable ones being it's slow to show something on the screen, the impact of this is worse on low-end devices and slower internet connection and Search Engine Optimization - bots and crawlers are usually unable to render these pages and can't parse the content to show results.</p><p>We have two standard solutions to solve the above problems: Server-Side Rendering (SSR) and Rendering during build time - SSG. SSG is similar to SSR but at build time, removing the need to render on every request at the server. SSG is common for sites whose content isn't that dynamic. The problem with these two solutions is that they don't solve the problem with SPAs but rather postpone it. </p><p>If you want any sort of interactivity, say opening and closing the navbar on your web app, you will need to hydrate your rendered app from either SSG or SSR. This is the process of bootstrapping the framework you are using, transferring the state from the server so that the framework can take over. This usually happens after the first content is painted (after rendering the server-side rendered HTML from the server) but before the interactivity in your web app. </p><p>This means the JS needed by your framework has to be downloaded and parsed, and the user has to wait for all that to happen to interact with your web app. This would mean even on pages where you don't need interactivity, i.e., About Us Page, Terms and Conditions, etc., you still need to do all that, which is a bit unnecessary.</p><h2 id="islands">Islands</h2><p>And this is where Islands Architecture comes in. Imagine this; what if you could create your web app with pure HTML and CSS for all the static content but then add in regions of dynamic content or interactivities - islands - that can use a framework to add interactivity. These regions would use any framework, and the framework runtime would only be downloaded only when on a page that uses it rather than on the initial load of the website. </p><p>Web frameworks such as Astro (<a href="https://mainawycliffe.dev/?ref=content.mainawycliffe.dev">My website</a> is built with Astro), Marko, and most recently Qwik, among others, are implementing this architecture method. In the case of Astro, you have Astro components that use some variation of JSX but do not have a client-side state, so there is no runtime.</p><h3 id="astro">Astro</h3><p>Astro uses the concept of JS opt-in, meaning by default, no Javascript is generated unless you tell Astro to include javascript. You can then either use Vanilla JS to include Javascript - the old fashioned way, as shown below:</p><figure class="kg-card kg-code-card"><pre><code class="language-html">&lt;script&gt;
  document.getElementById("menuToggle").addEventListener("click", () =&gt; {
    const collapsibleMenu = document.getElementById("collapsibleMenu");
    collapsibleMenu.classList.toggle("navbar-menu-show");
    collapsibleMenu.classList.toggle("navbar-menu-hidden");
  });
&lt;/script&gt;</code></pre><figcaption>JS Snippet to toggle mobile menu on and off&nbsp;</figcaption></figure><blockquote>Astro components cannot be hydrated as they are HTML only templating components and any Javascript needs to be included as indicated above or via a framework such as React, SolidJS, etc.</blockquote><p>The second option is to bring your framework, for example, React, Preact, Lit, Svelte, Vue, etc., to create components that add regions of interactivity (islands) in your web app.</p><pre><code class="language-astro">// index.astro file
---
import ReactComponent from "./ReactComponent"

---

&lt;ReactComponent /&gt;</code></pre><p>You are also in control of when the necessary region is hydrated. This is done via directives that instruct Astro when to perform hydration. For instance, you might want an island to be hydrated on load or only when it becomes visible. There are several directives to help you achieve this, which you can learn more about <a href="https://docs.astro.build/en/core-concepts/component-hydration/?ref=content.mainawycliffe.dev">here</a>.</p><figure class="kg-card kg-code-card"><pre><code class="language-astro">// index.astro file
---
import ReactComponent from "./ReactComponent"

---

&lt;ReactComponent client:visible /&gt;</code></pre><figcaption>An example of a component being hydrated when it becomes visible</figcaption></figure><h3 id="marko-and-qwik">Marko and Qwik</h3><p>While I am not an expert at either Marko.js or Qwik (the new kid in the block), I will link additional resources below if you are interested in learning more. Marko and Qwik take the concept of islands a little further when compared to Astro. </p><p>Marko is an MPA framework, and its Island architecture is a bit smarter in that it automatically decides to load JS needed for an Island, delaying it as far as possible, allowing for far more efficient islands. This is unlike the current Astro approach, which relies on the developer to tell Astro when to do hydration. Astro is still in the pre-release stage, and maybe this will change in the future. </p><p>Another key advantage Marko has over Astro is that Marko decides what is inside the Islands and what's not in it. This means components such as footers, headers, etc., that only display static content don't become islands, while forms and other rich components with dynamic content become islands that can be hydrated.</p><p>Qwik, on the other hand, takes this to a component level, breaking down how hydration is done so that it is done only when needed. This is achieved by aggressively breaking apart your website's JavaScript into multiple chunks, setting up global event listeners, and serializing points of interest directly into the HTML. For each distinct user interaction, Qwik has all it needs to load only the code required to perform the action and nothing more. </p><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">A qwik look at how <a href="https://twitter.com/QwikDev?ref_src=twsrc%5Etfw&ref=content.mainawycliffe.dev">@QwikDev</a> works <a href="https://t.co/NKxc4QO1pF?ref=content.mainawycliffe.dev">pic.twitter.com/NKxc4QO1pF</a></p>&mdash; Steve Sewell (@Steve8708) <a href="https://twitter.com/Steve8708/status/1516137857038966786?ref_src=twsrc%5Etfw&ref=content.mainawycliffe.dev">April 18, 2022</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure><p>In return, this leads to smaller chunks, which are faster to load, parse and load only what the user needs. This is known as <a href="https://www.builder.io/blog/why-progressive-hydration-is-harder-than-you-think?utm_source=twitter">progressive hydration</a>, which is out of scope for this article, and hopefully, I will write about it soon.</p><h2 id="conclusion">Conclusion</h2><p>This article looked at Islands Architecture, why they exist, and the frameworks currently applying them. In the next series of articles, I want to dig deeper into the frameworks mentioned above - Astro, Marko, and Qwik, plus other frameworks such as Svelte, Angular, and React and how they differ internally from each other.</p><h2 id="resources">Resources</h2><ol><li><a href="https://www.builder.io/blog/why-progressive-hydration-is-harder-than-you-think?utm_source=twitter">Why Progressive Hydration is Harder than You Think</a></li><li><a href="https://www.builder.io/blog/from-static-to-interactive-why-resumability-is-the-best-alternative-to-hydration?ref=content.mainawycliffe.dev">From Static to Interactive: Why Resumability is the Best Alternative to Hydration</a></li><li><a href="https://dev.to/this-is-learning/javascript-vs-javascript-fight-53fa?ref=content.mainawycliffe.dev">JavaScript vs. JavaScript. Fight!</a></li><li><a href="https://dev.to/this-is-learning/why-efficient-hydration-in-javascript-frameworks-is-so-challenging-1ca3?ref=content.mainawycliffe.dev">Why Efficient Hydration in JavaScript Frameworks is so Challenging</a></li><li><a href="https://dev.to/this-is-learning/resumable-javascript-with-qwik-2i29?ref=content.mainawycliffe.dev">Resumable JavaScript with Qwik</a></li><li><a href="https://dev.to/ryansolid/comment/1ni8p?ref=content.mainawycliffe.dev">Conquering JavaScript Hydration Event delegation is the key to not running over the component... Apr 15</a></li><li><a href="https://dev.to/ryansolid/state-of-javascript-2021-framework-reflections-2i77?ref=content.mainawycliffe.dev">State of JavaScript 2021: Framework Reflections</a></li><li><a href="https://www.builder.io/blog/introducing-qwik-framework?ref=content.mainawycliffe.dev">A first look at Qwik - the HTML first framework WRITTEN BYMIŠKO HEVERY JULY 2, 2021</a></li></ol>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Javascript</category>
        </item>
        <item>
            <title><![CDATA[Performance: Choosing The Right Tools...]]></title>
            <link>https://mainawycliffe.dev/blog/performance-choosing-right-tools</link>
            <guid>https://mainawycliffe.dev/blog/performance-choosing-right-tools</guid>
            <pubDate>Wed, 13 Apr 2022 18:00:27 GMT</pubDate>
            <content:encoded><![CDATA[<p>Before I wrote this, I was in the middle of writing a Twitter thread about performance on the web and the unintended impact tools developers choose to build their websites have on their users. As I was writing that, I realized that Twitter wasn't probably the most suitable medium to air my thoughts exactly, so I wrote this instead.</p><p>It's pretty common nowadays to find web developers specializing in a single framework. While there is nothing wrong with that, as long as you stick to its strengths, i.e., the right tool for the right job. The saying goes, "when you have a hammer, everything is a nail," and I have seen frontend developers who want to use the only Framework they know for everything, despite it not being the right fit for the task at hand.</p><h2 id="some-background">Some Background</h2><p>Before I can go any further, let me give you some context. I am from Kenya, and most of my friends have $200 or lower smartphones, and about half of those have a $100 or lower smartphone; some don't even have smartphones. This means the devices most of my friends own are quite limited performance-wise. And this is one crucial area we as developers need to understand as we tend to have more powerful devices at our disposal.</p><p>The other thing to be aware of is the state of internet connectivity. It's pretty decent, maybe even good, in some areas, primarily Urban areas, but the speed and reliability fall off the cliff when you start heading to informal settlements and rural areas. This trend can be replicated all over Africa, and I believe in large parts of the world.</p><h2 id="performance">Performance</h2><figure class="kg-card kg-image-card"><img src="https://media.tenor.com/images/1b95f145c3612aaf728193bbdc702ba6/tenor.gif" class="kg-image" alt loading="lazy" width="498" height="263"></figure><p>So, why am I telling you this? When it comes to performance, you need to approach it in two folds: First, the number of KBs the user has to download and the device's capability the user has. The internet speed is impacted by the device in question capabilities, not just the internet coverage. Users with low-end devices tend to also live in areas with poor internet coverage and connectivity. </p><p>The more the KBs your JS script is, the longer it will take to download the script before we can get to parsing, which will also be slower due to device capability limitations. As you can imagine, both of these can take a frustrating longer time on a low-end device on a slow network. When we develop poor-performing websites, i.e., takes longer to load, huge scrips that take a toll on the processor and battery life, we negatively impact our users, especially the already disadvantaged.</p><p>When I am using my iPhone 13 Pro Max (or whatever the latest model is as you are reading this) on the latest 5g network, I will probably notice slow performance, but it will be a minor inconvenience. However, for someone on a $100 or lower smartphone on a slow network, the impact on performance will be huge. We have all been there, trying to load a website that refuses to load or is laggy either due to poor network connection or the toll the website places on both memory and the process. This could mean the difference between someone getting life-saving information in time or not getting it.</p><h3 id="spas">SPAs</h3><p>One of the most popular ways of developing websites is using Single Page Applications (SPAs) frameworks popularized by React and Angular. These SPA frameworks have become a go-to for developers due to their excellent developer experience and ease of building websites, but this comes at a performance cost. SPA applications need to be bootstrapped, which means you ship your site in JavaScript for the browser to download, parse and render your website in what is known as Client-Side Rendering (CSR). </p><p>So, to recap, the user not only needs to download the Framework Code + your Application code, but they also need the browser to parse it before they can see content on your site. Depending on the size of the Framework and other libraries' sizes, this can quickly balloon to MBs of data. </p><p>Due to the above issues, we have come up with techniques to try and show the content as soon as possible such as Server-Side Rendering (SSR) and Static Site Generation (SSG). But these are not perfect solutions. They both need to put the Framework back into the rendered HTML after the initial content has been displayed for any interactivity, in a process called hydration.</p><p>This is okay (ish) if you are building a web app such as Facebook or YouTube (guess who is behind two of the most used SPA frameworks), where once the site loads, you can access a bazillion of content without having to load the site again. The examples I mentioned above behave more like apps than traditional websites. </p><p>In such instances, I may be okay paying the upfront tax, but subsequent navigations are faster, and requests and data exchange between the server and the client is more efficient. This, of course, is computationally expensive as the Framework in question has to update the DOM to create and removes nodes so that views can change.</p><p>But what if all I wanted to access was information on a single page? Think of a blog post or some instruction on applying for a government grant or social benefits. Do I have to download and run a whole web app to access this information? </p><p>As you can imagine, this can be very painful, especially for government sites, NGOs, and business services whose customer base has users with poor internet coverage and low-end devices or a combination of both.</p><p>To be honest, this should extend to everyone, no matter the internet connection speed or kind of device I have; I shouldn't have to download tons of JS code just to read your blog post.</p><figure class="kg-card kg-image-card"><img src="https://media.tenor.com/images/7d94d3aaba0a3c06a31e1f6e79b3ea3a/tenor.gif" class="kg-image" alt loading="lazy" width="230" height="226"></figure><h2 id="in-conclusion">In Conclusion</h2><p>So, where am I going with this? The title of this article is "The Right Tool for the Right Job." I mean that as developers, we need to think about our users and the purpose of what we are building before choosing the tools to use. Whatever tools and frameworks we use, we need to emphasize more on the user experience we are providing. This means that we need to learn to have more than one tool in our toolkit and be open to learning more. Lately, we have seen an uptick in frameworks and libraries geared towards 0KB Javascript without sacrificing developer experience. I believe every front-end developer should know at least one.</p><p>We have a lot of tools at our disposal from SPAs frameworks such as Angular, React, Vue, etc., which have their use cases but should not be used for everything. On the other hand, we have frameworks and tools for building Multi-Page Applications (MPAs) and Static Sites, such as Astro, Hugo, Jekyll, etc., that are designed for shipping as little Javascript as possible while providing incredible speeds most SPAs frameworks can only dream off. </p><figure class="kg-card kg-image-card"><img src="https://media.tenor.com/images/6132aa64077ae2c457d12d7244438a20/tenor.gif" class="kg-image" alt loading="lazy" width="498" height="280"></figure><p>My point is as a developer; you should make sure you have a few of these tools in your tool kit; this will ensure that whenever you are choosing, you choose the right tool for the job.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Javascript</category>
        </item>
        <item>
            <title><![CDATA[Live Reloading in Golang using Air]]></title>
            <link>https://mainawycliffe.dev/blog/live-reloading-golang-using-air</link>
            <guid>https://mainawycliffe.dev/blog/live-reloading-golang-using-air</guid>
            <pubDate>Wed, 06 Apr 2022 19:48:38 GMT</pubDate>
            <content:encoded><![CDATA[<p>Live reloading changes to our codebase is one of the core tenants of a great developer experience. When we make changes to our codebase, we want to be able to get feedback on the results as soon as possible. Live reloading is the process of watching codebase changes and automatically rebuilding the application with the changes integrated. It can be very frustrating if you have to do this manually: save changes, stop the server, rebuild and then start the server on every change you make.</p><p>Having worked with NodeJS based frameworks and frontend frameworks such as Angular and React, most (if not all) come with live reloading built-in. Some frameworks such as Flutter take this a little further with stateful <a href="https://www.youtube.com/watch?v=sgPQklGe2K8&amp%3Bvl=en&ref=content.mainawycliffe.dev">hot reloading</a>, which I won't go into details about.</p><p>Having switched to using Golang recently, I realized I needed to solve this problem. Lucky for me, there are a few great options out there to enable this behavior. One of them is the <a href="https://github.com/cosmtrek/air?ref=content.mainawycliffe.dev">Air (github.com/cosmtrek/air)</a> - a live reloading tool for Golang apps.</p><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Having spent a ton of time with frontend frameworks such as Angular, React, one thing I really missed when working with <a href="https://twitter.com/hashtag/golang?src=hash&amp%3Bref_src=twsrc%5Etfw&ref=content.mainawycliffe.dev">#golang</a> is live reloading when you make changes in your codebase, this was until I came across air -&gt; <a href="https://t.co/r1iNOddWDL?ref=content.mainawycliffe.dev">https://t.co/r1iNOddWDL</a> <a href="https://t.co/GRFyIRJSfj?ref=content.mainawycliffe.dev">pic.twitter.com/GRFyIRJSfj</a></p>&mdash; Maina Wycliffe (@mwycliffe_dev) <a href="https://twitter.com/mwycliffe_dev/status/1510881501344419840?ref_src=twsrc%5Etfw&ref=content.mainawycliffe.dev">April 4, 2022</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure><h2 id="installing-air">Installing Air</h2><p>First, we are going to install <code>air</code>. There are a number of ways to install <code>air</code>, but the way I did it was using <code>go install</code> as I had Golang already installed:</p><pre><code class="language-sh">go install github.com/cosmtrek/air@latest
</code></pre><p>There are a number of other installation options that you can find <a href="https://github.com/cosmtrek/air?ref=content.mainawycliffe.dev#installation">here</a>.</p><h2 id="configuring-air">Configuring Air</h2><p>Next, we need to configure Air for our Golang project. You can do that by running the following command:</p><pre><code class="language-sh">air init</code></pre><p>This will create a <code>air.toml</code> file that will contain the default configurations for Air. Here is an example of what that looks like:</p><pre><code class="language-toml">root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
  bin = "./tmp/main"
  cmd = "go build -o ./tmp/main ."
  delay = 1000
  exclude_dir = ["assets", "tmp", "vendor", "testdata"]
  exclude_file = []
  exclude_regex = ["_test.go"]
  exclude_unchanged = false
  follow_symlink = false
  full_bin = ""
  include_dir = []
  include_ext = ["go", "tpl", "tmpl", "html"]
  kill_delay = "0s"
  log = "build-errors.log"
  send_interrupt = false
  stop_on_error = true

[color]
  app = ""
  build = "yellow"
  main = "magenta"
  runner = "green"
  watcher = "cyan"

[log]
  time = false

[misc]
  clean_on_exit = false

[screen]
  clear_on_rebuild = false
</code></pre><p>Next, let me highlight a few notable configurations you might care about and might want to update for your project. </p><p>Under <code>build</code> in the <code>air.toml</code>; you might want to change the <code>cmd</code> property. If the entry of your golang application is in a different directory, say <code>server</code>, you can change the property to something like this:</p><pre><code class="language-toml">cmd = "go build -o ./tmp/main ./server/main.go"</code></pre><p>Another set of config properties that you might want to pay attention to are the <code>include_dir</code>, <code>include_ext</code>, <code>exclude_dir</code> and <code>exclude_file</code> entries. The <code>include_dir</code> and <code>include_ext</code> tell Air which dir and extensions to watch for changes when live reloading, while the <code>exclude_dir</code> and <code>exclude_file</code> tell air which directories, extensions, and files not to listen to changes from.</p><p>There is also the <code>exclude_regex</code> property that allows you to ignore files matching a certain pattern, i.e. test files as it does by default. These configs allow you to configure Air based on your app structure.</p><p>For more information about Air configurations, please refer to the example file <a href="https://github.com/cosmtrek/air/blob/master/air_example.toml?ref=content.mainawycliffe.dev">here</a>.</p><h2 id="running-your-app">Running your App</h2><p>Finally, the only part that is remaining is running our Golang application using Air. You can do this by running the <code>air</code> command:</p><pre><code class="language-sh">air</code></pre><p>After that, make changes to your project and watch air live-reload your Go application.</p><h2 id="conclusion">Conclusion</h2><p>In this article, we learned how we can use Air to live-reload our go applications as we make changes to our codebase. We learned how we can initialize, the configuration we might want to change, and how to start our application afterward.</p><p>To continue learning more about Air, visit the Github repository <a href="https://github.com/cosmtrek/air?ref=content.mainawycliffe.dev">here</a>.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Golang</category>
        </item>
        <item>
            <title><![CDATA[Busy Typescript Developer's Guide to the Typescript Type System - Angular Kenya]]></title>
            <link>https://mainawycliffe.dev/blog/angular-kenya-busy-typescript-developers-guide-to-the-typescript-type-system</link>
            <guid>https://mainawycliffe.dev/blog/angular-kenya-busy-typescript-developers-guide-to-the-typescript-type-system</guid>
            <pubDate>Thu, 31 Mar 2022 19:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>My talk About Busy Typescript Developer's Guide to the Typescript Type System for Angular Kenya.</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/_ooJoQticrs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Speaking</category>
            <category>Typescript</category>
            <category>Angular</category>
        </item>
        <item>
            <title><![CDATA[JavaScript and Friends Online Meetup - Mar-17-2022 - Maina Wycliffe]]></title>
            <link>https://mainawycliffe.dev/blog/javascript-and-friends-online-meetup-mar-17-2022-maina-wycliffe</link>
            <guid>https://mainawycliffe.dev/blog/javascript-and-friends-online-meetup-mar-17-2022-maina-wycliffe</guid>
            <pubDate>Thu, 17 Mar 2022 18:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<h2 id="title">Title</h2><p>Busy TypeScript Developer's Guide to the TypeScript Type System </p><h3 id="about-the-talk">About the Talk</h3><p>TypeScript is a strongly typed language that compiles to JavaScript. The key difference between TypeScript and JavaScript is the Type System, which enables developers to write type-safe programs with fewer errors and bugs. In this session, we will look to understand the TypeScript Type System and the features and tooling TypeScript provides us to write more concrete types.</p><figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="200" height="113" src="https://www.youtube.com/embed/Sl7AZfmlAh0?start=1048&feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><figcaption>My talk About Busy Typescript Developer's Guide to the Typescript Type System for Javascript and Friends Online Meetup.</figcaption></figure>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Speaking</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Getting the Best out of TypeScript with Maina Wycliffe]]></title>
            <link>https://mainawycliffe.dev/blog/episode-173-getting-the-best-out-of-typescript-with-maina-wyclyffe</link>
            <guid>https://mainawycliffe.dev/blog/episode-173-getting-the-best-out-of-typescript-with-maina-wyclyffe</guid>
            <pubDate>Fri, 04 Mar 2022 15:07:00 GMT</pubDate>
            <content:encoded><![CDATA[<!--kg-card-begin: html--><iframe height="200px" width="100%" frameborder="no" scrolling="no" seamless src="https://player.simplecast.com/2b570fa3-1bc9-4fdd-8ce4-1832868e191f?dark=true"></iframe><!--kg-card-end: html--><p>Web Rush Episode 173: Getting the Best out of TypeScript with Maina Wycliffe</p><h2 id="episode-summary">EPISODE SUMMARY</h2><p>Maina Wycliffe talks with us about how to write better TypeScript. How does he decide when to use TypeScript? How do you deal with null? Are TypeScript Enums bad? What are our pet peeves in TypeScript? And thoughts on creating a type from another type.</p><h3 id="episode-notes">EPISODE NOTES</h3><p>Recording date: Feb 17, 2022</p><p>John Papa <a href="https://twitter.com/john_papa?ref=content.mainawycliffe.dev">@John_Papa</a></p><p>Ward Bell <a href="https://twitter.com/WardBell?ref=content.mainawycliffe.dev">@WardBell</a></p><p>Dan Wahlin <a href="https://twitter.com/danwahlin?ref=content.mainawycliffe.dev">@DanWahlin</a></p><p>Craig Shoemaker <a href="https://twitter.com/craigshoemaker?ref=content.mainawycliffe.dev">@craigshoemaker</a></p><p>Maina Wycliffe <a href="https://twitter.com/mwycliffe_dev?ref=content.mainawycliffe.dev">@mwycliffe_dev</a></p><h2 id="brought-to-you-by"><strong><strong>Brought to you by</strong></strong></h2><p><a href="https://www.ag-grid.com/?ref=content.mainawycliffe.dev">AG Grid</a></p><figure class="kg-card kg-image-card"><img src="https://johnpapa.net/content/images/2021/07/Unknown.png" class="kg-image" alt="ag-grid-logo-2" loading="lazy"></figure><p><a href="https://nx.dev/?ref=content.mainawycliffe.dev">Narwhal</a></p><p>Visit <a href="https://nx.dev/?ref=content.mainawycliffe.dev">nx.dev</a> to get the preeminent open-source toolkit for monorepo development, today.</p><figure class="kg-card kg-image-card"><img src="https://johnpapa.net/content/images/2021/07/Nx-dev-logo-h60.jpg" class="kg-image" alt="Narwhal logo" loading="lazy"></figure><h2 id="resources"><strong><strong>Resources:</strong></strong></h2><ul><li><a href="https://www.marvel.com/characters/rocket/on-screen?ref=content.mainawycliffe.dev">Yes, Bradley Cooper does voice Rocket</a></li><li><a href="https://angularjs.org/?ref=content.mainawycliffe.dev">AngularJS</a></li><li><a href="https://angular.io/?ref=content.mainawycliffe.dev">Angular</a></li><li><a href="https://www.typescriptlang.org/?ref=content.mainawycliffe.dev">TypeScript</a></li><li><a href="https://en.wikipedia.org/wiki/Nairobi?ref=content.mainawycliffe.dev">Nairobi, Kenya</a></li><li><a href="https://www.typescriptlang.org/docs/handbook/basic-types.html?ref=content.mainawycliffe.dev">Basic types in TypeScript</a></li><li><a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html?ref=content.mainawycliffe.dev#non-null-assertion-operator">Non-null assertion operator in Typescript</a></li><li><a href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html?ref=content.mainawycliffe.dev#unions">Union types in Typescript</a></li><li><a href="https://www.typescriptlang.org/docs/handbook/enums.html?ref=content.mainawycliffe.dev">Enums in Typescript</a></li><li><a href="https://blog.kevinchisholm.com/javascript/javascript-wat/?ref=content.mainawycliffe.dev">Kevin Chisholm</a></li><li><a href="https://www.typescriptlang.org/docs/handbook/2/types-from-types.html?ref=content.mainawycliffe.dev">Creating types from types in TypeScript</a></li><li><a href="https://www.typescriptlang.org/docs/handbook/utility-types.html?ref=content.mainawycliffe.dev">Utility types in Typescript</a></li><li><a href="https://mainawycliffe.dev/blog/type-assertions-in-typescript/?ref=content.mainawycliffe.dev">Type Assertions in TypeScript - why not?</a></li></ul><h2 id="timejumps"><strong><strong>Timejumps</strong></strong></h2><ul><li><strong><strong><a>01:03</a></strong></strong> Ward's haircut</li><li><strong><strong><a>02:06</a></strong></strong> Guest introduction</li><li><strong><strong><a>03:40</a></strong></strong> What made you want to use TypeScript?</li><li><strong><strong><a>05:51</a></strong></strong> How do you decide when to use TypeScript?</li><li><strong><strong><a>09:08</a></strong></strong> Sponsor: Ag Grid</li><li><strong><strong><a>10:07</a></strong></strong> How do you deal with null in TypeScript?</li><li><strong><strong><a>14:37</a></strong></strong> Are TypeScript enums are bad?</li><li><strong><strong><a>20:12</a></strong></strong> What are your pet peeves in TypeScript?</li><li><strong><strong><a>21:36</a></strong></strong> Sponsor: Nx</li><li><strong><strong><a>22:12</a></strong></strong> What's your second pest peeve?</li><li><strong><strong><a>27:25</a></strong></strong> Why would you create a type from another type?</li><li><strong><strong><a>35:52</a></strong></strong> Final thoughts</li></ul><p>Podcast editing on this episode done by <a href="https://lemonproductions.ca/?ref=content.mainawycliffe.dev">Chris Enns of Lemon Productions</a>.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>podcast</category>
            <category>A Byte of Typescript</category>
        </item>
        <item>
            <title><![CDATA[const assertions in Typescript]]></title>
            <link>https://mainawycliffe.dev/blog/const-assertion-in-typescript</link>
            <guid>https://mainawycliffe.dev/blog/const-assertion-in-typescript</guid>
            <pubDate>Fri, 25 Feb 2022 09:35:30 GMT</pubDate>
            <content:encoded><![CDATA[<p>In Typescript 4.3, typescript introduced the <code>const</code> assertions. <code>const</code> assertions are used to tell the Typescript compiler one of the following:</p><h2 id="object-properties-are-readonly">Object properties are Readonly</h2><p>When you cast an object as const, the properties are marked as read-only and cannot be modified. Let's take the following variable <code>person</code> with name and age in it.</p><pre><code class="language-typescript">const person = {
    name: "John Doe",
    age: 25,
};</code></pre><p>Its types are inferred as <code>string</code> and <code>number</code> as expected:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-5.png" class="kg-image" alt loading="lazy" width="417" height="227"></figure><p>But if we assert it as <code>const</code>, the inferred types for the person object are marked as read-only and cannot be modified.</p><pre><code class="language-typescript">const person = {
    name: "John Doe",
    age: 25,
} as const;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-6.png" class="kg-image" alt loading="lazy" width="391" height="211"></figure><p>If we tried to update the <code>age</code> field, we would get the following error: <code>Cannot assign to 'age' because it is a read-only property</code></p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-7.png" class="kg-image" alt loading="lazy" width="640" height="157" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2022/02/image-7.png 600w, https://content.mainawycliffe.dev/content/images/2022/02/image-7.png 640w"></figure><h2 id="arrays-become-readonly-tuples">Arrays become Readonly Tuples</h2><p>In my last <a href="https://mainawycliffe.dev/blog/tuple-type-in-typescript/?ref=content.mainawycliffe.dev">article</a>, we looked into tuples, which you can learn more about <a href="https://mainawycliffe.dev/blog/tuple-type-in-typescript/?ref=content.mainawycliffe.dev">here</a>. <code>const</code> assertions on an array allow us to mark an array as read-only Tuple i.e. content of the array in each position becomes a literal type that cannot be modified.</p><p>Let's take the following variable <code>personNameAge</code>, a normal array with the name at the first position and age at the second position:</p><pre><code class="language-typescript">const personNameAge = ["john doe", 25]</code></pre><p>Typescript will infer this as an array of strings or numbers i.e. <code>(string | number)[]</code>:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-8.png" class="kg-image" alt loading="lazy" width="452" height="64"></figure><p>But, if we used <code>as const</code> assertions, this becomes restricted to a readonly Tuple, with "john doe" in the first position and "25" in the second position:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-9.png" class="kg-image" alt loading="lazy" width="493" height="73"></figure><p>And its values cannot be modified:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-11.png" class="kg-image" alt loading="lazy" width="683" height="111" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2022/02/image-11.png 600w, https://content.mainawycliffe.dev/content/images/2022/02/image-11.png 683w"></figure><h2 id="a-variable-value-should-be-treated-as-literal-type">A variable value should be treated as Literal Type</h2><p>Literal types allow us to define types that are more specific, instead of something that is generalized like string or number. For example:</p><pre><code class="language-typescript">type Switch: "On" | "Off";</code></pre><p><code>const</code> assertions allows us to mark a variable value as a literal type. For instance, if we had a variable <code>onSwitch</code> and assigned the value <code>on</code>, normally typescript will infer the type of the variable as a string:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-12.png" class="kg-image" alt loading="lazy" width="334" height="73"></figure><p>But, if we used <code>const</code> assertions, it will be inferred as a literal type of <code>On</code>:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-13.png" class="kg-image" alt loading="lazy" width="328" height="71"></figure><p>And cannot accept any other variable apart from <code>On</code>:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-14.png" class="kg-image" alt loading="lazy" width="521" height="112"></figure><p>One thing to keep in mind is that <code>const</code> assertions can only be applied to simple expressions. So you can not do something like this:</p><pre><code class="language-typescript">function switchValue(input: boolean) {
    let onSwitch =  (input ? "On" : "Off") as const; // Won't work
    return onSwitch;
}</code></pre><p>The above will throw an error: <code>A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.</code></p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-16.png" class="kg-image" alt loading="lazy" width="1327" height="155" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2022/02/image-16.png 600w, https://content.mainawycliffe.dev/content/images/size/w1000/2022/02/image-16.png 1000w, https://content.mainawycliffe.dev/content/images/2022/02/image-16.png 1327w" sizes="(min-width: 720px) 720px"></figure><p>To solve the above issue, we need to apply <code>const</code> assertions on each output value of our ternary operator:</p><pre><code class="language-typescript">function switchValue(input: boolean) {
    let onSwitch =  input ? "On" as const : "Off" as ;
    return onSwitch;
}</code></pre><p>And the type of <code>onSwitch</code> variable get inferred to a literal type union <code>On</code> | <code>Off</code>:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-15.png" class="kg-image" alt loading="lazy" width="509" height="121"></figure><h2 id="conclusion">Conclusion</h2><p>In this article, we looked at <code>const</code> assertions and how we can use it within our code. We learned that we can use it to mark an object field as read-only, create a read-only Tuple, and mark a variable's value as a Literal type instead of widening it to its based type i.e. string, number, etc.</p><p>Thank you for reading this article, if you are interested in more typescript content, check out my previous articles <a href="https://mainawycliffe.dev/blog/tags/a-byte-of-typescript/?ref=content.mainawycliffe.dev">here</a>, follow me on <a href="https://twitter.com/mwycliffe_dev?ref=content.mainawycliffe.dev">Twitter</a> and <a href="https://www.linkedin.com/in/mainawycliffe?ref=content.mainawycliffe.dev">LinkedIn</a>. And you can also join my new <a href="https://twitter.com/i/communities/1491713662867984387?ref=content.mainawycliffe.dev">community</a> on Twitter for all Typescript developers, where we can learn, share and connect with each other.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[The Tuple Type in Typescript]]></title>
            <link>https://mainawycliffe.dev/blog/tuple-type-in-typescript</link>
            <guid>https://mainawycliffe.dev/blog/tuple-type-in-typescript</guid>
            <pubDate>Mon, 21 Feb 2022 20:19:30 GMT</pubDate>
            <content:encoded><![CDATA[<p>A tuple type is an array with a predefined length and predefined types in each index position in the array. The types inside this array do not have to be the same, could be a mixture of different types. In a normal array, it can contain anywhere from zero to an unknown number of elements and order is not important.</p><p>This is where a Tuple differentiates itself from an array. In a tuple, the type of each element, the length of the array, and the order in which the elements are ordered in the array are important. I.e. it should always return an array of length 2, with the first element being a string and the second element being a number.</p><p>To define a Tuple type, we use syntax similar to Javascript array syntax but instead of specifying the values, we specify the type in each index location, as shown below.</p><pre><code class="language-typescript">type PersonNameAge = [string, number];</code></pre><p>In the example above, we are defining a Tuple type <code>PersonaNameAge</code>, as an array of length two, with the first element being a string for persons' name, and the next element being a number for persons' Age. </p><p>We can then go ahead and use the above tuple as follows:</p><pre><code class="language-typescript">const personNameAge: PersonNameAge = ["John Doe", 25] // this doesn't throw an error</code></pre><p>If we don't provide enough elements matching the length of fields defined in the <code>PersonNameAge</code> tupple, then Typescript will throw the following error:</p><pre><code class="language-typescript">const personNameAge: PersonNameAge = []

// Error:
Type '[]' is not assignable to type 'PersonNameAge'.
  Source has 0 element(s) but target requires 2.

// the same thing happens if provide more elements
const personNameAge: PersonNameAge = ["John Doe",25, true]

// ERROR:
Type '[string, number, number]' is not assignable to type 'PersonNameAge'. 
  Source has 3 element(s) but target allows only 2.</code></pre><p>And if we specified the types not matching the types specified in their index location, Typescript will throw the following error:</p><pre><code class="language-typescript">const personaNameAge: PersonNameAge = [25,"John Doe"]
                                            ~~ ERROR: Type 'string' is not assignable to type 'number'.(2322)
</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-4.png" class="kg-image" alt="The Tuple Type in Typescript" loading="lazy" width="837" height="116" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2022/02/image-4.png 600w, https://content.mainawycliffe.dev/content/images/2022/02/image-4.png 837w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-2.png" class="kg-image" alt="The Tuple Type in Typescript" loading="lazy" width="856" height="132" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2022/02/image-2.png 600w, https://content.mainawycliffe.dev/content/images/2022/02/image-2.png 856w" sizes="(min-width: 720px) 720px"></figure><h2 id="why-tuple">Why Tuple</h2><p>Tuples have several benefits, the first one being able to return more than one value from a function. Take for instance the following function:</p><pre><code class="language-typescript">function doSomething(): [string, number] {
    // do something
}</code></pre><p>It can return two values, a string and a number, which the caller can assign to variables. This leads to the second benefit, being able to destructure them easily to a variable name of choice i.e. being able to assign the return values of the tuple directly to their variables as shown below.</p><pre><code class="language-typescript">const [str, nmb] = doSomething();</code></pre><p>If you returned an object instead of a tuple, destructing takes an extra step of needing to rename the field, especially if there is a variable name collision. You can also ignore the return type of Tuple by using an underscore <code>(_)</code> character if you wanted to access the value of a variable that is in a much higher index position.</p><pre><code class="language-typescript">const [_, nmb] = doSomething();</code></pre><h2 id="examples-of-tuples-in-action">Examples of Tuples in Action</h2><p>In this section, I thought it was prudent to highlight a few places where tuples are in use out in the wild:</p><h3 id="promiseall">Promise.all()</h3><blockquote>The <strong><code>Promise.all()</code></strong> method takes an iterable of promises as an input, and returns a single <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise?ref=content.mainawycliffe.dev"><code>Promise</code></a> that resolves to an array of the results of the input promises. - <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all?ref=content.mainawycliffe.dev">MDN Docs</a></blockquote><p>This is a perfect use case of Tuples return type as each promise resolved is returned at the index position it was in inside the input. So, an input of promise a,b,c returns results of the promises of a,b,c in their respective index position in which they were in the input.</p><pre><code class="language-typescript">async function apiCall1() {
    return "";
}

async function apiCall2() {
    return 1;
}

async function apiCall3() {
    return false;
}

async function main() {
    const x = await Promise.all([apiCall1(), apiCall2(), apiCall3()])
}</code></pre><p>The type of valuable <code>x</code> will be a Tuple: <code>[string, number, boolea]</code>:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2022/02/image-1.png" class="kg-image" alt="The Tuple Type in Typescript - Promise.all example" loading="lazy" width="622" height="301" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2022/02/image-1.png 600w, https://content.mainawycliffe.dev/content/images/2022/02/image-1.png 622w"></figure><p>We can destructure the above <code>Promise.all()</code> as follows, with each variable getting assigned the correct types.</p><pre><code class="language-typescript">const [str, num, bool] = await Promise.all([apiCall1(), apiCall2(), apiCall3()])</code></pre><h3 id="reactusestate">React - useState</h3><p>Another use case can be found in React hooks - <code>useState</code>. <code>useState</code> is used to declare a state variable in react functional components and returns a tuple of value and a dispatch function to update the state variable.</p><pre><code class="language-typescript">const [count, setCount] = useState(0);
</code></pre><p>In the above example, the <code>count</code> variable is a number and the <code>setCount</code> variable is a dispatch function whose input parameter accepts a number. This allows you to have multiple state variables which are easily assigned unique variable names using array destructuring, as shown below:</p><pre><code class="language-typescript">const [count, setCount] = useState(0);
const [name, setName] = useState("John Doe")</code></pre><p>There are other use cases but these are the most common ones I could come up with. </p><h2 id="conclusion">Conclusion</h2><p>In this article, we covered the Tuple type in typescript, how and why we should use them. Tuples are special arrays that have their length predefined and the types at each index position of the array being predetermined and may vary from one index position to another. On top of that, we covered two particularly common use cases for Tuples and saw how we benefit from this Tuples usage in the real world.</p><p>Thank you for reading this article, if you are interested in more typescript content, check out my previous articles <a href="https://mainawycliffe.dev/blog/tags/a-byte-of-typescript/?ref=content.mainawycliffe.dev">here</a>, follow me on <a href="https://twitter.com/mwycliffe_dev?ref=content.mainawycliffe.dev">Twitter</a> and <a href="https://www.linkedin.com/in/mainawycliffe?ref=content.mainawycliffe.dev">LinkedIn</a>. And you can also join my new <a href="https://twitter.com/i/communities/1491713662867984387?ref=content.mainawycliffe.dev">community</a> on Twitter for all Typescript developers, where we can learn, share and connect with each other.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Writing Tests for MongoDB using Dockertest in Go]]></title>
            <link>https://mainawycliffe.dev/blog/using-dockertest-to-write-integration-tests-against-mongodb</link>
            <guid>https://mainawycliffe.dev/blog/using-dockertest-to-write-integration-tests-against-mongodb</guid>
            <pubDate>Mon, 03 Jan 2022 11:54:08 GMT</pubDate>
            <content:encoded><![CDATA[<p>Dockertest enables us to use Docker to create containers to run our tests against. With dockertest, we can use it to create a Docker container for our tests, which we can then connect to and run our tests against. And then remove the container afterward. This means that every time we run the tests, we get a sanitized environment that is not contaminated by the test data from previous tests.</p><h2 id="prerequisites">Prerequisites </h2><ul><li>Prior knowledge in MongoDB, Go, and Docker.</li><li>Docker: You can find installation instructions can be found <a href="https://docs.docker.com/engine/install/?ref=content.mainawycliffe.dev">here</a>.</li><li>Golang: You can find installation instructions can be found <a href="https://go.dev/doc/install?ref=content.mainawycliffe.dev">here</a>.</li></ul><h2 id="getting-started">Getting Started</h2><p>In this tutorial, we will run how we can use dockertest to write tests for our MongoDB database.</p><p>To demonstrate how to use dockertest for testing, we will build a very barebone todo app backend. It will have a few methods that will use MongoDB to store and retrieve the todos. We will have a few methods: <code>AddTodo</code>, <code>DeleteTodo</code>, <code>GetTodo</code>, <code>ListTodos</code> and <code>ToggleTodo</code> and here is the code implementation of the above methods:</p><figure class="kg-card kg-code-card"><pre><code class="language-go">package todos

import (
	"context"

	"github.com/mainawycliffe/todo-dockertest-golang-mongo-demo/model"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
)

type Todos struct {
	client *mongo.Client
}

func (todos *Todos) AddTodo(todo model.Todo) (model.Todo, error) {
	collection := todos.client.Database("todos").Collection("todos")
	result, err := collection.InsertOne(context.Background(), todo)
	todo.ID = result.InsertedID.(primitive.ObjectID)
	return todo, err
}

func (todos *Todos) DeleteTodo(id string) error {
	collection := todos.client.Database("todos").Collection("todos")
	objectID, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return err
	}
	_, err = collection.DeleteOne(context.Background(), model.Todo{
		ID: objectID,
	})
	return err
}

func (todos *Todos) GetTodo(id string) (model.Todo, error) {
	todo := model.Todo{}
	collection := todos.client.Database("todos").Collection("todos")
	objectID, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return model.Todo{}, err
	}
	err = collection.FindOne(context.Background(), bson.M{
		"_id": objectID,
	}).Decode(&amp;todo)
	return todo, err
}

func (todos *Todos) GetTodos() ([]model.Todo, error) {
	collection := todos.client.Database("todos").Collection("todos")
	cursor, err := collection.Find(context.Background(), bson.M{})
	if err != nil {
		return nil, err
	}
	var todoList []model.Todo
	if err := cursor.All(context.Background(), &amp;todoList); err != nil {
		return nil, err
	}
	return todoList, nil
}

func (todos *Todos) ToggleTodo(id string) error {
	collection := todos.client.Database("todos").Collection("todos")
	objectID, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return err
	}
	todo, err := todos.GetTodo(id)
	if err != nil {
		return err
	}
	_, err = collection.UpdateOne(context.Background(), bson.M{
		"_id": objectID,
	}, bson.M{
		"$set": bson.M{
			"isDone": !todo.IsDone,
		},
	})
	return err
}
</code></pre><figcaption>View on <a href="https://github.com/mainawycliffe/todo-dockertest-golang-mongo-demo/blob/main/todos/todos.go?ref=content.mainawycliffe.dev">GitHub</a></figcaption></figure><p>Now that we have our barebone todo app backend, let's write tests for it using dockertest. The first thing we are going to do is install dockertest by running the following command:</p><pre><code class="language-go">go get -u github.com/ory/dockertest/v3</code></pre><h2 id="setup-and-teardown-using-testmain">Setup and Teardown using TestMain</h2><p>We are going to be using <code>TestMain</code> to set up our MongoDB container using dockertest for testing and remove the container after we are done running the tests. </p><p><code>TestMain</code> in Go provides us with more control on how our tests are run, in our case, allowing us to use dockertest to set up a MongoDB container and connect to it and after the tests have run, remove it. This ensures that for every test we run, we have a fresh database to run tests against that is not contaminated by test data from the previous tests.</p><h3 id="setup-mongodb-docker-container">Setup MongoDB Docker Container</h3><p>We are going to start by defining a database client variable to store the MongoDB connection to the test database that will be spun up. We will pass this client to the <code>Todo</code> struct that we will create when running the tests. </p><pre><code class="language-go">var db *mongo.Client

func TestMain(m *testing.M) {
  // setup and teardown code goes in here 
}</code></pre><p>Next, inside the <code>TestMain</code> function, we are going to create a new <code>Pool</code>. A <code>Pool</code> is a dockertest struct that represents a connection to the Docker API and is used to create and remove the docker container when running tests. </p><pre><code class="language-go">pool, err := dockertest.NewPool("")

if err != nil {
	log.Fatalf("Could not connect to docker: %s", err)
}</code></pre><blockquote><strong>NB: </strong>Please make sure to import dockertest properly - to include the version of dockertest: <code>github.com/ory/dockertest/v3</code> and not <code>github.com/ory/dockertest</code> as VS Code might import it.</blockquote><p>And then, we are going to define a few environment variables that will be passed to our MongoDB containers. For the MongoDB container, we need to pass the <code>MONGO_INITDB_ROOT_USERNAME</code> and <code>MONGO_INITDB_ROOT_PASSWORD</code> which are going to set the credentials for the superuser for our MongoDB Database. The environment variables are defined as a String Array, with each entry of the array being a string in the following format: <code>KEY=VALUE</code>.</p><pre><code class="language-go">environmentVariables := []string{
	"MONGO_INITDB_ROOT_USERNAME=root",
	"MONGO_INITDB_ROOT_PASSWORD=password",
}</code></pre><p>Next, we need to create a docker container using the <code>pool.Run</code> function which accepts the docker image to use, the tag, and the environment variables we defined above.</p><pre><code class="language-go">resource, err := pool.Run("mongo", "5.0", environmentVariables)
if err != nil {
	log.Fatalf("Could not start resource: %s", err)
}</code></pre><p>And the final step for the setup is to try and connect to our MongoDB container and we will do this by creating a database client and pinging our database to ensure we can connect to our MongoDB container successfully.</p><pre><code class="language-go">if err = pool.Retry(func() error {
	var err error
	db, err = mongo.Connect(
		context.TODO(),
		options.Client().ApplyURI(
				fmt.Sprintf("mongodb://root:password@localhost:%s", resource.GetPort("27017/tcp")),
		),
	)
	if err != nil {
		return err
	}
	return db.Ping(context.TODO(), nil)
}); err != nil {
	log.Fatalf("Could not connect to docker: %s", err)
}</code></pre><p>After that, we can seed our database with test data if we have any. And then we can run our package tests by calling <code>m.Run()</code>.</p><pre><code class="language-go">// seed data

// Run tests
exitCode := m.Run()</code></pre><h3 id="teardown">Teardown</h3><p>Once our tests are all done, we are going to kill and remove the container.</p><pre><code class="language-go">if err = pool.Purge(resource); err != nil {
	log.Fatalf("Could not purge resource: %s", err)
}
</code></pre><p>And finally, we can call <code>os.Exit()</code> passing the exit code from <code>m.Run()</code> above.</p><pre><code class="language-go">os.Exit(exitCode)</code></pre><p>And that's it for our <code>TestMain</code>, here is what the method should look like now:</p><pre><code class="language-go">var db *mongo.Client

func TestMain(m *testing.M) {
	// Setup
	pool, err := dockertest.NewPool("")
	if err != nil {
		log.Fatalf("Could not connect to docker: %s", err)
	}
	
	environmentVariables := []string{
		"MONGO_INITDB_ROOT_USERNAME=root",
		"MONGO_INITDB_ROOT_PASSWORD=password",
	}
	
	resource, err := pool.Run("mongo", "5.0", environmentVariables)
	if err != nil {
		log.Fatalf("Could not start resource: %s", err)
	}

	// exponential backoff-retry, because the application in the container might not be ready to accept connections yet
	if err = pool.Retry(func() error {
		var err error
		db, err = mongo.Connect(
			context.TODO(),
			options.Client().ApplyURI(
				fmt.Sprintf("mongodb://root:password@localhost:%s", resource.GetPort("27017/tcp")),
			),
		)
		if err != nil {
			return err
		}
		return db.Ping(context.TODO(), nil)
	}); err != nil {
		log.Fatalf("Could not connect to docker: %s", err)
	}

	// seed data

	// Run tests
	exitCode := m.Run()

	// Teardown
	// When you're done, kill and remove the container
	if err = pool.Purge(resource); err != nil {
		log.Fatalf("Could not purge resource: %s", err)
	}

	// Exit
	os.Exit(exitCode)
}</code></pre><p>Next, let's write a few tests for our code:</p><h2 id="writing-tests-against-mongodb">Writing Tests Against MongoDB</h2><p>We will start by writing the simplest one, the <code>AddTodo</code> test. We are going to add a todo and then assert that error is nil and also check in the database to make sure that the todo exists in the database:</p><pre><code class="language-go">func TestAddTodo(t *testing.T) {
	todos := Todos{
		client: db,
	}
	createdAt := primitive.Timestamp{
		T: uint32(time.Now().Unix()),
		I: 0,
	}
	todo := model.Todo{
		Todo:      "test",
		IsDone:    false,
		CreatedAt: createdAt,
		UpdatedAt: createdAt,
	}
	// add todo
	todo, err := todos.AddTodo(todo)
	// assert error is nil
	assert.Nil(t, err)
	// assert todo ID is not not nil
	assert.NotNil(t, todo.ID)
	// fetch todo from the database
	todoGet, err := todos.GetTodo(todo.ID.Hex())
	// assert error is nil
	assert.Nil(t, err)
	// assert todo is equal to the todo returned from the database
	assert.Equal(t, todoGet, todo)
}</code></pre><p>For the <code>GetTodo</code> test, we are going to add a new todo first and then use <code>GetTodo</code> method to retrieve the todo we added and assert that they are Equal:</p><pre><code class="language-go">func TestGetTodo(t *testing.T) {
	todos := Todos{
		client: db,
	}
	createdAt := primitive.Timestamp{
		T: uint32(time.Now().Unix()),
		I: 0,
	}
	todo := model.Todo{
		Todo:      "Test Get Todo",
		IsDone:    false,
		CreatedAt: createdAt,
		UpdatedAt: createdAt,
	}
	todoAdd, err := todos.AddTodo(todo)
	assert.Nil(t, err)
	todoGet, err := todos.GetTodo(todoAdd.ID.Hex())
	assert.Nil(t, err)
	assert.Equal(t, todoGet.Todo, todo.Todo)
}
</code></pre><p>And the final test I want to focus on is the test for <code>ToggleTodo</code> which marks a todo as done or vice versa based on the current status. In this one, we are going to add a todo and then toggle, retrieve it from the database and then check <code>IsDone</code> is not equal to the original <code>IsDone</code> property.</p><pre><code class="language-go">func TestToggleTodo(t *testing.T) {
	todos := Todos{
		client: db,
	}
	createdAt := primitive.Timestamp{
		T: uint32(time.Now().Unix()),
		I: 0,
	}
	todo := model.Todo{
		Todo:      "Test Toggle Todo",
		IsDone:    false,
		CreatedAt: createdAt,
		UpdatedAt: createdAt,
	}
	todoAdd, err := todos.AddTodo(todo)
	assert.Nil(t, err)
	err = todos.ToggleTodo(todoAdd.ID.Hex())
	assert.Nil(t, err)
	todoGet, err := todos.GetTodo(todoAdd.ID.Hex())
	assert.Nil(t, err)
	assert.NotEqual(t, todoGet.IsDone, todo.IsDone)
}</code></pre><p>The rest of the tests can be found <a href="https://github.com/mainawycliffe/todo-dockertest-golang-mongo-demo/blob/main/todos/todos_test.go?ref=content.mainawycliffe.dev">here</a> on GitHub.</p><h2 id="conclusion">Conclusion</h2><p>In this article, we learned how we can use dockertest to create MongoDB containers that we can write tests against. Dockertest uses docker to create a test container during the setup process and remove the docker container after all tests have run ensuring a sanitized test Database every time.</p><p>For more information on dockertest, you can find the repository <a href="https://github.com/ory/dockertest?ref=content.mainawycliffe.dev">here</a>.</p><h3 id="source-code">Source Code</h3><p>You can find the source code for the examples given in this article <a href="https://github.com/mainawycliffe/todo-dockertest-golang-mongo-demo?ref=content.mainawycliffe.dev">here</a>. </p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Golang</category>
            <category>Docker</category>
        </item>
        <item>
            <title><![CDATA[Type Assertions in TypeScript - why not?]]></title>
            <link>https://mainawycliffe.dev/blog/type-assertions-in-typescript</link>
            <guid>https://mainawycliffe.dev/blog/type-assertions-in-typescript</guid>
            <pubDate>Thu, 30 Dec 2021 10:29:49 GMT</pubDate>
            <content:encoded><![CDATA[<p>A while back, I had a look at why you should avoid using the <code>any</code> type and instead use the <code>unknown</code> type, which you can read <a href="https://mainawycliffe.dev/blog/typescript-use-unknown-instead-of-any/?ref=content.mainawycliffe.dev">here</a>. In this article, I want to focus on Type assertion and why you should avoid them. </p><p>So, what are Type Assertions? Types assertion is a way of telling Typescript what the type of a variable is. This can be done either of two ways: using the <code>as</code> syntax or the angle bracket <code>&lt;Type&gt;</code> syntax, as shown below:</p><pre><code class="language-typescript">type Person = {
    firstname: string;
    lastname: string;
}

// using as syntax
const x : unknown = {};

// asserting it as Person using as syntax
const firstname = (x as Person).firstname;

// asserting it as Person using the angle brackets
const firstname = (&lt;Person&gt;x).firstname;
</code></pre><p>When we use type assertion we are basically telling the Typescript compiler that we know what the type is and it should trust us, i.e. we know what we are doing. The problem with this is that we prevent Typescript from helping us where it should and take on that responsibility ourselves. </p><p>In the above example, Typescript does not type check whether the variable <code>x</code> has the property <code>firstname</code> we are accessing because we are asserting the type, which will definitely introduce a bug into our system.</p><h3 id="non-null-assertions">Non-null Assertions</h3><p>Another common type of assertion is a non-null assertion. In this assertion, we use the <code>!</code> operator after variable to tell the Typescript compiler that a variable isn't null.</p><pre><code class="language-typescript">function square(x: number) {
	return x * x;
}

const x : number | undefined;

const answer = square(x!);</code></pre><p>This assertion should be used sparingly, especially if the null suggestion is coming from external API typing like environment variables, which are always typed as <code>string | undefined</code>. I have come across not-so-obvious bugs that were thrown in a completely different section of the code with a different error message because I allowed an undefined variable to be passed on. This happened because instead of handling the possibility of the environment variable being undefined, I decided non-null assertion was the way to go.</p><h2 id="so-what-are-the-alternatives">So, what are the Alternatives?</h2><h3 id="narrowing-of-types">Narrowing of Types</h3><p>Type narrowing is the process of moving a less precise type to a more precise type. For instance, taking a variable of type <code>any</code> and moving it to string. There are various ways of achieving this, which I have covered previously <a href="https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript/?ref=content.mainawycliffe.dev">here</a>, but I will take a look at a few notable ones.</p><p><strong>Type Guards:</strong> You can use Type Guards to narrow the types of a <code>union</code>, <code>unknown</code>, <code>any</code>, etc. to a specific type:</p><pre><code class="language-typescript">function doSomething(x: string | number) {
    if(typeof x === "string") {
    	// do somethign with the string
    } else {
    	// do something with the number
    }
}</code></pre><p><strong>Truthiness Narrowing: </strong>You can check if a variable is truthy i.e. not undefined or null before using it:</p><pre><code class="language-typescript ">function doSomething(x?: string) {
	if(x) {
		// type of x is now string
	}
}</code></pre><p><strong>Building Custom Type Guards: </strong>And finally, you can create type guards that do an exhaustive type checking on an object before asserting its type:</p><pre><code class="language-typescript">function isRectangle(shape: unknown): shape is Rectangle {
  if ("width" in shape &amp;&amp; "height" in shape) {
  	// this is a rectangle
  	return true; 
  }
  // it's not a rectangle
  return false;
}</code></pre><p>You can learn more about custom-type guards <a href="https://mainawycliffe.dev/blog/custom-type-guards-in-typescript/?ref=content.mainawycliffe.dev">here</a>.</p><p>You can learn more about the narrowing of types in Typescript in my previous article <a href="https://mainawycliffe.dev/blog/typescript-use-unknown-instead-of-any/?ref=content.mainawycliffe.dev">here</a>.</p><h3 id="providing-default-values">Providing Default Values</h3><p>This mostly works with null and undefined values, but instead of asserting to a string to remove the possibility of it being undefined, you can provide a default value that automatically becomes a string. You can achieve this by using either null coalescing operator (<code>??</code>) or the or ( <code>||</code>) operator. </p><pre><code class="language-typescript">// using the nullish coalescing operator
const API_URL = process.ENV.API_URL ?? "DEFAULT URL";

// using the OR (||) logical operator
const API_URL = process.ENV.API_URL || "DEFAULT URL";

</code></pre><p>We can also use Javascripts Logical Assignment Operator to provide a default value:</p><pre><code class="language-typescript ">let x : string | number;

// provide a default value if null or undefined
x ??= "Hello World"

// provide a default value if falsy
x ||= "Hello World"</code></pre><h2 id="conclusion">Conclusion</h2><p>In this article, we learned that by using type assertions, we are removing the ability of the Typescript compiler to do Type checking for us. We also covered a few techniques we can use to avoid type assertions in Typescript.</p><p>If you liked this article and would like to keep learning, visit my new series on Typescript - <a href="https://mainawycliffe.dev/blog/tags/a-byte-of-typescript?ref=content.mainawycliffe.dev">A Byte of Typescript</a>. A Byte of Typescript is a new series that I will be publishing on a regular basis to help you demystify Typescript.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
        </item>
        <item>
            <title><![CDATA[Template String Types as Discriminants in Typescript 4.5]]></title>
            <link>https://mainawycliffe.dev/blog/template-string-types-as-discriminants</link>
            <guid>https://mainawycliffe.dev/blog/template-string-types-as-discriminants</guid>
            <pubDate>Wed, 17 Nov 2021 21:56:10 GMT</pubDate>
            <content:encoded><![CDATA[<p>Typescript 4.5 was just released and one of the features that stood out to me is the Template String Types as Discriminants. In this article, we are going to explore this new feature using rudimentary examples.  In my last <a href="https://mainawycliffe.dev/blog/better-types-using-discriminated-types-in-typescript/?ref=content.mainawycliffe.dev">article</a>, we covered using discriminated unions to write better types that are easy to narrow. </p><p>This is an extension of that but instead of having a concrete literal type, you can use a non-concrete literal type i.e. <em>string</em>, <em>number</em>, etc instead as part of the template literal type, and Typescript will be able to use it as a discriminant.</p><p>In order to understand this feature, we are going to start by creating two types: <code>SuccessType</code> and <code>ErrorType</code>. They are going to represent possible responses for different operations we can perform in a computer system i.e. HTTP Request, FTP Request, IO Request, etc. So, if an HTTP request succeeds we get a <code>SuccessType</code> data, if it fails we get an <code>ErrorType</code> data.</p><p>For the two types, each will have a <code>type</code> property, which we can use to discriminate between the two types when they are used in a union i.e. <code>ResponseType</code> union. But Instead of using a concrete literal type, we will use a template string type instead.</p><p>This means that the resulting template literal type could be any string combined with <code>Success</code> or <code>Error</code>  i.e. <code>${string}Success</code> and <code>${string}Error</code>. This will allow our success type to cover a number of possible operations like <code>httpSuccess</code>, <code>ftpSuccess</code>, etc. and the same goes for <code>ErrorType</code>.</p><pre><code class="language-typescript ">type SuccessType = {
    type: `${string}Success`,
    data: Record&lt;string, unknown&gt;;
}

type ErrorType = {
    type: `${string}Error`,
    message: string;
}

type ResponseType = SuccessType | ErrorType;</code></pre><pre><code class="language-typescript ">function processHTTPResponse(response: ResponseType) {
    // function body here
}</code></pre><p>In previous versions, Typescript won't be able to narrow down the type of the <code>ResponseType</code> union based on the type field, as shown below. </p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/11/image.png" class="kg-image" alt="Template String Types as Discriminants in Typescript 4.5" loading="lazy" width="600" height="113" srcset="https://content.mainawycliffe.dev/content/images/2021/11/image.png 600w"></figure><p>But as of the latest version (4.5 and above), typescript is able to narrow the type of <code>response</code> to <code>SuccessType</code> as shown below.</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/11/image-1.png" class="kg-image" alt="Template String Types as Discriminants in Typescript 4.5" loading="lazy" width="611" height="118" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/11/image-1.png 600w, https://content.mainawycliffe.dev/content/images/2021/11/image-1.png 611w"></figure><p>As you can imagine, this opens up a world of new possibilities by providing a literal type that is not concrete, typescript can discriminate between two unions as long as the field used to discriminate is contained in the string being compared to. Here is another rudimentary example:</p><pre><code class="language-typescript">type HttpOK = {
    status: `2${string}`;
    data: string;
}

type Http500 = {
    status: `5${number}`;
    message: string;
}

type Http300 = {
    status: `3${string}`;
    redirect: string;   
}

function processResponse(response: HttpOK | Http300 | Http500) {
    if(response.status === "200") {
        console.log(response.data);
    }

    if(response.status === "300") {
        console.log(response.redirect);
    }

    if(response.status === "500") {
        console.log(response.message);
    }
}</code></pre><p>Here is a link to <a href="https://www.typescriptlang.org/play?ts=4.5.0-beta&amp%3Bssl=28&amp%3Bssc=2&amp%3Bpln=1&amp%3Bpc=1&ref=content.mainawycliffe.dev#code/C4TwDgpgBAEsxgPIGkoF4oG8CwAoKBUAzsAIbACuRAXFAAYBMAJJiQE4CWAdgOYC+dANx5CUACblStdtx7DcfPHlCRY8MAFYADFvRYRhEuSq06GllwoBbAEYQ2A+aKsQiRUjwjTgnXvMW4yuDQcAgAzDp6OPiGZJQ09GEsMryOBgRsEGIcmQDGwN6+coR4AXgAZhRc+RwA9lxQYGy1ua5EAEquYPVEEAAUmUTdXL20oUioAD5q4ZHT49paAJT6MQQc5QNdPRAAdEbx6GgYAEQMOicr0aKiuT21ADZ7D7U8W0M7uxJkS06EZWsoBt3sNevs4lQjqcIlpLqsboQ7iNHs9XiDPplsnlgL90lAAaJgYNQXsDpDjqdFnDrgioEiiCjdi83sTPi43B4ILjAQE+EA">Typescript Playground</a> for the above code.</p><h2 id="conclusion">Conclusion</h2><p>In this brief article, we looked at a new feature coming to Typescript v4.5 for using Template String Types as a discriminant. This allows us to build more versatile types by relying on a template pattern for the discriminant property rather than an exact string.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Better Types using Discriminated Unions in TypeScript]]></title>
            <link>https://mainawycliffe.dev/blog/better-types-using-discriminated-types-in-typescript</link>
            <guid>https://mainawycliffe.dev/blog/better-types-using-discriminated-types-in-typescript</guid>
            <pubDate>Sun, 26 Sep 2021 13:31:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>How we define our types in Typescript impacts how effective typescript is at warning us when we make mistakes. If we take a broad approach i.e. to cover many types in a single type, we end up handicapping typescript and it becomes less effective. </p><p>The more specific we are, the more effective typescript can be at catching possible errors. In this article, we are going to look at how we can use discriminative unions to write better and more specific types and help typescript to be more helpful to us.</p><p>Let's take the simplest example I can think of - <strong>Shapes</strong>. In shapes, we can have Circles, Rectangles, Squares, etc; you get the idea. There is no way you can have a single type alias that can cover all shapes without compromising on something.</p><p>If we were to define a <code>Shape</code> type alias for just the above 3 shapes, it would need to account for the possibility that all fields are not there for all shapes, i.e. Circle only has a radius, which doesn't exist in either Rectangle or Square, while the circle doesn't have either width or height. As you can imagine, our problem only becomes bigger as you add more shapes.</p><p>So, our type alias would look like this.</p><figure class="kg-card kg-code-card"><pre><code class="language-typescript">type Shape = {
  radius?: Number; // Circle
  length?: Number; // Rectangle
  width?: Number; // Reactangle
  side?: Number; // Square side Length
}</code></pre><figcaption>For the purpose of this above example, I am assuming that the Square can't take height and width.&nbsp;</figcaption></figure><p>As you can see, the type alias above is not very useful, since if you had a circle, you could easily leave out all fields or add all of them to <code>Shape</code> and typescript will not be able to help you at all. </p><p>This is especially not a good practice for third-party SDKs, where you have to keep referring to the documentation just to get an idea of the shape of the data you are dealing with. Types help us avoid making silly and avoidable mistakes, which we all make as it's in our nature as human beings.</p><p>On top of that, we also lose out on the ability to narrow types. It's not easy to narrow the above type to either Circle, Rectangle, or Square.</p><blockquote>Type narrowing is the process of moving a type from a less precise type to a more precise type. You can learn more about type narrowing <a href="https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript?ref=content.mainawycliffe.dev">here</a>.</blockquote><h2 id="discriminated-unions">Discriminated Unions</h2><blockquote>A discriminated type union is where you use code flow analysis to reduce a set of potential objects down to one specific object. - Typescript <a href="https://www.typescriptlang.org/play?ref=content.mainawycliffe.dev#example/discriminate-types">Docs</a></blockquote><p>Now, let me offer a possible solution to the above problem. We will start by defining three different type-aliases. Each type alias will have a literal type member property - <code>shape</code> - distinguishing for its corresponding shape i.e. <code>Rectangle</code>, <code>Circle</code>, and <code>Square</code> for each of our shapes.</p><pre><code class="language-typescript">type Square = {
  shape: "Square";
  side: number;
}

type Rectangle = {
  shape: "Rectangle",
  length: number;
  width: number;
}

type Circle = {
  shape: "Circle"
  radius: number;
}
</code></pre><p>And then we can use a union of the three to declare a type alias of shape that can only be a single type of the above.</p><pre><code class="language-typescript">type Shape = Square | Rectangle | Circle;</code></pre><blockquote>The <code>Shape</code> type alias can only be Square, Rectangle or Circle.</blockquote><p>So, what is the advantage of the above you may ask? </p><h3 id="strongly-typed-shapes">Strongly Typed Shapes</h3><p>The first advantage is that our types are now strongly typed for each shape as compared to the previous solution. For instance, if you specify the shape to be <strong>Circle</strong>, then, we only provide radius and if it's missing, Typescript throws an error.</p><pre><code class="language-typescript">const x: Shape = {
  shape: "Circle",
  radius: 5,
  width: 5, // Error ---&gt; Object literal may only specify known properties, and 'width' does not exist in type 'Circle'.
}</code></pre><p>As you can see above, once you specify the shape property to be <code>Circle</code>, then you are restricted to only specifying properties available in the <code>Circle</code> type alias. </p><p>Trying to add fields that do not exist will result in the following error: <code>// Error ---&gt; Object literal may only specify known properties, and 'width' does not exist in type 'Circle'.</code></p><h3 id="type-narrowing-is-now-possible">Type Narrowing is Now Possible</h3><p>Type narrowing is now possible using the literal property <code>shape</code>.</p><pre><code class="language-typescript">if(shape.shape === "Circle") {
  // the type is now a Circle only
}</code></pre><p>Learn more about Type Narrowing in typescript <a href="https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript?ref=content.mainawycliffe.dev">here</a>.</p><h2 id="conclusion">Conclusion</h2><p>In this article, we learned how we can use discriminated unions to write more specific types in Typescript, and thus better types overall and have an improved developer experience. This allows us in turn to write more type-safe code, which can help typescript eliminate a lot of bugs from our code that would otherwise slip through. </p><p>If you found this article informative and would like to keep learning about typescript, visit my series on Typescript - <a href="https://mainawycliffe.dev/blog/tags/a-byte-of-typescript?ref=content.mainawycliffe.dev">A Byte of Typescript</a>. A Byte of Typescript is a new series that I will be publishing on a regular basis to help you demystify Typescript.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[All Things TypeScript ft. Wycliffe Maina - AiA 326]]></title>
            <link>https://mainawycliffe.dev/blog/all-things-typescript-ft-wycliffe-maina-aia-326</link>
            <guid>https://mainawycliffe.dev/blog/all-things-typescript-ft-wycliffe-maina-aia-326</guid>
            <pubDate>Thu, 23 Sep 2021 08:19:00 GMT</pubDate>
            <content:encoded><![CDATA[<!--kg-card-begin: html--><iframe src="https://player.fireside.fm/v2/EijgUSsq+BqcvvpRW?theme=dark" width="740" height="200" frameborder="0" scrolling="no"></iframe><!--kg-card-end: html--><h3 id="about-this-episode">About this Episode</h3><p>In this Podcast, I join the adventure in angular as a Guest to discuss the ins and outs of Typescript and several tips and tricks for using TypeScript in your Angular and other applications.</p><h2 id="panel">Panel</h2><ul><li>Armen Vardanyan</li><li>Subrat Mishra</li></ul><h2 id="guest">Guest</h2><ul><li>Wycliffe Maina</li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>podcast</category>
            <category>A Byte of Typescript</category>
            <category>Angular</category>
        </item>
        <item>
            <title><![CDATA[Custom Type Guards in Typescript]]></title>
            <link>https://mainawycliffe.dev/blog/custom-type-guards-in-typescript</link>
            <guid>https://mainawycliffe.dev/blog/custom-type-guards-in-typescript</guid>
            <pubDate>Wed, 15 Sep 2021 19:52:24 GMT</pubDate>
            <content:encoded><![CDATA[<p>Previously, we covered various approaches that you can take to narrowing types in Typescript. Type narrowing is the process of moving the type of a variable from a less precise to a more precise type i.e. from a union of string and number to string only. You can learn more about type narrowing <a href="https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript?ref=content.mainawycliffe.dev">here</a>. </p><p>In this article, we are going to look at how we can create our own custom type guards. Custom type guards will help you to check if a variable is of a certain type before usage, which helps in Type narrowing.</p><p>Take for instance the following function, which calculates the area of a shape i.e. Circle or Rectangle.</p><pre><code class="language-typescript">function calculateArea(shape: Rectangle | Circle) {
	// calculate area
}</code></pre><p>In order to calculate the area, we will need to determine whether the shape being passed in is a Rectangle or Circle. We can create a custom type guide that will check if the type of a <code>Rectangle</code> and calculate its area, otherwise calculates the area of a circle:</p><pre><code class="language-typescript">if(isRectangle(shape)) {
	// calculate area of a rectangle
} else {
	// calculate area of a circle
}</code></pre><h2 id="what-is-a-type-predicate">What is a Type Predicate?</h2><p>A type predicate is a function return type that tells typescript a parameter is of a specific type. A predicate takes the following format: <code>parameterName is Type</code>, where <code>parameterName</code> must be the name of a parameter in the function parameter signature. </p><p>For instance, if we wanted to build the custom type guard <code>isRectangle</code> above, our type predicate would be <code>shape is Rectangle</code>, where <code>shape</code> is the parameter name, as shown below.</p><pre><code class="language-typescript ">function isRectangle(shape: unknown): shape is Rectangle {
	// function body
}</code></pre><h2 id="custom-type-guard">Custom Type Guard</h2><p>To define a custom type guard, we create a function that returns a type predicate. The function itself just needs to return true or false. If we take the example above for <code>isRectangle</code> type guard, we would check if the <code>width</code> and the <code>height</code> are present and return <code>true</code>, otherwise, return <code>false</code>.</p><pre><code class="language-typescript">function isRectangle(shape: unknown): shape is Rectangle {
  if ("width" in shape &amp;&amp; "height" in shape) {
  	// this is a rectangle
  	return true; 
  }
  // it's not a rectangle
  return false;
}
</code></pre><p>In the above example, we are using Javascripts <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in?ref=content.mainawycliffe.dev">in operator</a> to check if the width and height properties are in the shape object.</p><h3 id="usage">Usage</h3><p>To use the custom type guard, we use it just like any other function that returns a boolean.</p><pre><code class="language-typescript">type Rectangle = {
  height: number;
  width: number;
}

type Circle = {
  radius: number;
}

const r: Rectangle = {
  height: 12,
  width: 15
}

const c: Circle = {
  radius: 10,
}

console.log(isReactangle(r)); // true
console.log(isReactangle(c)) // false</code></pre><p>By using it within a control flow, you can narrow the type of the variable, just like other methods of narrowing types.</p><pre><code class="language-typescript">function area(shape: Rectangle | Circle) {
  if(isRectangle(shape)) {
    // Rectangle
    shape.height // no error
    shape.radius // error
  } else {
    // Circle
    shape.radius // no error
    shape.height // error
  }
}
</code></pre><h2 id="conclusion">Conclusion</h2><p>In this brief article, we learned what a Type predicate is and how to build custom type guards. We learned that a type guard is a special function that returns a type predicate so that typescript is able to determine the type of a variable.</p><p>We will continue covering similar topics in Typescript in this series - <a href="https://mainawycliffe.dev/blog/tags/a-byte-of-typescript?ref=content.mainawycliffe.dev">A Byte of Typescript</a>. A Byte of Typescript is a new series that I will be publishing on a regular basis to help you demystify Typescript.</p><p>If you are looking to learn more about Typescript, here are the previous articles I have published. Thank you 😄.</p><ul><li><a href="https://mainawycliffe.dev/blog/typescript-use-unknown-instead-of-any?ref=content.mainawycliffe.dev">Typescript: why you should use unknown instead of any</a></li><li><a href="https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript?ref=content.mainawycliffe.dev">Type Narrowing in TypeScript</a></li><li><a href="https://mainawycliffe.dev/blog/types-and-mocking-typescript?ref=content.mainawycliffe.dev">Types and Mocking - Typescript</a></li><li><a href="https://mainawycliffe.dev/blog/template-literal-types-in-typescript?ref=content.mainawycliffe.dev">Template Literal Types in TypeScript</a></li><li><a href="https://mainawycliffe.dev/blog/transforming-types-typescript-utility-types?ref=content.mainawycliffe.dev">Transforming Types in TypeScript with Utility Types</a></li></ul><p> </p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Typescript: why you should use unknown instead of any]]></title>
            <link>https://mainawycliffe.dev/blog/typescript-use-unknown-instead-of-any</link>
            <guid>https://mainawycliffe.dev/blog/typescript-use-unknown-instead-of-any</guid>
            <pubDate>Wed, 01 Sep 2021 18:56:46 GMT</pubDate>
            <content:encoded><![CDATA[<p>From time to time, we come across situations where the type isn't known beforehand, i.e. could be anything. Before TS v3, we would use the <code>any</code> type for such types. But this comes with a few tradeoffs, like losing any type safety provided by Typescript.</p><p>Take the following example for instance:</p><pre><code class="language-typescript ">const x: any = {
  a: "a-value",
  b: "b-value"
};</code></pre><p>You can access the properties of the object above, i.e. <code>x.a</code> and <code>x.b</code> and everything would work as expected. The problem is that if you tried to access <code>x.c</code> value, Typescript would not throw an error, since the object <code>x</code> can be anything.</p><pre><code class="language-typescript ">const c = x.c
console.log(c)</code></pre><p>As you can see, this can be a source of many bugs, since common errors which Typescript would catch during build time will be allowed through. This is because when you use <code>any</code> type, you opt out of type checking.</p><h2 id="why-unknown">Why <code>unknown</code>?</h2><p>The <code>unknown</code> type was introduced in version 3 of typescript as an accompanying type to <code>any</code>. The <code>unknown</code> type, when assigned to a variable, means that a variable type is not known. </p><p>And typescript doesn't allow you to use a variable of <code>unknown</code> type unless you either cast the variable to a known type or narrow its type. Type narrowing is the process of moving a less precise type to a more precise type. You can learn more about Type narrowing in Typescript <a href="https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript?ref=content.mainawycliffe.dev">here</a>.</p><p>Take the following example.</p><pre><code class="language-typescript">const x: unknown = 1;</code></pre><p>if we tried to square <code>x</code> above without narrowing the type, typescript will throw the following error:</p><pre><code>Object is of type 'unknown'.</code></pre><p>To fix the above error, we can use type guards to check if it's a number before squaring it.</p><pre><code class="language-typescript">if(typeof x === "number") {
  console.log(x * x);
}</code></pre><p>The same thing with the initial example, if we changed the type to <code>unknown</code> and tried to access any of the properties, typescript would throw an error.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://content.mainawycliffe.dev/content/images/2021/08/image.png" class="kg-image" alt loading="lazy" width="550" height="118"><figcaption>Typescript doesn't allow you to use an unknown type before casting it.</figcaption></figure><p>You would need to cast it, in order to typescript to allow you to use it.</p><pre><code class="language-typescript">const x: unknown = {
  a: "a-value",
  b: "b-value"
};

console.log((x as {a: string; b: string; }).b)</code></pre><p>As you can see from the above examples, the <code>unknown</code> type forces you to determine what a variable typed as <code>unknown</code> is, either through type casting or type narrowing. This in turn leads to a better program, as typescript can then type checking the resulting type, leading to a more type-safe program.</p><h2 id="conclusion">Conclusion</h2><p>In this article, we learned about the <code>unknown</code> type and why we should use it to write more type-safe typescript programs. We also learned why you should avoid using type <code>any</code> unless absolutely necessary.</p><p>If you found this article informative and would like to keep learning, visit my new series on Typescript - <a href="https://mainawycliffe.dev/blog/tags/a-byte-of-typescript?ref=content.mainawycliffe.dev">A Byte of Typescript</a>. A Byte of Typescript is a new series that I will be publishing on a regular basis to help you demystify Typescript.</p><ul><li><a href="https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript?ref=content.mainawycliffe.dev">Type Narrowing in TypeScript</a></li><li><a href="https://mainawycliffe.dev/blog/types-and-mocking-typescript?ref=content.mainawycliffe.dev">Types and Mocking - Typescript</a></li><li><a href="https://mainawycliffe.dev/blog/template-literal-types-in-typescript?ref=content.mainawycliffe.dev">Template Literal Types in TypeScript</a></li><li><a href="https://mainawycliffe.dev/blog/transforming-types-typescript-utility-types?ref=content.mainawycliffe.dev">Transforming Types in TypeScript with Utility Types</a></li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Type Narrowing in TypeScript]]></title>
            <link>https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript</link>
            <guid>https://mainawycliffe.dev/blog/type-guards-and-narrowing-in-typescript</guid>
            <pubDate>Wed, 25 Aug 2021 19:09:25 GMT</pubDate>
            <content:encoded><![CDATA[<p>In the spirit of my last few articles, where we have looked into <a href="https://mainawycliffe.dev/blog/template-literal-types-in-typescript?ref=content.mainawycliffe.dev">Template Literal Types</a> and <a href="https://mainawycliffe.dev/blog/types-and-mocking-typescript?ref=content.mainawycliffe.dev">Types and Mocking</a>, we are going to dissect another topic in typescript involving types. In this article, we are going to learn various ways you can narrow types. Type narrowing is the process of moving a type from a less precise type to a more precise type.</p><p>Let's start with a simple function:</p><pre><code class="language-typescript">function friends(input: string | number) {
	// code here
}</code></pre><p>The above function can either take a number or a string. Let's say we want to perform different actions based upon whether <code>input</code> is a number or a string. In this case, we will use Javascripts type guards to check if it's a string or number, as shown below:</p><pre><code class="language-typescript">function someFunc(input: string | number) {
  if(typeof input === "string") {
    // do something with the string
    console.log("input is a string");
  }
  
  if(typeof input === "number") {
    // do something with number
    console.log("input is a number");
  }
}</code></pre><h2 id="type-guards">Type Guards</h2><p>In the above example, we used Javascripts type guards to narrow the type of <code>input</code> to either number or string. Type guards are used to check if a variable is of a certain type, i.e. <code>number</code>, <code>string</code>, <code>object</code>, etc. When a type guard is used, Typescript expects that variable to be of that type. It will automatically type check its usage based on that information.</p><p>Here is a list of Javascripts type guards available: </p><h3 id="string">string</h3><pre><code class="language-typescript">if(typeof param === "string") {
  // do something with string value
}</code></pre><h3 id="number">number</h3><pre><code class="language-typescript">if(typeof param === "number") {
  // do something with number value
}</code></pre><h3 id="bigint">bigint</h3><pre><code class="language-typescript">if(typeof param === "bigint") {
  // do something with bigint value
}</code></pre><h3 id="boolean">boolean</h3><pre><code class="language-typescript">if(typeof param === "boolean") {
  // do something with boolean value
}</code></pre><h3 id="symbol">symbol</h3><pre><code class="language-typescript">if(typeof param === "symbol") {
  // do something with symbol value
}</code></pre><h3 id="undefined">undefined</h3><pre><code class="language-typescript">if(typeof param === "undefined") {
  // do something with undefined value
}</code></pre><h3 id="object">object</h3><pre><code class="language-typescript">if(typeof param === "object") {
  // do something with object value
}</code></pre><h3 id="function">function</h3><pre><code class="language-typescript">if(typeof param === "function") {
  // do something with the function
}</code></pre><h2 id="truthiness-narrowing">Truthiness Narrowing</h2><p>In this type of narrowing, we check whether a variable is <strong>truthy </strong>before using it. When a variable is truthy, typescript will automatically remove the possibility of that variable being <strong>falsy</strong> i.e. <code>undefined</code> or <code>null</code>, etc, within the conditional check. </p><p>Take for instance the following example, where a function <strong>someFunction</strong> below takes an <code>input</code>, whose type is either a string or undefined (i.e. optional).</p><pre><code class="language-typescript">function someFunction(x?: string) {
  if(x) {
    console.log(typeof x) // "string"
  }
}
</code></pre><p>By checking whether <code>input</code><strong> </strong>is truthy, the type of <strong>x</strong> becomes a string otherwise it's <strong>undefined</strong>.</p><h2 id="equality-narrowing">Equality Narrowing</h2><p>If two variables are equal, then the types of both variables must be the same. If one variable is of an imprecise type (i.e. <code>unknown</code>, <code>any</code> etc.) and is equal to another variable of a precise type, then typescript will use that information to narrow the type of the first variable.</p><p>Take the following function, which takes two parameters: <strong>x</strong> and <strong>y</strong>, with <strong>x</strong> being either a <strong>string</strong> or a <strong>number</strong> and <strong>y</strong> being a <strong>number</strong>. When the value of <strong>x</strong> is equal to the value of <strong>y</strong>, then the type of <strong>x</strong> is inferred to be a <strong>number</strong> and otherwise a <strong>string</strong>.</p><pre><code class="language-typescript">function someFunction(x: string | number, y: number) {
    if(x === y) {
        // narrowed to number
        console.log(typeof x) // number
    } else {
        // this is not narrowed
        console.log(typeof x) // number or string
    }
}
</code></pre><h2 id="discriminated-unions">Discriminated Unions</h2><p>In this approach, you create an object, with a literal member that can be used to discriminate between two different unions. Let's take an example of a function that calculates the square of different shapes - Rectangle and Circle. We will start by defining the type of Rectangle and Circle.</p><pre><code class="language-typescript">type Rectangle = {
    shape: "reactangle",
    width: number;
    height: number;
}

type Circle = {
    shape: "circle"
    radius: number;
}</code></pre><p>From the above types, the objects will each have the literal field of shape, which can either be a <code>circle</code> or <code>rectangle</code>. We can use the shape field within our function to calculate area, that would accept a union of <code>Rectangle</code> and <code>Circle</code>, as shown below:</p><pre><code class="language-typescript">function calculateArea(shape: Rectangle | Circle) {
    if(shape.shape === "reactangle") {
        // you can only access the properties of reactangle and not circle
        console.log("Area of reactangle: " + shape.height * shape.width);
    }

    if(shape.shape === "circle") {
        // you can only access the properties of circle and not reactangle
        console.log("Area of circle: " + 3.14 * shape.radius * shape.radius);
    }
}</code></pre><p>When the <code>shape</code> field is a rectangle, you only have access to properties available in the <code>Rectangle</code> type, that is <code>width</code>, <code>height</code> and <code>shape</code>. The same applies to when <code>shape</code> field is a circle, typescript will only allow you to access <code>radius</code> and <code>circle</code> and will throw an error otherwise.</p><figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="1000" height="500" src="https://codesandbox.io/embed/typescript-playground-export-forked-jswcw?fontsize=14&hidenavigation=1&theme=dark&view=editor" style="width:1000px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe><figcaption>Open the example in Code Sandbox to enable linting and see the error</figcaption></figure><h2 id="using-the-in-operator-for-narrowing">Using the in Operator for Narrowing</h2><p>The <code>in</code> operator is used to determine if an object has a property with a name in it. It's used in the format of <code>"property" in object</code> where <code>property</code> is the name of the property you want to check if it exists inside the <code>object</code>.</p><p>In the example above, we used discriminated unions to distinguish between a Circle and Rectangle. We can also use the <code>in</code> operator to achieve the same, but this time we will be checking if a shape contains certain properties i.e. <code>radius</code> for <code>Circle</code>, <code>width</code> and <code>height</code> for <code>Rectangle</code>, and the results would be the same.</p><figure class="kg-card kg-code-card"><pre><code class="language-typescript">type Circle = {
  radius: number;
};

type Reactangle = {
  width: number;
  height: number;
};

function calculateArea(shape: Circle | Reactangle) {
  if ("radius" in shape) {
    // now you can access radius from shape
    console.log("Area of circle: " + 3.14 * shape.radius * shape.radius);

    // any attempt to access height or width will result to an error
    shape.width; // Property 'width' does not exist on type 'Circle'.
    shape.height; // Error: Property 'height' does not exist on type 'Circle'
  }
  if ("width" in shape &amp;&amp; "height" in shape) {
    // now you can access height and width from the shape object
    console.log("Area of reactangle: " + shape.height * shape.width);

    // any attempt to access raidus would result to an error
    shape.radius; // Error: Property 'radius' does not exist on type 'Reactangle'.ts
  }
}
</code></pre><figcaption>Open the Example on <a href="https://codesandbox.io/s/type-narrowing-jswcw?file=%2FinOperatorNarrowing.ts&ref=content.mainawycliffe.dev">Code Sandbox</a></figcaption></figure><h2 id="using-assignment-narrowing">Using Assignment Narrowing</h2><p>In this type of narrowing, typescript will narrow the type of a variable once it's assigned a value. Take a variable x of union type of either <code>number</code> or <code>string</code>, if we assign it a <code>number</code>, the type becomes a <code>number</code> and if we assign it a <code>string</code>, the type changes to a string instead. </p><pre><code class="language-typescript">let x : number | string = 1;

console.log(typeof x) // "number"

x = "something"

console.log(typeof x) // "string"
</code></pre><p>Here is a detailed example at Code Sandbox:</p><figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="1000" height="500" src="https://codesandbox.io/embed/type-narrowing-jswcw?fontsize=14&hidenavigation=1&module=%2FassignmentNarrowing.ts&theme=dark&view=editor" style="width:1000px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe><figcaption>Open the example in Code Sandbox to enable linting and view the error</figcaption></figure><h2 id="using-instanceof-for-narrowing">Using instanceof for Narrowing</h2><p>Javascripts' <code>instanceof</code> operator is used to check if a value is an instance of a certain class. It's used in the format of <code>value instanceof value2</code> and returns a boolean. When you check if a value is an <code>instanceof</code> a class, Typescript will assign that type to the variable, thereby narrowing the type. </p><p>Take the following example, where a function takes in a date, which can be either a string or a Date. If it's a Date, we want to convert it to a string and if it's a string, we will return it as is. We can use instanceof to check if it's an instance of a Date and convert it to string, as shown below.</p><pre><code class="language-typescript">function dateToString(value: string | Date) {
  if(value instanceof Date) {
    // The type now is Date and you can access Date methods
    return value.toISOString();
  }
  return value;
}</code></pre><h2 id="conclusion">Conclusion</h2><p>In this article, we learned various ways we can narrow types, from type guards to discriminated unions. In our next article, we will learn how we can build our own type guards using type predicates.</p><p>If you found this article informative and would like to keep learning, visit my new series on Typescript - <a href="https://mainawycliffe.dev/blog/tags/a-byte-of-typescript?ref=content.mainawycliffe.dev">A Byte of Typescript</a>. A Byte of Typescript is a new series that I will be publishing on a regular basis to help you demystify Typescript.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[A monorepo of serverless microservices]]></title>
            <link>https://mainawycliffe.dev/blog/a-monorepo-of-serverless-microservices</link>
            <guid>https://mainawycliffe.dev/blog/a-monorepo-of-serverless-microservices</guid>
            <pubDate>Wed, 04 Aug 2021 22:24:00 GMT</pubDate>
            <content:encoded><![CDATA[<!--kg-card-begin: html--><audio data-theme="night" data-src="https://changelog.com/shipit/13/embed" src="https://chtbl.com/track/A551A9/https://cdn.changelog.com/uploads/shipit/13/ship-it-13.mp3" preload="none" class="changelog-episode" controls></audio><p><a href="https://changelog.com/shipit/13?ref=content.mainawycliffe.dev">Ship It! 13: A monorepo of serverless microservices</a> – Listen on <a href="https://changelog.com/?ref=content.mainawycliffe.dev">Changelog.com</a></p><script async src="//cdn.changelog.com/embed.js"></script><!--kg-card-end: html--><p>In this episode, Gerhard talks to his Skyhook Adventure friends: Alan Cooney, Saul Cullen &amp; Wycliffe Maina. They are the ones that introduced Gerhard to the world of serverless in the context of Amazon Web Services. Gerhard shared his experience with remote work, how to ship software with confidence and consistency, and what to look for in infrastructure as code.</p><p>At the heart of Skyhook Adventure are adventure trips, and 2020 was not a good one for this business. As you can already tell, code and infrastructure was not the biggest challenge for this team. Having said that, serverless, microservices, a monorepo and the event-based architecture played a big part in successfully navigating the challenges.</p><p>This is a story about what happens when a good team allows itself to be guided by solid experience and keeps doing the right thing, long-term. It’s fun, real, and it applies to many.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>podcast</category>
        </item>
        <item>
            <title><![CDATA[My Impressions of Docker Development Containers]]></title>
            <link>https://mainawycliffe.dev/blog/my-impressions-of-docker-development-containers</link>
            <guid>https://mainawycliffe.dev/blog/my-impressions-of-docker-development-containers</guid>
            <pubDate>Wed, 21 Jul 2021 18:15:54 GMT</pubDate>
            <content:encoded><![CDATA[<p>Docker development containers enable developers to set up development environment faster and consistently. With docker development containers, you can configure a container with all required tools and SDKs necessary for a project's development environment, which can easily and consistently be recreated with little to no <strong>hassle</strong>.</p><p>For instance, take an Angular project, this requires a few things to get started, like Typescript, NodeJS, Angular CLI, etc. This can easily be created using docker and once set up can easily be re-created on demand. As you can imagine, this can have several benefits, which we will look at later.</p><p>On its own, it still leaves much to be desired though. But, a while back the Visual Studio Code team released a pack of extensions for remote development. These extensions enabled you to work with development environment hosted remotely such as docker containers, among others and continue with development workflow as you would if they were on your local PC.</p><p>Combined with VS Code Remote - Container's extension, part of <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers&ref=content.mainawycliffe.dev">Visual Studio Remote extensions pack</a>, which enables you to use docker as a full-fledged development environment. The Remote Container extension, provides you with tools to connect to a docker container and carry on with your development workflow on the container. </p><p>On top of that, it provides tools to:</p><ul><li>Generate Docker Environment Configurations for different environment requirements like Typescript, Golang, etc. This allows you fine-grained control over your development environment with exactly the dependencies you need to enable your development workflow. </li><li>Clone a repository directly to docker containers. You can target different branches and PRs, allowing you to have a development environment per PR if need be.</li></ul><h2 id="benefits-for-development">Benefits For Development</h2><p>For one, since docker containers are isolated environments, collision between different development environment dependencies is greatly reduced if not entirely eliminated. How many times have you required to have different versions of the same dependency installed, for instance NodeJS? Docker development container would eliminate such collisions entirely, reducing the need for tools such as NVM.</p><p>Secondly, it is easier to onboard developers, as the development environment are already specified and it's a matter of building the containers. This makes it easy to onboard developers as they can set up their environment faster and go straight to understanding what actually matters to the organization. </p><p>On top of on boarding new developers, reviewing PRs is easier, as you can easily and quickly create a new development environment per PR for review purpose. VS Code remote container extension provides you with tools to enable clone repository, branches or PRs into development containers, making this a more viable approach.</p><p>Another key benefit is keeping your development environments up to date across team members becomes easier. When you come back from a vacation, with a single command, you can update your development environment making easy to continue as if you never left with little to no hinderances. </p><p>Fully compatibility with GitHub Code Spaces. GitHub code spaces is a remote development environment that uses docker development containers under the hood. While still in beta and a lot could change, as of the moment of writing, they are fully compatible. This means that you can easily take your development environment on the road without needing to configure anything after the initial configuration. GitHub code spaces will provide you with all the computing power you need while on the road.</p><h2 id="cons">Cons</h2><p>Steep learning curve. While VS Code helps to set up common development environments like NodeJS, Typescript, etc., setting a fine-grained environment will require you to understand docker and dockerfiles. This can be a barrier to people who aren't familiar to docker and adds an extra barrier to getting up to speed.</p><h2 id="conclusion">Conclusion</h2><p>In this article, we looked at Docker development containers and the benefits of using them. I am hoping that the benefits we looked at above convinced you to give docker development containers a try. </p><p>If you are looking to get started, here some resources for you:</p><ul><li><a href="https://code.visualstudio.com/docs/remote/containers?ref=content.mainawycliffe.dev">Developing inside a Container using Visual Studio Code Remote Development</a></li><li><a href="https://docs.docker.com/language/nodejs/develop/?ref=content.mainawycliffe.dev">Use containers for development | Docker Documentation</a></li><li><a href="https://docs.docker.com/develop/?ref=content.mainawycliffe.dev">Develop with Docker | Docker Documentation</a></li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Docker</category>
            <category>VS Code</category>
        </item>
        <item>
            <title><![CDATA[Template Literal Types in TypeScript]]></title>
            <link>https://mainawycliffe.dev/blog/template-literal-types-in-typescript</link>
            <guid>https://mainawycliffe.dev/blog/template-literal-types-in-typescript</guid>
            <pubDate>Wed, 23 Jun 2021 19:51:28 GMT</pubDate>
            <content:encoded><![CDATA[<p>In this article, we will take a closer look at template literal types and how you can take advantage of them in your day-to-day activities as a developer. </p><p>So, what are template literal types?</p><h2 id="literal-types">Literal Types</h2><p>In order to understand what template literal types are, we first need to have a brief look at literal types. Literal types allow us to define types that are more specific, instead of something that is generalized like string or number. </p><p>Let's say you have a switch; it can have the value of either on or off. One way of defining the types of this, is to use literal types, giving it the type of either <code>On</code> or <code>Off</code>:</p><pre><code class="language-typescript">type Switch = "On" | "Off"
</code></pre><p> In the case above, the value of any variable of type Switch can only be <code>On</code> or <code>Off</code>:</p><pre><code class="language-typescript">const x: Switch = "On"
const y: Switch = "Off"</code></pre><p>If you tried to assign any other values other than <code>On</code> or <code>Off</code>, typescript will throw an error:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/06/Template-Literal-Types-1.png" class="kg-image" alt loading="lazy" width="745" height="201" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/06/Template-Literal-Types-1.png 600w, https://content.mainawycliffe.dev/content/images/2021/06/Template-Literal-Types-1.png 745w" sizes="(min-width: 720px) 720px"></figure><h2 id="template-literal-types">Template Literal Types</h2><p>Template Literal Types build on this, allowing you to build new types using a template and can expand to many different string using <a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html?ref=content.mainawycliffe.dev#union-types">Unions</a>. This works just like <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals?ref=content.mainawycliffe.dev">template literal/strings</a>, but instead of concatenating to form strings, it concatenates to form types. </p><pre><code class="language-typescript">const variable = "string";
type tVariable = "string";

// this results to a variable
const val = `This is a concatenated ${variable}`

// while this results to type
type X = `This is a concatenated ${tVariable}`</code></pre><p>As you can see, they are similar in syntax apart from what they are defined as, the first being a variable and the second being a type. The type of the first definition will be string, while the second one will be of type <code>This is a concatenated string</code> and a variable of that type can only be assigned to that string.</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/06/image-2.png" class="kg-image" alt loading="lazy" width="441" height="191"></figure><blockquote><strong>NB:</strong> If you tried to use variable instead of a type when defining Template Literal Type, it will throw the following error: <code>'variable' refers to a value, but is being used as a type here. Did you mean 'typeof variable'?</code></blockquote><p>If we take our example above of type Switch, we may want to have a function that returns the status of the switch, i.e. <code>Switch is On</code> or <code>Switch is Off</code>, and have it strongly typed, in that it can only return only those strings. With Template Literal Types, we can define this as follows:</p><pre><code class="language-typescript">type Switch = "On" | "Off"

const x: Switch = "On"
const y: Switch = "Off"


type SwitchStatus = `Switch is ${Switch}`;</code></pre><p>And this in return gives us the types: <code>Switch is On</code> and <code>Switch is Off</code>:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/06/Template-Literal-Types-3.png" class="kg-image" alt loading="lazy" width="588" height="150"></figure><h2 id="using-to-build-types-for-grid-items-coordinates">Using To Build Types for Grid Items Coordinates</h2><p>Let's say we are working with a grid system, and wanted to perform a task on various boxes in our grid, like placing something on a specific box given its coordinates. It would be nice if we could strongly type it and ensure we don't specify values outside the grid.</p><p>For instance, if we had a grid whose length was 3 smaller boxes on either side of the box. This makes it that we have 9 smaller box fitting on our big box. We can use literal types to create a type for each of our boxes, with the type being its position in the grid. So, the first gets <code>L1-H1</code> and the last gets <code>L3-H3</code> types, as shown below. </p><pre><code class="language-typescript">type SquareBoxes = "L1-H1" | "L1-H2" | "L1-H3" | "L2-H1" | "L2-H2" | "L2-H3" | "L3-H1" | "L3-H2" | "L3-H3"; </code></pre><p>Those are a lot of types to create by hand even for a small grid of 9 boxes. But, with template literals types, we could define just the type of the length of one side and use template string literals to expand the rest of the types:</p><pre><code class="language-typescript">type length = "1" | "2" | "3";

type SmallerBoxes = `L${length}-H${length}`</code></pre><p>And this would yield the same result as before:</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/06/Template-Literal-Types-2.png" class="kg-image" alt loading="lazy" width="957" height="91" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/06/Template-Literal-Types-2.png 600w, https://content.mainawycliffe.dev/content/images/2021/06/Template-Literal-Types-2.png 957w" sizes="(min-width: 720px) 720px"></figure><p>This makes our work easier and it is more versatile, because if the smaller boxes ever increased or decreased, you only need to adjust the size of the length.</p><pre><code class="language-typescript">// 16 boxes
type length = "1" | "2" | "3" | "4";

// 25 boxes
type length = "1" | "2" | "3" | "4" | "5";

// 4 boxes
type length = "1" | "2";</code></pre><h2 id="combining-with-generics">Combining With Generics</h2><p>We can combine template literal types with generics to some amazing effect. Let's take with a Type of <code>Person</code>, which has two properties - <code>name</code> and <code>age</code>. </p><pre><code class="language-typescript">type Person = {
    name: string;
    age: number;
}</code></pre><p>We want to add two methods to be called to update the values of <code>name</code> or <code>age</code> i.e. <code>nameChanged</code> or <code>ageChanged</code>. We can create a new type, that will take type <code>Person</code> as a generic, and for each property of type <code>Person</code>, we will add new properties with <code>Changed</code> appended the original properties of type Person i.e. <code>nameChanged</code> and <code>ageChanged</code>. We will used template literal types to create a new property by appending <code>Changed</code> to the property name.</p><pre><code class="language-typescript">type WithPersonChangedEvents&lt;Type&gt; = {
    [Property in keyof Type as `${string &amp; Property}Changed`]: (newValue: Type[Property]) =&gt; void;
} &amp; Type;</code></pre><blockquote><strong>NB:</strong> The above example uses some advanced typescript technique for manipulating types on top of Template Literal Types which you can learn more <a href="https://www.typescriptlang.org/docs/handbook/2/types-from-types.html?ref=content.mainawycliffe.dev">here</a>.</blockquote><p>Now, we can use both of our Types (<strong>Person</strong> and <strong>WithPersonChangedEvent</strong>) above:</p><pre><code class="language-typescript">const person: WithPersonChangedEvents&lt;Person&gt; = {
    name: "Name",
    age: 20,
    nameChanged: (newName) =&gt; console.log(newName),
    ageChanged: (newAge) =&gt; console.log(newAge),
};

person.ageChanged(21); // Logs: 21
person.nameChanged("new Name"); // Logs: "new Name"</code></pre><p>And as you can see, our object - <code>person</code> has 4 properties, with 2 being the added methods.</p><h2 id="conclusion">Conclusion</h2><p>We have learned about Template Literal Types in Typescript and how they build on top Literal types to provide you even more flexibility when defining types. We have also looked at different use cases like in a grid system type definition for different boxes coordinates and combining them with generics to define extra properties for an object.</p><h3 id="resources">Resources</h3><ul><li>Creating Types from Types - <a href="https://www.typescriptlang.org/docs/handbook/2/types-from-types.html?ref=content.mainawycliffe.dev">Link</a>.</li><li>Template Literal Types Documentation - <a href="https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html?ref=content.mainawycliffe.dev">Link</a>.</li><li>Template literals (Template strings) - <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals?ref=content.mainawycliffe.dev">Link</a>.</li><li>Types and Mocking - Typescript - <a href="https://mainawycliffe.dev/blog/types-and-mocking-typescript?ref=content.mainawycliffe.dev">Link</a>.</li><li>Transforming Types in TypeScript with Utility Types - <a href="https://mainawycliffe.dev/blog/transforming-types-typescript-utility-types?ref=content.mainawycliffe.dev">Link</a>.</li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Building an RSS Scully Plugin - Angular]]></title>
            <link>https://mainawycliffe.dev/blog/building-scully-rss-plugin-angular</link>
            <guid>https://mainawycliffe.dev/blog/building-scully-rss-plugin-angular</guid>
            <pubDate>Wed, 16 Jun 2021 19:37:44 GMT</pubDate>
            <content:encoded><![CDATA[<p>In this article, we will learn how to extend Scully functionality through plugins. We will do this by building an RSS Plugin. This plugin will generate an RSS feed for our blog web app build using Angular and Scully.</p><p>For an RSS plugin, we will build a <strong>routeDiscoveryDone </strong>plugin, which is usually called when all routes have been discovered. This is going to use data discovered during the route discovery process to create an RSS feed. The route discovery process is done by a <strong>router</strong> plugin, which you can learn more about <a href="https://scully.io/docs/Reference/plugins/types/router/?ref=content.mainawycliffe.dev">here</a>.</p><p>Scully provides 9 types of plugins which are called during different stages of Scully build. For more information about different types of plugins, please visit the official documentation <a href="https://scully.io/docs/Reference/plugins/overview/?ref=content.mainawycliffe.dev">here</a>.</p><h2 id="prerequisites">Prerequisites</h2><ul><li>Setup Scully for Your Angular Project - <a href="https://scully.io/docs/learn/getting-started/overview/?ref=content.mainawycliffe.dev">Link</a>.</li></ul><h2 id="building-the-plugin">Building the Plugin</h2><h3 id="getting-started">Getting Started</h3><p>If you used schematics to setup your Scully for your Angular project, you should be able to spot a Scully directory at the root of the workspace. This directory contains a <code>tsconfig</code> file for Scully plugins and a plugins directory, which is where our plugin will live.</p><p>Inside the plugins directory - <code>scully/plugins</code> - we will create a new file named <code>rss.ts</code>, which is going to contain the source code for our plugin. </p><h3 id="plugin-code">Plugin Code</h3><p>To create our RSS feed, we will use the NPM package <a href="https://github.com/jpmonette/feed?ref=content.mainawycliffe.dev">Feed</a>, which make it easy to generate syndicated feed using Typescript.</p><p>Our RSS plugin will be called when Scully discovers all routes and it will receive a list of routes and route data associated with each route discovered.</p><pre><code class="language-typescript ">const createRSSFeed = async (routes: HandledRoute[]) =&gt; {
  // code here
}</code></pre><p>We will start by creating a new instance of <code>Feed</code>. </p><p>First, we need to import <code>Feed</code>.</p><pre><code class="language-typescript">import { Feed } from 'feed';</code></pre><p>Then instantiate <code>Feed</code>.</p><pre><code class="language-typescript">const feed = new Feed({
  title: 'John Doe Blog',
  language: 'en-us',
  author: {
    email: 'johndoe@example.com',
    name: 'John Doe',
  },
  description: 'about you website or blog',
  id: 'https://example.com',
  link: 'https://example.com/blog',
  favicon: 'https://example.com/favicon.png',
  copyright: "John Doe Copyright"
});</code></pre><blockquote>NB: Update the content above according to your own specification.</blockquote><p>Next, we will loop over the routes, and add an RSS Feed item for each.</p><pre><code class="language-typescript">routes.forEach((route) =&gt; {
	// add each item to an RSS Feed Article  
})</code></pre><p>Then, for each route, we want to add an RSS item, and use the route data - <code>route.data.*</code> to fill in the different properties like <code>title</code>, <code>date</code>, <code>content</code>, etc.</p><pre><code class="language-typescript ">routes.forEach((route) =&gt; {
  feed.addItem({
    title: route.data.title,
    date: new Date(route.data.publishedAt),
    link: route.data.link,
    // loop through the names of the authors if list
    author: [
      {
        email: route.data.author.email,
        name: route.data.author.email,
      },
    ],
    // uses tags as categories
    category: route.data?.tags?.map((t: Tag) =&gt; ({
      name: t.name,
    })),
    content: route.data.html,
    id: route.data.id,
    image: route.data.featured_image,
    published: new Date(route.data.publishedAt),
  });
})</code></pre><blockquote><strong>NB: </strong>update the different properties of each item according to the structure of your data. For markdown content, this are the keys in the <a href="https://jekyllrb.com/docs/front-matter/?ref=content.mainawycliffe.dev">Front Matter</a>.</blockquote><p>Finally, we will save our RSS feed as an XML file inside the output directory of Scully. We can use <code>fs-extra</code> to do that, so we will start by installing the package.</p><p><strong>Yarn:</strong></p><pre><code class="language-sh">yarn add --dev fs-extra</code></pre><p><strong>NPM:</strong></p><pre><code class="language-sh">npm i -D fs-extra</code></pre><p>Then, we will import <code>outputFileSync</code> from <code>fs-extra</code>.</p><pre><code class="language-typescript">import { outputFileSync } from 'fs-extra';
</code></pre><p>Finally, we will save the RSS feed.</p><pre><code class="language-typescript">// the output directory of your scully builds artefacts
const outDir = './dist/static';

outputFileSync(join(outDir, 'blog', `feed.xml`), feed.rss2());</code></pre><p>On top of that, we can also generate both JSON and Atom files:</p><pre><code class="language-typescript">outputFileSync(join(outDir, 'blog', `feed.atom`), feed.atom1());
outputFileSync(join(outDir, 'blog', `feed.json`), feed.json1());</code></pre><p>That's it for the plugin, here is what the plugin function looks like.</p><pre><code class="language-typescript">const createRSSFeed = async (routes: HandledRoute[]) =&gt; {
  log(`Generating RSS Feed for Blog`);

   const feed = new Feed({
    title: 'John Doe Blog',
    language: 'en-us',
    author: {
      email: 'johndoe@example.com',
      name: 'John Doe',
    },
    description: 'about you website or blog',
    id: 'https://example.com',
    link: 'https://example.com/blog',
    favicon: 'https://example.com/favicon.png',
    copyright: "John Doe Copyright"
  });

  routes.forEach((route) =&gt; {
    feed.addItem({
      title: route.data.title,
      date: new Date(route.data.publishedAt),
      link: route.data.link,
      // loop through the names of the authors if list
      author: [
        {
          email: route.data.author.email,
          name: route.data.author.email,
        },
      ],
      // uses tags as categories
      category: route.data?.tags?.map((t: Tag) =&gt; ({
        name: t.name,
      })),
      content: route.data.html,
      id: route.data.id,
      image: route.data.featured_image,
      published: new Date(route.data.publishedAt),
    });
  })

  try {
    const outDir = './dist/static';
    outputFileSync(join(outDir, 'blog', `feed.xml`), feed.rss2());
    log(`✅ Created ${yellow(`${outDir}/blog/feed.xml`)}`);
    outputFileSync(join(outDir, 'blog', `feed.atom`), feed.atom1());
    log(`✅ Created ${yellow(`${outDir}/blog/feed.atom`)}`);
    outputFileSync(join(outDir, 'blog', `feed.json`), feed.json1());
    log(`✅ Created ${yellow(`${outDir}/blog/feed.json`)}`);
  } catch (error) {
    logError('❌ Failed to create RSS feed. Error:', error);
    throw error;
  }
};</code></pre><blockquote>NB: <code>log</code> and <code>logError</code> are helper functions from Scully, imported from <code>@scullyio/scully</code>.</blockquote><h3 id="registering-the-plugin">Registering the Plugin</h3><p>Next, we will give our plugin a name. First, we will declare and export a variable for the name of the plugin. </p><pre><code class="language-typescript">export const BlogRSSFeed = Symbol('BlogRSSFeed');
</code></pre><blockquote>This variable can be imported in to the Scully config file to use the plugin.</blockquote><p>Then, we will register our Scully plugin as a <code>routeDiscoveryDone</code> plugin.</p><pre><code class="language-typescript ">registerPlugin('routeDiscoveryDone', BlogRSSFeed, createRSSFeed);
</code></pre><h3 id="using-the-plugin">Using the Plugin</h3><p>Finally, we can use the RSS plugin by adding to the array of <code>postRederrers</code>. This can be achieved using two approaches. The first one will be for all routes within our our application:</p><pre><code class="language-typescript ">export const config: ScullyConfig = {
  projectRoot: './src',
  projectName: 'project-name',
  outDir: './dist/website',
  defaultPostRenderers: [BlogRSSFeed], // for all routes
  routes: {
    '/blog/:slug': {
     	// ...
    },
  },
};</code></pre><p>While the second one can be specified for a specific route i.e. blog. This is useful when you only want to generate an RSS feed for a single section of your site like the blog section.</p><pre><code class="language-typescript ">export const config: ScullyConfig = {
  // ...
  routes: {
    '/blog/:slug': {
      postRenderers: [BlogRSSFeed],
      // ...
    },
  },
};</code></pre><h2 id="conclusion">Conclusion</h2><p>In this article, we learnt how to create a Scully plugin to generate RSS feeds for our Angular app. We have created a <code>routeDiscoveryDone</code> plugin that's called after routes for our application have been discovered and uses the route data to generate RSS feed for each of our route.</p><h3 id="resources">Resources</h3><ul><li>Speeding Up Angular Scully Builds in GitHub Actions - <a href="https://mainawycliffe.dev/blog/speeding-angular-scully-builds-github-actions?ref=content.mainawycliffe.dev">Link</a>.</li><li>Angular CDK - Platform Module - <a href="https://mainawycliffe.dev/blog/angular-cdk-platform-module?ref=content.mainawycliffe.dev">Link</a>.</li><li>Scully Documents - <a href="https://scully.io/docs/learn/getting-started/overview/?ref=content.mainawycliffe.dev">Link</a>.</li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Angular</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Types and Mocking - Typescript]]></title>
            <link>https://mainawycliffe.dev/blog/types-and-mocking-typescript</link>
            <guid>https://mainawycliffe.dev/blog/types-and-mocking-typescript</guid>
            <pubDate>Mon, 07 Jun 2021 21:38:18 GMT</pubDate>
            <content:encoded><![CDATA[<p>In this article, we are going to learn how to create functions which are easy to test and mock using TypeScript utility types.</p><p>Let's take the following function, how do you mock it's inputs i.e. <code>person</code>:</p><pre><code class="language-typescript">interface Person {
    name: {
        firstName: string;
        lastName: string;
    }
    id: string;
    age: number;
    height: number;
    weight: number;
}

function getPersonsFullName(person: Person) {
    return `${person.name.firstName} ${person.name.lastName}`;
}
</code></pre><p>One common way, is to create an object of type <code>Person</code> with only the fields being used by function and then cast the object as any, as shown below:</p><pre><code class="language-typescript ">const person = {
    name: {
        firstName: "Wycliffe",
        lastName: "Maina"
    }
}

console.log(getPersonsFullName(person as any));</code></pre><p>This works, but you are losing the benefits of typescript typing system by casting as any, since the compiler won't type check the object <code>person</code> being passed to the function. </p><p>A good reason as to why this is not a good idea, is that if the function changes and starts using other properties or the shape of the input object changes, TypeScript will not help you. I am guilty of casting as <code>any</code>, especially when writing mocks for tests.</p><p>But, is there a better way? Yes, we can improve the function above, so that it is easier to mock the input without resulting to the above technique. One approach, which I really recommend, is to create a new type which only has the fields the function needs to run successfully, in this case the <code>name</code> property. This can easily be achieved in Typescript using Utility Types, which you can learn more about <a href="https://mainawycliffe.dev/blog/transforming-types-typescript-utility-types?ref=content.mainawycliffe.dev">here</a>. </p><p>We can use the <code>Pick&lt;T&gt;</code> utility type, to create a new type from Person, with only the name field i.e. picking the <code>name</code> field from the <code>Person</code> type. </p><pre><code class="language-typescript ">function getPersonsFullName(person: Pick&lt;Person, "name"&gt;) {
    return `${person.name.firstName} ${person.name.lastName}`;
}
</code></pre><p>This way, our mock example still works, but without resulting to casting as any:</p><pre><code class="language-typescript ">const person = {
    name: {
        firstName: "Wycliffe",
        lastName: "Maina"
    }
}

console.log(getPersonsFullName(person));</code></pre><p>The advantage of this is that you can still pass a person object with more properties as long as name property is present, as shown below:</p><pre><code class="language-typescript">const person = {
    name: {
        firstName: "Wycliffe",
        lastName: "Maina"
    },
    id: 21
}

// this still works
console.log(getPersonsFullName(person));</code></pre><p>Utility types such as <code>Omit</code>, <code>Pick</code>, <code>Partial</code>, <code>Required</code>, etc. can help you create new types easily that define the shape of an input object for a function. This makes it possible to define with precision what a function input type is, with just a little extra work on your part. You can learn more about TypeScript utility types in my previous article <a href="https://mainawycliffe.dev/blog/transforming-types-typescript-utility-types/?ref=content.mainawycliffe.dev">here</a>.</p><p>This makes your functions and methods more friendly since they are taking in only what they need, making it easy to mock as seen above. Another advantage is that your functions are more re-usable as they don't place an unnecessary burden on the consumer of the function by requiring larger input than they are using.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Transforming Types in TypeScript with Utility Types]]></title>
            <link>https://mainawycliffe.dev/blog/transforming-types-typescript-utility-types</link>
            <guid>https://mainawycliffe.dev/blog/transforming-types-typescript-utility-types</guid>
            <pubDate>Wed, 05 May 2021 10:19:23 GMT</pubDate>
            <content:encoded><![CDATA[<p>Every once in a while, you end up in a situation where you need some variation of a type. For instance, you might want to omit some keys, retain some keys only, or even mark all keys as undefined or required on a type, among other use cases.</p><p>Typescript offers Utility Types, which are intended to solve this particular problem. In this article, we are going to have a look at these built-in utility types and a third-party library (with examples) that offers more utilities you might find helpful in achieving the above goal.</p><h2 id="built-in-utility-types">Built-in Utility Types</h2><p>This section focuses on TypeScript built-in utility types, they are numerous and I won't be able to cover all of them, I will just look at a few key ones, with examples, in my own opinions.</p><h3 id="partial">Partial</h3><p>This utility type constructs a new type from an existing one, with the keys at the top level being marked as optional <code>(?)</code>.</p><pre><code class="language-typescript ">interface Type {
    field: string;
}

type Type2 = Partial&lt;Type&gt;;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/partial_type.png" class="kg-image" alt loading="lazy" width="418" height="118"></figure><blockquote><strong>NB:</strong> This only runs one level, meaning keys below one level will not be affected. If you want to mark all keys as optional, regardless the level they are in, check out PartialDeep below. </blockquote><h3 id="required">Required</h3><p>This utility type does the opposite of the above, constructing a new type with all keys from the old type that are optional being marked as required.</p><pre><code class="language-typescript ">interface Type {
    field?: string;
    optional?: string;
}

type Type2 = Required&lt;Type&gt;;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/required_utility_type.png" class="kg-image" alt loading="lazy" width="317" height="129"></figure><h3 id="omit">Omit</h3><p>This utility type constructs a new type from an existing type while omitting specified keys from the new type.</p><pre><code class="language-typescript">interface Type {
    field1?: string;
    field2: string;
    field3: string;
}

type Type2 = Omit&lt;Type, "field3" | "field1"&gt;;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/omit_utility_type.png" class="kg-image" alt loading="lazy"></figure><h3 id="pick">Pick</h3><p>This utility type constructs a new type by picking keys specified from the old type. It does the opposite of Omit, as described above.</p><pre><code class="language-typescript">interface Type {
    field1?: string;
    field2: string;
    field3?: string;
    field4: string;
    field5?: string;
}

type Type2 = Pick&lt;Type, "field2" | "field3"&gt;;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/pick_utility_type.png" class="kg-image" alt loading="lazy"></figure><h3 id="readonly">Readonly</h3><p>This utility type constructs a new type from an existing one and marks all keys as read-only i.e. they cannot be re-assigned. This is useful for types of a frozen object - i.e. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze?ref=content.mainawycliffe.dev"><code>Object.freeze()</code></a>.</p><pre><code class="language-typescript ">interface Type {
    field1?: string;
    field2: string;
    field3: string;
}

type Type2 = Readonly&lt;Type&gt;;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/readonly_utility_types.png" class="kg-image" alt loading="lazy"></figure><h3 id="record">Record</h3><p>This utility type constructs a new type with union members as keys and the type as the type of the keys.</p><pre><code class="language-typescript ">interface Name {
    firstName: string;
    lastName: string;
}

type Names = "user1" | "user2";

type Type2 = Record&lt;Names, Name&gt;;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/record_utility_type.png" class="kg-image" alt="Record Utility Type" loading="lazy" width="387" height="175"></figure><p></p><p>Above are a few built-in utility types that I find very useful, you can find out more about built-in utility types in the official documentation <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html?ref=content.mainawycliffe.dev">here</a>.</p><h2 id="extending-built-in-utility-types">Extending Built-in Utility Types</h2><p>While the above built-in utility types are amazing, they don't cover all use cases, and this is where libraries that provide more utilities fill in the gap. A good example of such a library is <a href="https://github.com/sindresorhus/type-fest?ref=content.mainawycliffe.dev">type-fest</a>, which provides even more utilities. </p><p>While I won't look in to all utilities provided by type-fest, I will highlight a few that are quite help and build on the built-in types utilities.</p><h3 id="except">Except</h3><p>This is a variation of the Omit utility type described above, but stricter. It constructs a new type by omitting specified keys from a Type, but unlike Omit, the keys being emitted must strictly exist in the Type.</p><pre><code class="language-typescript">import { Except } from "type-fest"

interface X {
  a: string;
  b: string;
  c: string;
}

// Omit Example
type Y = Omit&lt;X, "d"&gt;

// Except Example
type Z = Except&lt;X, "d" &gt;</code></pre><p>As you can see in the image below, Except throws an error if you provide a Key that doesn't exist.</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/typefest-except-example.png" class="kg-image" alt loading="lazy" width="795" height="388" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/05/typefest-except-example.png 600w, https://content.mainawycliffe.dev/content/images/2021/05/typefest-except-example.png 795w" sizes="(min-width: 720px) 720px"></figure><h3 id="merge">Merge</h3><p>Constructs a new type by merging two Types, with keys of the second type overriding the keys of the first type.</p><pre><code class="language-typescript ">import { Merge } from "type-fest"

interface X {
  a: string;
  b: string;
  c: string;
}

interface Y {
  c: number;
  d: number;
  e: number;
}

type Z = Merge&lt;X, Y&gt;

const x : Z = {
  a: "is string",
  b: "is string",
  c: 1,
  d: 2,
  e: 3,
}</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/typefest-merge-type.png" class="kg-image" alt loading="lazy" width="789" height="595" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/05/typefest-merge-type.png 600w, https://content.mainawycliffe.dev/content/images/2021/05/typefest-merge-type.png 789w" sizes="(min-width: 720px) 720px"></figure><h3 id="partialdeep">PartialDeep</h3><p>This utility type constructs a new type where all keys in all levels are optional. This is quite similar to the <code>Partial</code> built-in utility type, with one significant difference, it runs deeply to all levels, while the former does it at the first level.</p><pre><code class="language-typescript">import { PartialDeep } from "type-fest";

interface X {
  a: string;
  b: string;
  c: string;
}

interface Y {
  c: number;
  d: number;
  e: number;
  f: X;
}

type Z = PartialDeep&lt;Y&gt;;

const x: Z = {};
</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/typefest-partial_deep.png" class="kg-image" alt loading="lazy" width="802" height="473" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/05/typefest-partial_deep.png 600w, https://content.mainawycliffe.dev/content/images/2021/05/typefest-partial_deep.png 802w" sizes="(min-width: 720px) 720px"></figure><h3 id="readonlydeep">ReadonlyDeep</h3><p>This utility type constructs a new type with all keys on all levels marked as required. This is also similar to the built-in <code>Readonly</code> utility type, but unlike the built-in utility type, this one goes down to all keys in all levels, making them immutable.</p><figure class="kg-card kg-embed-card"><iframe width="1000" height="500" src="https://codesandbox.io/embed/keen-grass-75wy9?fontsize=14&theme=dark&view=editor" style="width:1000px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe></figure><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/typefest-readonlydeep.png" class="kg-image" alt loading="lazy" width="743" height="354" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/05/typefest-readonlydeep.png 600w, https://content.mainawycliffe.dev/content/images/2021/05/typefest-readonlydeep.png 743w" sizes="(min-width: 720px) 720px"></figure><h3 id="mutable">Mutable</h3><p>This utility type constructs a type that strips out <code>readonly</code> from a keys in a type, essentially the opposite of what the built-in utility type <code>Readonly</code> does.</p><pre><code class="language-typescript ">import { Mutable } from "type-fest";

interface X {
  readonly a: string;
  readonly d: string;
}

type Y = Mutable&lt;X&gt;;</code></pre><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/05/typefest-mutable.png" class="kg-image" alt loading="lazy" width="791" height="309" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2021/05/typefest-mutable.png 600w, https://content.mainawycliffe.dev/content/images/2021/05/typefest-mutable.png 791w" sizes="(min-width: 720px) 720px"></figure><h2 id="conclusion">Conclusion</h2><p>In this article, I looked into typescript utility types and how they can help you automatically create types from existing ones without resulting to duplicating eliminating the need to keep related types in sync. </p><p>I highlighted a few built-in utility types that I find particularly useful on my day to day job as a developer. On top of that, we looked into type-fest, a library with a lot of utility types that extends the built-in types, and highlighted just a few.</p><h3 id="resources">Resources</h3><ul><li><a href="https://www.typescriptlang.org/docs/handbook/utility-types.html?ref=content.mainawycliffe.dev">Utility Types - Typescript Docs</a></li><li><a href="https://github.com/sindresorhus/type-fest?ref=content.mainawycliffe.dev">type-fest</a><br></li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>A Byte of Typescript</category>
            <category>Typescript</category>
        </item>
        <item>
            <title><![CDATA[Speeding Up Angular Scully Builds in GitHub Actions]]></title>
            <link>https://mainawycliffe.dev/blog/speeding-angular-scully-builds-github-actions</link>
            <guid>https://mainawycliffe.dev/blog/speeding-angular-scully-builds-github-actions</guid>
            <pubDate>Mon, 19 Apr 2021 06:36:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>In this article, we are going to learn how you can speed your Scully builds by re-using Angular build artifacts in GitHub Actions. In order to statically build your Angular website with Scully, first you have to do the Angular build and then use the build artifacts to generate a statically generated site using Scully.</p><p>It is common for most websites, that content can change without the source code of your website changing. Therefore, it can be wasteful to run an Angular build every time your website content changes.</p><p>Normally, Angular builds time are decent. But due to a number of factors, Angular builds could slow down, like in my case, running purge CSS against <a href="https://tailwindcss.com/?ref=content.mainawycliffe.dev">Tailwindcss</a> extends the build time to over 7 minutes. Add everything else together, and my GitHub Actions would take over 12 minutes.</p><h2 id="using-github-releases">Using GitHub Releases</h2><p>First, we are going to need a place to store our Angular build artifacts. GitHub <a href="https://docs.github.com/en/github/administering-a-repository/about-releases?ref=content.mainawycliffe.dev">releases</a> are a nice way, as it allows you to have a long-term storage of your artifacts that you can use anytime you want. This combined with <code>npm version</code> means ones you have your features ready; you can cut a release that will be used by subsequent builds as you continue to work on other features and/or improvements.</p><p>So, we are going to build our workflow to have two jobs, the first job will take care of building our Angular app, and creating a release and uploading our build artifacts to the release. While the second job will take care of Scully builds using the latest artifacts stored in GitHub releases and publishing our website to our hosting platform. </p><p>Whenever a new tag is added to the repository, we will create a release with the version no. of the tag and upload our angular builds to that release.</p><h2 id="building-our-angular-app">Building our Angular App</h2><h3 id="listening-to-tags">Listening to Tags</h3><p>First, we will need to trigger our GitHub workflow every time a new tag is created. We will be using tags to create release version. This will allow us to use <code>npm version</code> to create new build artifacts for us to use during the publishing process.</p><pre><code class="language-yaml">on:
  push:
    tags:
      - "*"</code></pre><blockquote><strong>NB: </strong>In the publish our blog section, we will modify this section to listen to <code>repository_dispatch</code>, which we will use with webhooks to trigger the workflow when events outside our repository like blog post published occur, you can learn more <a href="https://mainawycliffe.dev/blog/github-actions-trigger-via-webhooks?ref=content.mainawycliffe.dev">here</a>.</blockquote><p>We will limit this job to only run when a new tag is created using <code>startsWith(github.ref, 'refs/tags/')</code>. This will allow us to utilize the same workflow file for building and publishing, with them being two separate jobs. </p><pre><code class="language-yaml">jobs:
  build:
    if: startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest</code></pre><h3 id="installing-npm-packages">Installing NPM Packages</h3><p>Next, we will need to install NPM packages before we can build our angular app. In this case, we are using <code>yarn</code> but feel free to use your favorite package manager. We will start by checking out <code>(git checkout)</code> our repository. After that, we will then setup NodeJS and finally run yarn install to install our NPM packages.</p><pre><code class="language-yaml">steps:
  - uses: actions/checkout@v1
  - name: Setup Node
    uses: actions/setup-node@v1
    with:
      node-version: 12.x
  - name: yarn install
    run: yarn install</code></pre><h3 id="building-angular-project">Building Angular Project</h3><p>And then, we can add a step to run <code>yarn build:prod</code> to build our Angular app in production.</p><pre><code class="language-yaml">- name: yarn build
  run:  yarn build:prod</code></pre><h3 id="creating-a-release-and-uploading-artifacts">Creating a Release and Uploading Artifacts</h3><p>Now that we have built our project, we are going to do two things next. We will zip the build artefacts and then create a release and upload our zipped artifact to the releases. We will use <a href="https://github.com/marketplace/actions/easy-zip-files?ref=content.mainawycliffe.dev">papeloto/action-zip</a> action to zip the files:</p><pre><code class="language-yaml">- uses: papeloto/action-zip@v1
  with:
    files: "./dist/webapp/"
    dest: webapp.zip</code></pre><blockquote>Replace <code>webapp</code> with the output directory of your angular project build.</blockquote><p>And then, we are going to create a GitHub release and upload the above zipped artifact to the GitHub release. We will be using <a href="https://github.com/marketplace/actions/create-release?ref=content.mainawycliffe.dev">ncipollo/release-action action</a>, to accomplish this as shown below.</p><pre><code class="language-yaml">- name: Push Build to Releases
  uses: ncipollo/release-action@v1
  with:
    artifacts: "webapp.zip"
    token: ${{ secrets.GITHUB_TOKEN }}</code></pre><p>Here is what our workflow looks so far:</p><pre><code class="language-yaml">name: Release a new Version

on:
  push:
    tags:
      - "*"

jobs:
  build:
    if: startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      
      - name: Setup Node
        uses: actions/setup-node@v1
        with:
          node-version: 12.x
          
      - name: yarn install
        run: yarn install
        
      - name: yarn build
        run:  yarn build:prod
        
      - uses: papeloto/action-zip@v1
        with:
          files: "./dist/webapp/"
          dest: webapp.zip
          
      - name: Push Build to Releases
        uses: ncipollo/release-action@v1
        with:
          artifacts: "webapp.zip"
          token: ${{ secrets.GITHUB_TOKEN }}</code></pre><h2 id="building-scully-and-publishing-blog">Building Scully and Publishing Blog</h2><p>Next, we are going to add a second job - <code>publishing</code> - that will download our Angular build artifacts from our repos latest release, run Scully build and upload the artifacts to our hosting platform.</p><p>First, we will need to listen to the on <code>repository_dispatch</code> as this is how we will trigger our website rebuild when the content on our CMS changes, as explained <a href="https://mainawycliffe.dev/blog/github-actions-trigger-via-webhooks?ref=content.mainawycliffe.dev">here</a>. Feel free to use any other GitHub action triggers suitable for your content management system i.e. on push to master on the blog directory if you are using markdown.</p><pre><code class="language-yaml">on:
  push:
    tags:
      - "*"
      
  repository_dispatch:
    types:
      - publish_blog</code></pre><p>Next, we are going to create a publish job, which will run after the build job but if the build job doesn't run, it will run anyway. We will use the <code>if: always()</code> condition to run the job even if the build doesn't. This will run the publish job if a new blog post is published, which will skip the build job, but also when a new release is made, in which case you want the website to be published with changes that were released.</p><blockquote>The one downside of this approach is that the publish job will run even if the build job fails.</blockquote><pre><code class="language-yaml">publish:
  runs-on: ubuntu-latest
  needs: [build]
  if: always()</code></pre><p>Next, we will need to setup Node and run <code>yarn install</code> to install NPM packages as Scully needs both to run.</p><pre><code class="language-yaml">steps:
  - uses: actions/checkout@v1
  - name: Setup Node
    uses: actions/setup-node@v1
    with:
      node-version: 12.x
  - name: yarn install
    run: yarn install</code></pre><p>After that, we are going to download our build artifact that we uploaded to GitHub release - <code>webapp.zip</code> - and unzip the content to the <code>dist/webapp</code> directory. To download the artifact from GitHub release, we will be using the <a href="https://github.com/marketplace/actions/fetch-github-release-asset?ref=content.mainawycliffe.dev">dsaltares/fetch-gh-release-asset</a> action.</p><pre><code class="language-yaml">- uses: dsaltares/fetch-gh-release-asset@master
  with:
    repo: "USERNAME/REPOSITORY"
    version: "latest"
    file: "webapp.zip"
    target: "webapp.zip"
    token: ${{ secrets.GITHUB_PAT }}</code></pre><blockquote>NB: For private repository, you will need a GitHub Personal Access Token <code>(PAT)</code> with at least the <code>org:hook</code> scope. Learn more <a href="https://github.com/marketplace/actions/fetch-github-release-asset?ref=content.mainawycliffe.dev#token">here</a>.</blockquote><p>Next, we will create a directory to put the angular webapp build artifacts in and then unzip <code>webapp.zip</code> which we downloaded from GitHub releases.</p><pre><code class="language-yaml">- name: create dist directory
  run: mkdir -p dist/webapp

- name: Decompress
  uses: TonyBogdanov/zip@1.0
  with:
      args: unzip -qq ./webapp.zip -d ./dist/webapp</code></pre><p>And finally, run <code>yarn scully</code> for statically site generation of our Angular app:</p><pre><code class="language-yaml">- name: Run scully
  run: yarn scully</code></pre><p>Now we can deploy the Scully build artifact to your website. In this case we will use firebase hosting, which you can do as shown below.</p><pre><code class="language-yaml">- name: deploy firebase webapp
  uses: w9jds/firebase-action@master
  with:
    args: deploy --only hosting
  env:
    FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}</code></pre><p>And now our final GitHub Action Workflow looks like this:</p><pre><code class="language-yaml">name: Publish Blog

on:
  push:
    tags:
      - "*"
 
  repository_dispatch:
    types:
      - publish_blog
      - build_site

jobs:
  build:
    if: startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v1

      - name: Setup Node
        uses: actions/setup-node@v1
        with:
          node-version: 12.x

      - name: yarn install
        run: yarn install
        
      - name: yarn build
        run:  yarn build:prod

      - uses: papeloto/action-zip@v1
        with:
          files: "./dist/webapp/"
          dest: webapp.zip
          
      - name: Push Build to Releases
        uses: ncipollo/release-action@v1
        with:
          artifacts: "webapp.zip"
          token: ${{ secrets.GITHUB_TOKEN }}


  publish:
    runs-on: ubuntu-latest
    needs: [build]
    if: always()

    steps:
      - uses: actions/checkout@v1

      - name: Setup Node
        uses: actions/setup-node@v1
        with:
          node-version: 12.x

      - name: yarn install
        run: yarn install
        
      - uses: dsaltares/fetch-gh-release-asset@master
        with:
          repo: "[USERNAME]/[REPO]"
          version: "latest"
          file: "webapp.zip"
          target: "webapp.zip"
          token: ${{ secrets.GITHUB_PAT }}

      - name: create dist directory
        run: mkdir -p dist/webapp

      - name: Decompress
        uses: TonyBogdanov/zip@1.0
        with:
            args: unzip -qq ./webapp.zip -d ./dist/webapp
            
      - name: Run scully
        run: yarn scully

      - name: deploy firebase webapp
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only hosting
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}</code></pre><h2 id="conclusion">Conclusion</h2><p>In this article, we have looked at how we can optimize our Scully build time by splitting Angular builds and Scully builds, where we store our Angular builds and re-use the artifacts in future Scully builds. </p><p>This may not be necessary for your application if you are not using tools like purge CSS to remove unused CSS, since Angular builds are usually fast for small to medium size applications. </p><p>There are few things I skipped like caching NPM dependencies, which can shave off a few more seconds from your build time and I highly recommend you implement following instructions <a href="https://github.com/marketplace/actions/cache?ref=content.mainawycliffe.dev">here</a>.</p><h3 id="links">Links</h3><ul><li>Use Webhooks to Trigger GitHub Actions - <a href="https://mainawycliffe.dev/blog/github-actions-trigger-via-webhooks?ref=content.mainawycliffe.dev">Link</a>.</li><li>Getting Started with Scully - <a href="https://scully.io/docs/learn/getting-started/overview/?ref=content.mainawycliffe.dev">Link</a>.</li><li>Getting Started with GitHub Actions - <a href="https://docs.github.com/en/actions/quickstart?ref=content.mainawycliffe.dev">Link</a>.</li><li>About GitHub Releases - <a href="https://docs.github.com/en/github/administering-a-repository/about-releases?ref=content.mainawycliffe.dev">Link</a>.</li><li>Angular CDK - Platform Module - <a href="https://mainawycliffe.dev/blog/angular-cdk-platform-module?ref=content.mainawycliffe.dev">Link</a>.</li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Angular</category>
            <category>GitHub</category>
        </item>
        <item>
            <title><![CDATA[GitHub Actions Trigger Via Webhooks]]></title>
            <link>https://mainawycliffe.dev/blog/github-actions-trigger-via-webhooks</link>
            <guid>https://mainawycliffe.dev/blog/github-actions-trigger-via-webhooks</guid>
            <pubDate>Mon, 29 Mar 2021 10:44:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>In this article, we are going to look at how we can build a webhook to trigger a GitHub action workflow manually. This can be especially useful when you want to run a workflow where the triggers are external to the repository. </p><p>For instance, in a blogging platform, you might want to run a workflow to rebuild your statically generated website when the content is updated in a headless CMS. Most headless CMSs will request webhooks which they will send requests to when various events take place. For instance, when a new article is published or an old one is updated, you might want to just trigger a rebuild of your website.</p><h2 id="prerequisite">Prerequisite</h2><ul><li>GitHub Personal Access Token (PAT) - follow instructions <a href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token?ref=content.mainawycliffe.dev">here</a></li></ul><blockquote>NB: Please ensure you have selected the <code>workflow</code> on the scope of the GitHub Personal Access Token (<code>PAT)</code>.</blockquote><h2 id="basics-first">Basics First</h2><p>GitHub actions provides a <code>repository_dispatch</code> event to allow us to manually trigger a GitHub action workflow. To use this, we are going to configure our GitHub action workflow to run on <code>repository_dispatch</code>.</p><p>And then, we will specify the types of event upon which they will be triggered by. These event types are user defined and can be anything you wish them to be. </p><blockquote>You can learn more about <code>repository_dispatch</code> <a href="https://docs.github.com/en/actions/reference/events-that-trigger-workflows?ref=content.mainawycliffe.dev#repository_dispatch">here</a>.</blockquote><p>For instance, here is an example of a GitHub action workflow config which runs when a new blog post is published:</p><pre><code class="language-yaml">on:
  # publish blog using webhook
  repository_dispatch:
    types: [publish_blog]
 
 # steps</code></pre><p>In the case above, we will make a post request to create repository dispatch action endpoint with <code>event_type</code> of <code>publish_blog</code> and that's when the GitHub Action will get triggered and not by any other event type. The <code>event_type</code> allows you to trigger a specific GitHub action workflow.</p><h3 id="triggering-the-action">Triggering the Action</h3><p>In order to trigger the action above, we are going to send a POST request to the GitHub API endpoint for <a href="https://docs.github.com/en/rest/reference/repos?ref=content.mainawycliffe.dev#create-a-repository-dispatch-event">creating a repository dispatch event</a>. The URL follows the following format:</p><pre><code class="language-shell">https://api.github.com/repos/[USERNAME]/[REPOSITORY]/dispatches</code></pre><blockquote>Replace the <code>[USERNAME]</code> with your GitHub owner i.e. your username or organization and <code>[REPOSITORY]</code> with the name of the repository. </blockquote><p>To specify the GitHub Workflow to trigger, you need to provide <code>event_type</code> in the body. The <code>event_type</code> specified must be listed in the types array section of the <code>repository_dispatch</code>.</p><h3 id="nodejs-example">NodeJS Example</h3><p>For this example, we are going to use <a href="https://www.npmjs.com/package/got?ref=content.mainawycliffe.dev">Got</a>, a Node JS library for sending HTTP requests.</p><pre><code class="language-typescript">const url = 'https://api.github.com/repos/[USERNAME]/[REPOSITORY]/dispatches';
const githubPAT = "GITHUB_PAT"; // keep this secret
await got.post(url, {
  json: {
    event_type: 'publish_blog',
  },
  headers: {
    Authorization: "token " + githubPAT,
  },
});</code></pre><blockquote><strong>NB: </strong>Remember to substitute <code>[USERNAME]</code>, <code>[REPOSITORY]</code> and <code>GITHUB_PAT</code> with the appropriate values.</blockquote><p>The above request is going to trigger all GitHub Actions workflows which are listening to event type <code>publish_blog</code>.</p><h2 id="building-a-webhook">Building a Webhook</h2><p>Now that we have the basics out, we are going to build a Webhook which we can use to trigger our workflow. While the GitHub dispatch event does qualify to be a webhook, you might want to simplify the API being exposed. This is because some systems where you might want to use the webhook in, will not be that configurable. Some will just give you the option of entering a URL and nothing more, which makes it difficult to use the GitHub Dispatches API directly.</p><p>For the purpose of this article, we will be using <a href="https://firebase.google.com/docs/functions?ref=content.mainawycliffe.dev">Firebase Cloud Functions,</a> but any rest endpoint will do. This will expose a public <code>GET</code> endpoint that we can pass an <code>action</code> query param, which will be the type of event we want to trigger and will default to <code>publish_blog</code>. We will use <a href="https://firebase.google.com/docs/functions/config-env?ref=content.mainawycliffe.dev">Firebase Functions Config</a> to pass the GitHub PAT to the function.</p><pre><code class="language-typescript">export const triggerGithubActionWorkflow = https.onRequest(async (req, res) =&gt; {
  const dispatchAction = req.query?.action ?? 'publish_blog';
  const url =
    'https://api.github.com/repos/[USERNAME]/[REPOSITORY]/dispatches';
  const githubPAT = config().github.pat;
  await got.post(url, {
    json: {
      event_type: dispatchAction,
    },
    headers: {
      Authorization: "token " + githubPAT,
    },
  });
  res
    .send({
      message: `Dispatch Github action event emitted successfully!`,
    })
    .status(200);
});</code></pre><blockquote><strong>NB:</strong> The above Firebase function is public and might wise to add some security measures to prevent anyone from triggering your GitHub Action workflow.</blockquote><h2 id="conclusion">Conclusion</h2><p>In this article, we looked at how we can trigger GitHub Action workflows Webhooks. We used the <a href="https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads?ref=content.mainawycliffe.dev#repository_dispatch">create repository dispatch</a> GitHub API endpoint to trigger our GitHub Action Workflow and created our own REST Endpoint to act as a Webhook to integrate with third party APIs.</p><p>Like I pointed out above, our example could use more security measures to ensure that not just anyone with the REST Endpoint can trigger the GitHub Action Workflow. This will most depend on how the web hook is called, if it's part of a dashboard, you could ensure the user in question has permission to perform the action in question or it could be as simple as using passphrase.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>GitHub</category>
        </item>
        <item>
            <title><![CDATA[Angular CDK - Platform Module]]></title>
            <link>https://mainawycliffe.dev/blog/angular-cdk-platform-module</link>
            <guid>https://mainawycliffe.dev/blog/angular-cdk-platform-module</guid>
            <pubDate>Mon, 08 Mar 2021 10:33:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>In this article, we are going to take a look at the Platform Module from Angular CDK. The platform module provides you with information about the current platform where your web app is running on, such as OS, Browser, Rendering Engine, etc. It also gives you information on the features the platform supports such as scroll behavior.</p><p>This enables you to identify the platform where your app is running on and modify the behavior of your Angular app appropriately. The CDK Platform Module makes the following information available to you:</p><ul><li>Is Android - Whether the OS is Android</li><li>Is iOS - Whether the OS is iOS</li><li>Is Firefox - Whether the browser is Firefox</li><li>Is Edge - Whether the browser is Edge</li><li>Is Safari - Whether the browser is Safari</li><li>Is Blink - Whether the rendering engine is Blink</li><li>Is Webkit - Whether the rendering engine is WebKit</li><li>Is Trident - Whether the rendering engine is <a href="https://wikivisually.com/wiki/Trident_%28software%29?ref=content.mainawycliffe.dev">Trident</a></li><li>Supported Input Types - A list of input form field types supported by the browser i.e. number, password, radio, range, reset, search, submit, tel, text, time, url, etc.</li><li>Whether the browsers supports <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior?ref=content.mainawycliffe.dev">Scroll Behavior</a> - </li><li>And Whether the browser supports <a href="https://web.dev/uses-passive-event-listeners/?ref=content.mainawycliffe.dev">passive event listeners</a>.</li></ul><h2 id="installation">Installation</h2><p><strong>Using yarn:</strong></p><figure class="kg-card kg-code-card"><pre><code class="language-sh">$ yarn add @angular/cdk</code></pre><figcaption>Install @angular/cdk using yarn</figcaption></figure><p><strong>Using NPM:</strong></p><figure class="kg-card kg-code-card"><pre><code class="language-sh">$ npm install @angular/cdk</code></pre><figcaption>Install @angular/cdk using npm</figcaption></figure><h2 id="usage">Usage</h2><p>First, we will need to import the <code>PlatformModule</code> from <code>@angular/cdk/platform</code> inside our app module, as shown below:</p><pre><code class="language-typescript">// other imports
import { PlatformModule } from '@angular/cdk/platform';

@NgModule({
  declarations: [
    AppComponent,
    // ... components
  ],
  imports: [
  	// ... other modules
    PlatformModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}</code></pre><blockquote><strong>NB: </strong>If you are using feature or shared modules, you will need to import <code>PlatformModule</code> inside the module where the component using it is located.</blockquote><p>Then, we are going to inject the <code>Platform</code> service into the component where we want to use the platform information.</p><pre><code class="language-typescript">import { Platform } from '@angular/cdk/platform';
// ... other imports

@Component({
 // ... component metadata
})
export class Component  {
  constructor(private platform: Platform) {}
}
</code></pre><p>And finally, we can determine the browser platform information as shown below.</p><pre><code class="language-typescript">this.platform.ANDROID; // check if OS is android
this.platform.FIREFOX // check if Browser is Firefox
this.platform.IOS; // check if OS is iOS
this.platform.BLINK; // check if render engine is Blink
this.platform.isBrowser; // check if the app is being rendered on the browser</code></pre><p>For an up-to-date reference for the API, please refer to the official docs <a href="https://material.angular.io/cdk/platform/api?ref=content.mainawycliffe.dev">here</a>.</p><h2 id="example">Example</h2><p>We are going to implement a share functionality for our web app, where on mobile devices i.e. iOS and Android, we will use native share while on Desktop, we will use share buttons for each Social Media Platform. </p><p>We will use the <code>PlatformModule</code> to determine if the user is on <code>iOS</code> and <code>Android</code>, and then we will use the <a href="https://web.dev/web-share/?ref=content.mainawycliffe.dev">WebShare API</a>. For other devices i.e. On the desktop, we will just show a simple twitter share button instead. Here is what our component looks like:</p><pre><code class="language-typescript">import { Platform } from '@angular/cdk/platform';

// ... component metadata
export class CustomSocialShareComponent implements OnInit {
  @Input()
  shareUrl: string;

  @Input()
  title: string;

  @Input()
  text: string;

  @Input()
  hashtags: string;

  tweetShareUrl: string;

  isNativeShareSupported = false;

  constructor(private platform: Platform) {}

  ngOnInit(): void {
    // show native share if on Android and IOS and if it is supported
    this.isNativeShareSupported =
      navigator.share &amp;&amp; (this.platform.ANDROID || this.platform.IOS);
    const baseUrl = 'https://twitter.com/intent/tweet';
    this.tweetShareUrl =
      baseUrl +
      '?url=' +
      this.shareUrl +
      '&amp;via=mwycliffe_dev&amp;text=' +
      this.title +
      '&amp;hashtags=' +
      this.hashtags;
  }

  async nativeShare() {
    if (navigator.share) {
      await navigator.share({
        title: this.title,
        text: this.text.substr(0, 200),
        url: this.shareUrl,
      });
    }
  }
}
</code></pre><p>Our share component above, has a property named <code>isNativeShareSupported</code> - which is a <code>boolean</code>. We are checking whether the current browser supports native share, and the platform is iOS or Android before setting that property to true. And then we can use this property to show the correct UI, as shown below:</p><pre><code class="language-html">&lt;ng-container *ngIf="isNativeShareSupported; else showSocialShareButton"&gt;
  &lt;a (click)="nativeShare()" class="space-x-2"&gt;
    &lt;span&gt;Share this article&lt;/span&gt;
  &lt;/a&gt;
&lt;/ng-container&gt;

&lt;ng-template #showSocialShareButton&gt;
  Share on this article: &lt;a target="_blank" [href]="tweetShareUrl"&gt;Twitter&lt;/a&gt;
&lt;/ng-template&gt;
</code></pre><h2 id="conclusion">Conclusion</h2><p>In this article, we have learned how to use CDK <code>Platform Module</code> to check the platform details in which our app is running on. This is a simple and quite useful way of modifying the behavior of your Angular app based on the platform being used. This can lead to an improved UX as you can enable enhanced features to users with access to them while providing a decent fallback to users without access to the enhanced features.</p><h3 id="links">Links</h3><ul><li>CDK Documentation on Platform Module - <a href="https://material.angular.io/cdk/platform/overview?ref=content.mainawycliffe.dev">Link</a>.</li><li>Integrate with the OS sharing UI with the Web Share API - <a href="https://web.dev/web-share/?ref=content.mainawycliffe.dev">Link</a>.</li><li>Does not use passive listeners to improve scrolling performance - <a href="https://web.dev/uses-passive-event-listeners/?ref=content.mainawycliffe.dev">Link</a>.</li><li>scroll-behavior - <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior?ref=content.mainawycliffe.dev">Link</a>.</li><li>How to build a reusable Modal Overlay/Dialog Using Angular CDK - <a href="https://mainawycliffe.dev/blog/how-to-build-a-reusable-modal-overlay-dialog-using-angular-cdk?ref=content.mainawycliffe.dev">Link</a>.</li><li>Building a Custom Stepper using Angular CDK - <a href="https://indepth.dev/posts/1284/building-a-custom-stepper-using-angular-cdk?ref=content.mainawycliffe.dev">Link</a>.</li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Angular</category>
            <category>Typescript</category>
            <category>Javascript</category>
        </item>
        <item>
            <title><![CDATA[My Blog is Overengineered]]></title>
            <link>https://mainawycliffe.dev/blog/my-blog-is-over-engineered</link>
            <guid>https://mainawycliffe.dev/blog/my-blog-is-over-engineered</guid>
            <pubDate>Fri, 05 Mar 2021 21:02:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>If you are reading this, odds are you doing it on my blog - <a href="https://mainawycliffe.dev/?ref=content.mainawycliffe.dev">mainawycliffe.dev</a> - if you are not, please drop by sometime. On the surface, it looks like any other blog, but do not let that fool you, this hides away a lot of complexities for a blog. In this article, I would like to try and explain why I did this, not the first time, and why I feel it's a rewarding process for me.</p><p>Where to start? Let's start by looking at the stack that went into building this blog. </p><h2 id="the-stack">The Stack</h2><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2020/11/books-3322275_1280.jpg" class="kg-image" alt loading="lazy" width="1280" height="853" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2020/11/books-3322275_1280.jpg 600w, https://content.mainawycliffe.dev/content/images/size/w1000/2020/11/books-3322275_1280.jpg 1000w, https://content.mainawycliffe.dev/content/images/2020/11/books-3322275_1280.jpg 1280w" sizes="(min-width: 720px) 720px"></figure><p>To easily manage the content, I went with Ghost CMS, which gives me an effortless way to add, update content. My previous blog was built with <a href="https://gohugo.io/?ref=content.mainawycliffe.dev">Hugo</a>, which uses markdown and as much that was fun to work with initially, the process from writing a post all the way to publishing got exceedingly long and quite tiresome. I found myself posting less and less.</p><p>For the frontend, I decided to go with Angular and use <a href="https://scully.io/?ref=content.mainawycliffe.dev">Scully </a>to generate static version website for the blog, with <a href="https://tailwindcss.com/?ref=content.mainawycliffe.dev">Tailwind </a>for the UI. And then, the website itself is hosted on Firebase Hosting. </p><p>If you think that's it, then you clearly didn't read the title of this post. Since the website is statically generated, it means the content is fetched at build time instead of REST API request on load. This means that the website doesn't serve live updates or new articles unless it's rebuilt. To solve this problem, I am using web hooks to trigger a CI to do a rebuild and deploy the new site.</p><h2 id="why">Why?</h2><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2020/11/man-5723449_1280.jpg" class="kg-image" alt loading="lazy" width="1280" height="896" srcset="https://content.mainawycliffe.dev/content/images/size/w600/2020/11/man-5723449_1280.jpg 600w, https://content.mainawycliffe.dev/content/images/size/w1000/2020/11/man-5723449_1280.jpg 1000w, https://content.mainawycliffe.dev/content/images/2020/11/man-5723449_1280.jpg 1280w" sizes="(min-width: 720px) 720px"></figure><p>I know what is going on your mind, why go into all the trouble for a simple blog. I could have easily gotten the same or even better results on Medium or WordPress. I don't know what to say, but I enjoy building stuff. Working on this gave me an opportunity to create something and have fun at the same time. </p><p>In this case, I got interested in trying out some innovative technologies that otherwise I wouldn't get a chance at work or anywhere else to work with. So, having already an existing blog - codinglatte.com - I had a few requirements I need for a blog. </p><p>The first was, I needed an effortless way to add and manage blog posts, a UI quite like what is provided by WordPress or Medium. Ghost CMS provides an easy-to-use UI that's quite intuitive, on top of that, I can easily manage when posts go live via their schedule feature.</p><p>The second requirement I had was I needed to be able to add new features on top of the blog. I have dreams for this to evolve beyond a blog to a platform where I can interact and provide move value to my readers. For this I turned to Angular, with Scully for SSG, but this could have easily been Gatsby or Next.JS. The biggest benefit of this is having all the blogs posts and pages, progenerated to static HTML, which would allow the website to load fast and be responsive, while being cost effective. </p><p>And lastly, I needed to be able to hit publish and the blog would be re-built, and the recent changes push lived without me having to do anything extra. For this, I turned to GitHub Actions to handle the build process and Ghost CMS Webhooks to trigger the build GitHub Action. </p><p>As you can see, this gave me an opportunity to work with a few tools that I could not resist. This was my first foray into Scully, and I could not turn down the opportunity of learning how it works with a real project with potential of being used by thousands of people down.</p><h2 id="conclusion">Conclusion</h2><p>So, after going through that process, would I do it again? The simple answer for me yes. I have learned a great deal from this, and I am looking to share what I have learned here, among other stuff on this blog. It was fun, challenging and gave me an opportunity to learn and improve my skills. </p><p>Would I recommend you do the same? The answer is it depends, as I stated earlier, you can easily get a blog up and learning with medium or some other platform with excellent results, and all you have to think about are the posts themselves. </p><p>On the other hand, building out your platform presents you with a lot of flexibility and is quite rewarding when everything is working. It also gives you the opportunity to experiment and learn while working on project that will be used by quite a few people, probably thousands if your blog posts are great.</p>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Angular</category>
            <category>Firebase</category>
        </item>
        <item>
            <title><![CDATA[The State of RxJS. RxJS 7 and Beyond]]></title>
            <link>https://mainawycliffe.dev/blog/the-state-of-rxjs-rxjs-7-and-beyond</link>
            <guid>https://mainawycliffe.dev/blog/the-state-of-rxjs-rxjs-7-and-beyond</guid>
            <pubDate>Fri, 02 Oct 2020 11:50:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>In this article, we are going to discuss the state of RxJS, because the next major version – RxJS 7 – is around the corner. Let's take a closer look at new features, deprecations, and removals in both v7 and v7.1 and what to look forward to v8.</p><h2 id="improved-stability">Improved Stability</h2><p>I know, this sounds like a moot point but the RxJS team has made some changes on how they release new versions to improve stability. </p><blockquote>The RxJS team is partnering with Google, thus ensuring smooth and stable releases. Google will run pre-release versions of RxJS against their mono-repo build targets where RxJS is used widely. </blockquote><p>If anything breaks, they work together with RxJS core team to resolve the issues. The goal here is to ensure that releases are as stable as possible especially patch and minor releases which should be safe to update to.</p><h2 id="latest-typescript-version-support">Latest Typescript Version Support</h2><p>RxJS is adopting features from the latest versions of Typescript. By supporting the latest version of Typescript, we get the following benefits:</p><h3 id="type-inference">Type Inference </h3><p>Type inference around n-argument is being improved, by allowing TypeScript to do all the type inference. Before, there was a limit of around 8 argument before RxJS could not infer the type anymore, but thanks to TypeScript, this limit no longer exists. This allows RxJS to return an observable whose types closely match the arguments passed.</p><h3 id="union-types-improvements">Union Types Improvements</h3><p>Unions types are also being improved, ensuring type inference around return types are accurate without needing to explicitly type things.</p><h3 id="fixing-bad-types">Fixing Bad Types</h3><p>Another fix that will be coming along in v7 is for bad types. A good example is the <strong>toPromise</strong> operator, in v7, it will also return union type alongside the actual type, since if an observable completes without emitting anything, it returns undefined instead of throwing an error. From v7, you will need to check if the returned promise value is undefined before using it.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://admin.indepth.dev/content/images/2020/09/Screenshot-2020-09-22-171043.png" class="kg-image" alt loading="lazy"><figcaption>const <strong>num </strong>is either number or undefined</figcaption></figure><h2 id="topromise-operator-is-being-deprecated">toPromise Operator is being deprecated</h2><p>The <strong>toPromise</strong> operator is getting deprecated in RxJS 7 and will get removed completely in v8. In its place, there are two operators – <strong>lastValueFrom()</strong> and <strong>firstValueFrom()</strong>. The <strong>lastValueFrom() </strong>waits from the last value of an observable before resolving the promise. On the other hand, the <strong>firstValueFrom()</strong> resolves on the first value from an observable before unsubscribing and resolving the promise.</p><p>There are two reasons the operator is being deprecated, the first being, it is unclear to users when the promise resolve and returns undefined instead of throwing an error. The two replacement operators will throw an empty error if the observable completes without a value. The <strong>toPromise() </strong>operator would have returned undefined instead of throwing an error. The second reason is that they are more explicit on when the promise resolves i.e. whether it is the first value or the last value that will be resolved.</p><h3 id="before-">Before:</h3><pre><code class="language-typescript">const numbers$ = of(1,2,3,4,5)

// toPromise() will return the last value of the observable
numbers$.toPromise().then(n =&gt; console.log("toPromise(): " + n))</code></pre><h3 id="after-">After:</h3><pre><code class="language-typescript">const numbers$ = of(1,2,3,4,5)

// lastValueFrom() will return the last value just like to promise
lastValueFrom(numbers$).then(n =&gt; console.log("lastValueFrom(): " + n))

// firstValueFrom() will return the first value of the observable
firstValueFrom(numbers$).then(n =&gt; console.log("firstValueFrom(): " + n))
</code></pre><h2 id="new-animationframe-method">new <u>animationFrame()</u> method</h2><p><strong>animationFrame()</strong> is a new static method that fires an observable that gives the amount of time elapsed in milliseconds since the start of the observable. This provides a method to measure the progress of an observable without the need of a deeper understanding of how RxJS works under the hood. With <strong>animationFrame()</strong>, you can control the animation of an object using RxJS.</p><figure class="kg-card kg-embed-card"><iframe width="1280" height="500" src="https://codesandbox.io/embed/dry-rain-r621o?fontsize=14&hidenavigation=1&theme=dark" style="width:1280px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe></figure><h2 id="consuming-asynciterable-support">Consuming AsyncIterable Support</h2><p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator?ref=content.mainawycliffe.dev">AsyncIterable objects</a> are now fully supported in an array of RxJS operators and will be accepted anywhere where an observable or a promise is accepted. </p><p>Take for instance the following range object:</p><pre><code class="language-typescript">const range = {
  from: 1,
  to: 5,

  [Symbol.asyncIterator]() { // (1)
    return {
      current: this.from,
      last: this.to,

      async next() { // (2)
        await wait(1000);
        if (this.current &lt;= this.last) {
          return { done: false, value: this.current++ };
        } else {
          return { done: true };
        }
      }
    }; 
  }
};</code></pre><p>We can consume the above AsyncIterable object as follows:</p><pre><code class="language-typescript">from(range).subscribe(x =&gt; console.log(x))</code></pre><h3 id="example-">Example:</h3><figure class="kg-card kg-embed-card"><iframe width="1280" height="500" src="https://codesandbox.io/embed/asynciterable-support-igx49?expanddevtools=1&fontsize=14&hidenavigation=1&theme=dark" style="width:1280px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe></figure><blockquote><strong>NB: </strong>You can use the <a href="https://github.com/benlesh/rxjs-for-await?ref=content.mainawycliffe.dev"><code>rxjs-for-await</code></a> library by Ben Lesh to make your observables compatible with AsyncIterables. </blockquote><h2 id="renamed-operators">Renamed Operators</h2><p>Some of the legacy operators including deprecated ones that has the same names as their creation methods, have been renamed to reduce collision. This has been done by adding <strong>with</strong> at the end of the operators. For instance, the following operators: <strong>zip, combineLatest, merge, conca</strong>t have been renamed to <strong>zipWith, combineLatestWith, mergeWith, concatWith.</strong></p><p><strong>NB:</strong> The Deprecated operators with be removed in the next major version of RxJS.</p><h2 id="new-resetonsuccess-option-for-retry">new resetOnSuccess option for retry</h2><p>A new option called <strong>resetOnSuccess</strong> has been added to the retry options, which lets you reset the counter back to zero whenever it’s successful. In version 6, the counter is never reset and if the retries becomes successful for a while and then start failing, it would pick up where it left. This would lead the retries being exhausted faster in subsequent retries.</p><pre><code class="language-typescript">retry({
  count: 5, 
  resetOnSuccess: true 
})</code></pre><h2 id="reducing-scheduler-footprint">Reducing Scheduler Footprint</h2><p>Some operators include the Scheduler which means the Scheduler ends up within your final bundle even if you are not using it. The goal is to ensure that extra code from the Scheduler ends up in your final bundle when you explicitly need it.</p><p>To Achieve this, a new <strong>TimeStampProvider</strong> has been added that has a now method in it. This allows the third argument of the <strong>replaySubject</strong> to be defaulted to the date objected, which is native and does not need to be shipped. You can override this by passing any object that has a now method. RxJS will continue over the course of v7 to try and reduce the bundle size that is shipped with your application in non-breaking ways.</p><h2 id="scheduler-arguments-are-being-deprecated">Scheduler Arguments are being Deprecated</h2><p>Passing Scheduler arguments is being deprecated, instead you should switch to <a href="https://rxjs-dev.firebaseapp.com/api/index/function/scheduled?ref=content.mainawycliffe.dev"><strong>scheduled()</strong></a> or <a href="https://rxjs-dev.firebaseapp.com/api/operators/observeOn?ref=content.mainawycliffe.dev"><strong>observeOn()</strong></a> APIs. The Scheduler arguments are not going to disappear completely but will be retained in operators that still need them such as timer and interval.</p><h2 id="removing-subscription-and-tap-callback-options">Removing Subscription and Tap Callback Options</h2><p>Passing multiple callback methods when subscribing or tapping to an observable will be deprecated. From v7 onwards, you can use a single callback or an object with <strong>data</strong>, <strong>error</strong>, and <strong>complete</strong> fields for respective callbacks. By removing the multiple callback option, most of the logic that goes to determine which callback method you used can be removed. This will lead to a leaner and faster RxJS library.</p><h3 id="deprecated-">Deprecated:</h3><pre><code class="language-typescript">source$.pipe(tap(
  data =&gt; console.log(data),
  error =&gt; console.log(error)
)).subscribe(
  data =&gt; console.log(data),
  error =&gt; console.log(error)
)</code></pre><p>The following are acceptable:</p><h3 id="passing-a-single-callback-">Passing a single callback:</h3><pre><code class="language-typescript">source$.pipe(tap(
  data =&gt; console.log(data)
)).subscribe(
   data =&gt; console.log(data)
)</code></pre><h3 id="passing-an-object-with-multiple-callbacks-">Passing an object with multiple callbacks:</h3><pre><code class="language-typescript">source$.pipe(
  tap({ 
    next: data =&gt; console.log(data),
    error: e =&gt; console.log(e)
  })
).subscribe(
  {
    next:  data =&gt; console.log(data), 
    error:  err =&gt; console.log(err),
  }
)</code></pre><h2 id="subscription-add-returns-a-void">subscription.add() returns a void </h2><p><code>subscription.add()</code> is used to put together multiple subscriptions so that you can unsubscribe to all of them together. in v6, you could chain <code>subscription.add()</code> when adding multiple subscription. The API for chaining is being removed as it led to inconsistent un-subscription behavior. </p><figure class="kg-card kg-embed-card"><iframe width="1280" height="500" src="https://codesandbox.io/embed/subscription-add-rxjs6-quujb?autoresize=1&expanddevtools=1&fontsize=14&hidenavigation=1&module=%2Fsrc%2Findex.ts&moduleview=1&theme=dark" style="width:1280px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe></figure><p>In v7, you will have to add the subscriptions one at a time.</p><figure class="kg-card kg-embed-card"><iframe width="1280" height="500" src="https://codesandbox.io/embed/subscription-add-rxjs7-oehrx?expanddevtools=1&fontsize=14&hidenavigation=1&theme=dark" style="width:1280px; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe></figure><h2 id="beyond-v7-0">Beyond v7.0</h2><h3 id="version-7-1">Version 7.1</h3><p>In line with semantic versioning, v7.1 is a minor change with non-breaking features and improvements. We are likely to see the following in v7:</p><p>ESLint Rules and Transformations - This is expected in v7.1 and the goal is to help developer to gradually remove and replace deprecated operators that will be removed. There will also be minor improvements and a lot of preparation for version 8.</p><h2 id="version-8">Version 8</h2><p>In v8, we will see the deprecations where the team was able to add ESLint code transformations removed. This is to ensure that developers have an uncomplicated way of replacing deprecated APIs and are following the best practices. On top of that, there are some experiments being done by the RxJS team in progress and the impact is a smaller bundle size, in some cases, as small as 40% of the current size. RxJS is also going try and keep up with the latest versions of Typescript and JavaScript, whenever it is possible.</p><h2 id="additional-resources">Additional Resources</h2><ul><li><a href="https://indepth.dev/rxjs-for-await-what/?ref=content.mainawycliffe.dev">Rxjs + For + Await… What? - RxJS inDepth</a></li><li><a href="https://javascript.info/async-iterators-generators?ref=content.mainawycliffe.dev">Async iteration and generators </a></li><li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of?ref=content.mainawycliffe.dev">for await...of</a></li><li><a href="https://videos.ng-conf.org/videos/state-of-rxjs?ref=content.mainawycliffe.dev">The State of RxJS by Ben Lesh</a></li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>RxJS</category>
            <category>Typescript</category>
            <category>Javascript</category>
            <category>Angular</category>
        </item>
        <item>
            <title><![CDATA[How to build a reusable Modal Overlay/Dialog Using Angular CDK]]></title>
            <link>https://mainawycliffe.dev/blog/how-to-build-a-reusable-modal-overlay-dialog-using-angular-cdk</link>
            <guid>https://mainawycliffe.dev/blog/how-to-build-a-reusable-modal-overlay-dialog-using-angular-cdk</guid>
            <pubDate>Tue, 19 Nov 2019 21:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>Today, I am going to show you how to create a reusable modal overlay/dialog<br>using Angular CDK Overlay that can be reused inside our Angular project<br>multiple times with ease. We are going to try and match the behavior and<br>the functionality of Angular Material Dialog component, but using the UI Framework<br>of our choice.</p><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/03/cover.gif" class="kg-image" alt loading="lazy"></figure><p>This is going to be the first of a few articles, focusing on ways you can<br>utilize Angular CDK to implement common interaction patterns within your<br>application.</p><h3 id="demo-and-source-code">Demo and Source Code</h3><p>You can find the link to the demo <a href="https://mainawycliffe.github.io/ng-cdk-overlay-demo/?ref=content.mainawycliffe.dev">here</a> and the GitHub repo for this post <a href="https://github.com/mainawycliffe/ng-cdk-overlay-demo?ref=content.mainawycliffe.dev">here</a>.</p><h3 id="prerequisites">Prerequisites</h3><p>Install Angular CLI and create a new Angular project – <a href="https://codinglatte.com/posts/how-to/how-to-set-up-angular-for-beginners/?ref=content.mainawycliffe.dev">link</a>.</p><p>Setup Bulma inside your Angular Project.</p><p>Install Angular CDK – <code>npm i @angular/cdk</code> or <code>yarn add @angular/cdk</code></p><p>The article is divided into two sections:</p><ul><li>The Basics - a Quick look at how to use Angular CDK Overlay</li><li>Building a Reusable Modal Overlay - A detailed guide into building a reusable<br>modal overlay.</li></ul><h3 id="the-basics">The Basics</h3><p>Let us get the basics out of the way first. Assuming you have installed Angular CDK you will need to import <code>OverlayModule</code> into your app module.</p><pre><code class="language-typescript">import {OverlayModule} from '@angular/cdk/overlay';
</code></pre><p>And then, inject the <code>Overlay</code> service and <a href="https://angular.io/api/core/ViewContainerRef?ref=content.mainawycliffe.dev#description">ViewContainerRef</a> into your component.</p><pre><code class="language-typescript">constructor(private overlay: Overlay, private viewContainerRef: ViewContainerRef) {}
</code></pre><p>To show a modal overlay, you need either a <a href="https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/?ref=content.mainawycliffe.dev">Template</a> or an Angular <a href="https://angular.io/api/core/Component?ref=content.mainawycliffe.dev">Component</a> holding the content you would like to show. Let’s look at how you can use both below:</p><h4 id="using-a-template">Using a Template</h4><p>Inside the template of our component, let’s define a new template and add our overlay content:</p><pre><code class="language-html">&lt;ng-template #tpl&gt;
  &lt;div class="modal-card"&gt;
  &lt;header class="modal-card-head"&gt;
    …
  &lt;/header&gt;
  &lt;section class="modal-card-body"&gt;
    …
  &lt;/section&gt;
  &lt;footer class="modal-card-foot"&gt;
    …
  &lt;/footer&gt;
 &lt;/div&gt;
&lt;/ng-template&gt;
</code></pre><p>Then, add a method to show the overlay and it accepts an <code>ng-template</code> reference as the parameter.</p><pre><code class="language-typescript">openWithTemplate(tpl: TemplateRef&lt;any&gt;) {}
</code></pre><p>Then, Inside the above method, we are going to create an overlay. We will start by defining the configs of the overlay – <code>OverlayConfig</code>. In our case, we will just set the <code>hasBackdrop</code> and <code>backdropClass</code> properties. For <code>backdropClass</code> we are using <code>modal-background</code> a Bulma CSS Framework class. You can find all the Overlay Configurations you can add <a href="https://material.angular.io/cdk/overlay/api?ref=content.mainawycliffe.dev#OverlayConfig">here</a>.</p><pre><code class="language-typescript">const configs = new OverlayConfig({
 hasBackdrop: true,
 panelClass: ['modal', 'is-active'],
 backdropClass: 'modal-background'
});
</code></pre><blockquote>NB: For <code>backdrop</code> click to dismiss the modal overlay to work, you might need<br>to disable <code>pointer-events</code> for your modal, for some CSS Frameworks like<br>Bulma. This is because CDK Overlay doesn't add them to DOM in the nested order<br>of <code>modal ➡ modal-background ➡ modal-content</code>, but rather <code>modal ➡ modal-content</code>, while the backdrop is a separate div tag not nested under<br><code>modal</code>, but on a level above <code>modal</code> class div tag.</blockquote><figure class="kg-card kg-image-card"><img src="https://content.mainawycliffe.dev/content/images/2021/03/code_snippet.png" class="kg-image" alt loading="lazy"></figure><blockquote>For Bulma CSS framework case, you can override the default behavior like this:</blockquote><pre><code class="language-css">.modal {
  pointer-events: none !important;
}

.modal-content {
  pointer-events: all !important;
}
</code></pre><p>Then, let’s create an <code>OverlayRef</code>, by using the <code>create</code> method of the Overlay service and pass the configs we just created above:</p><pre><code class="language-typescript">const overlayRef = this.overlay.create(configs);
</code></pre><p>And then we can attach our template, using <a href="https://material.angular.io/cdk/portal/api?ref=content.mainawycliffe.dev#TemplatePortal">TemplatePortal</a>, passing our template and <code>ViewContainerRef</code> which we injected into our component:</p><pre><code class="language-typescript">overlayRef.attach(new TemplatePortal(tpl, this.viewContainerRef));
</code></pre><p>Now, we can trigger the method with a click of a button:</p><pre><code class="language-html">&lt;button (click)="openWithTemplate(tpl)" &gt;
 Show
&lt;/button&gt;
</code></pre><h4 id="using-a-component">Using a Component</h4><p>The difference between the two is that we will be using <code>ComponentPortal</code> instead of <code>TemplatePortal</code> to attach the component to the <code>OverlayRef</code>.</p><pre><code class="language-typescript">this.overlayRef.attach(
 new ComponentPortal(OverlayComponent, this.viewContainerRef)
);
</code></pre><p><strong>NB:</strong> The component must be added to the list of <code>entryComponents</code> in your App Module.</p><h5 id="closing-modal-overlay-on-backdrop-clip">Closing Modal Overlay on Backdrop Clip</h5><p>You can close the overlay when the backdrop is clicked by subscribing to the <code>backdropClick()</code> and then calling the <code>dispose</code> method.</p><pre><code class="language-typescript">overlayRef.backdropClick().subscribe(() =&gt; overlayRef.dispose());
</code></pre><h3 id="making-a-re-usable-modal-overlay">Making a Re-usable Modal Overlay</h3><p>Building modal overlays as shown above works very well if you are building one or two of them, however, it does not really scale very well. Wouldn’t it be nice if you could build a re-usable modal overlay that you can then use across your Angular project or projects? Wouldn’t it also be nice if we could be able to pass data to and receive data from the modal?</p><h4 id="objective">Objective</h4><p>A service to open the modal, than can be injected into any component</p><p>A way to subscribe to when the modal is closed and access the response.</p><p>Pass data to the modal</p><p>Pass data as a String, Template or Component.</p><h4 id="overlay-ref-class">Overlay Ref Class</h4><p>We are going to start by extending the <code>OverlayRef</code>. We will create a custom <code>OverlayRef</code>, creatively named <code>MyOverlayRef</code>, which is going to accept the <code>OverlayRef</code>, <code>content</code> and the data to pass to our modal overlay. The content can be of type <code>string</code>, <code>TemplateRef</code> or <code>Component</code>.</p><pre><code class="language-typescript">// R = Response Data Type, T = Data passed to Modal Type
export class MyOverlayRef&lt;R = any, T = any&gt; {
 …
 constructor(public overlay: OverlayRef, public content: string | TemplateRef&lt;any&gt; | Type&lt;any&gt;, public data: T ) {
  …
 }
 …
}
</code></pre><p>Then, Inside the <code>MyOverlayRef</code> class, we are going to add a <code>BehaviorSubject</code> property named <code>afterClosed$</code> which we can subscribe to get data once the overlay is closed.</p><pre><code class="language-typescript">afterClosed$ = new Subject&lt;OverlayCloseEvent&lt;R&gt;&gt;();
</code></pre><p>The behavior subject is going to pass back an <code>OverlayCloseEvent</code>, which contains the data from modal and how the modal was closed. Feel free to modify this to cover your needs.</p><pre><code class="language-typescript">export interface OverlayCloseEvent&lt;R&gt; {
 type: 'backdropClick' | 'close';
 data: R;
}
</code></pre><p>Next, we need to add a private method to close the overlay. The method will dispose off the overlay, pass the <code>OverlayCloseEvent</code> back to the subscriber and complete the <code>afterClosed$</code> Observable.</p><pre><code class="language-typescript">private _close(type: 'backdropClick' | 'close', data: R) {
  this.overlay.dispose();
  this.afterClosed$.next({
   type,
   data
  });

  this.afterClosed$.complete();
 }
</code></pre><p>And then, we are going to add a second public close method. It will only accept <code>data</code> as a parameter and will call the private <code>_close</code> method, to close the modal.</p><pre><code class="language-typescript">close(data?: R) {
 this._close('close', data);
}
</code></pre><p>And finally, we are going to subscribe to <code>backdropClick</code> and close the modal when clicked. We are adding this subscriber to the <code>MyOverlayRef</code> constructor.</p><pre><code class="language-typescript">overlay.backdropClick().subscribe(() =&gt; this._close('backdropClick', null));
</code></pre><h4 id="overlay-component">Overlay Component</h4><p>Next, we are going to add a special component that we will use to show our modal content. If it is a simple string, we will bind it to a div, while we can use either <code>ngTemplateOutlet</code> and <code>ngComponentOutlet</code> to load the <code>template</code> and <code>component</code> respectively.</p><h5 id="component-class">Component Class</h5><p>We are going to start by injecting an instance of our <code>MyOverlayRef</code> into the component.</p><pre><code class="language-typescript">constructor(private ref: MyOverlayRef) {}
</code></pre><p>And then, let’s define 3 more properties inside our component class:</p><pre><code class="language-typescript">contentType: 'template' | 'string' | 'component' = 'component';
content: string | TemplateRef&lt;any&gt; | Type&lt;any&gt;;
context;
</code></pre><p>Then, <code>OnInit</code>, we need to determine the content type and set the above properties appropriately.</p><pre><code class="language-typescript">ngOnInit() {
  if (typeof this.content === 'string') {
   this.contentType = 'string';
  } else if (this.content instanceof TemplateRef) {
   this.contentType = 'template';
   this.context = {
    close: this.ref.close.bind(this.ref)
   };
  } else {
   this.contentType = 'component';
  }
}
</code></pre><p>And finally, we are going to be adding a global close button, so let’s add a <code>close</code> method:</p><pre><code class="language-typescript">close() {
 this.ref.close(null);
}
</code></pre><p>And finally, remember to add the Overlay component as an <code>entryComponent</code> in your app module.</p><h5 id="component-template">Component Template</h5><p>In the template, we are going to use <code>ngSwitch</code> to switch between content type and add a global close button for our modal.</p><pre><code class="language-html">&lt;div class="modal-content"&gt;
 &lt;ng-container [ngSwitch]="contentType"&gt;
  &lt;ng-container *ngSwitchCase="'string'"&gt;
      &lt;div class="box"&gt;
        &lt;div [innerHTML]="content"&gt;&lt;/div&gt;
   &lt;/div&gt;
  &lt;/ng-container&gt;
  
  &lt;ng-container *ngSwitchCase="'template'"&gt;
   …
  &lt;/ng-container&gt;

  &lt;ng-container *ngSwitchCase="'component'"&gt;
   …
  &lt;/ng-container&gt;
 &lt;/ng-container&gt;
&lt;/div&gt;

&lt;!-- You can also add a global close button --&gt;
&lt;button (click)="close()" class="modal-close is-large" aria-label="close"&gt;&lt;/button&gt;
</code></pre><p>For template content type, we will use <code>ngTemplateOutlet</code>, passing the template, which is the <code>content</code> and then pass the <code>context</code>:</p><pre><code class="language-html">&lt;ng-container *ngTemplateOutlet="content; context: context"&gt;&lt;/ng-container&gt;
</code></pre><p>And while for component content type, we will use <code>ngComponentOutlet</code>, passing the Component, which is the content:</p><pre><code class="language-html">&lt;ng-container *ngComponentOutlet="content"&gt;&lt;/ng-container&gt;
</code></pre><h4 id="the-overlay-service">The Overlay Service</h4><p>Next, we are going to create an Overlay service, which we can inject into any component we want to use our modal overlay. Where we are going to inject <code>Overlay</code> Service and the <code>Injector</code>.</p><pre><code class="language-typescript">export class OverlayService {
  constructor(private overlay: Overlay, private injector: Injector) {}
}
</code></pre><p>Then, add an <code>open</code> method, which will accept content and data. The <code>data</code> param, in this case, is the data you would like to pass to your modal.</p><pre><code class="language-typescript">open&lt;R = any, T = any&gt;(
 content: string | TemplateRef&lt;any&gt; | Type&lt;any&gt;,data: T): MyOverlayRef&lt;R&gt; {
 …
}
</code></pre><p>Inside the method, first, we need to create an <code>OverlayRef</code> object by using the <code>Overlay</code> <code>create</code> method. Feel free to customize the configs to suit your needs.</p><pre><code class="language-typescript">const configs = new OverlayConfig({
 hasBackdrop: true,
 panelClass: ['modal', 'is-active'],
 backdropClass: 'modal-background'
});

const overlayRef = this.overlay.create(configs);
</code></pre><p>Then, let’s instantiate our <code>MyOverlayRef</code> Class passing the <code>OverlayRef</code> object we created above, then content and the data, both from the method parameters.</p><pre><code class="language-typescript">const myOverlayRef = new MyOverlayRef&lt;R, T&gt;(overlayRef, content, data);
</code></pre><p>Create an injector using <code>PortalInjector</code>, so that we can inject our custom <code>MyOverlayRef</code> object to the overlay component, we created above.</p><pre><code class="language-typescript">const injector = this.createInjector(myOverlayRef, this.injector);
</code></pre><p>And finally use <code>ComponentPortal</code>, to attach the <code>OverlayComponent</code> we created above and the newly created injector and return a <code>MyOverlayRef</code> object.</p><pre><code class="language-typescript">overlayRef.attach(new ComponentPortal(OverlayComponent, null, injector));
return myOverlayRef;
</code></pre><p>And here is the method for creating a custom injector using <code>PortalInjector</code>:</p><pre><code class="language-typescript">createInjector(ref: MyOverlayRef, inj: Injector) {
 const injectorTokens = new WeakMap([[MyOverlayRef, ref]]);
 return new PortalInjector(inj, injectorTokens);
}
</code></pre><p>And that’s it, we now have a re-usable modal overlay, that we can use anywhere inside our application.</p><h3 id="usage">Usage</h3><p>First, inject the Overlay Service in the component where you would like to open a new modal overlay.</p><pre><code class="language-typescript">constructor(private overlayService: OverlayService) {}
</code></pre><p>Then, inside the method you would want to trigger the modal overlay, you just<br>use the open method and pass the content and any data you want to pass to the<br>modal overlay.</p><pre><code class="language-typescript">const ref = this.overlayService.open(content, null);

ref.afterClosed$.subscribe(res =&gt; {
 console.log(res);
});
</code></pre><p>The content can be a simple string or a <code>Template</code> or a <code>Component</code>.</p><h4 id="string">String</h4><pre><code class="language-typescript">const ref = this.overlayService.open("Hello World", null);
</code></pre><h4 id="template">Template</h4><pre><code class="language-html">&lt;ng-template #tpl let-close="close"&gt;
  &lt;div class="modal-card"&gt;
  &lt;section class="modal-card-body"&gt;
   A yes no dialog, using template
  &lt;/section&gt;
  &lt;footer class="modal-card-foot"&gt;
   &lt;div class="buttons"&gt;
    &lt;button (click)="close('yes')" type="button" class="button is-success"&gt;Yes&lt;/button&gt;
    &lt;button (click)="close('no')" type="button" class="button is-danger"&gt;No&lt;/button&gt;
   &lt;/div&gt;
  &lt;/footer&gt;
 &lt;/div&gt;
&lt;/ng-template&gt;
</code></pre><p>And a button to open the modal:</p><pre><code class="language-html">&lt;button (click)="open(tpl)" class="button is-small is-primary"&gt;
 Show
&lt;/button&gt;
</code></pre><p>And then open the overlay with an <code>open</code> method:</p><pre><code class="language-typescript">open(content: TemplateRef&lt;any&gt;) {
 const ref = this.overlayService.open(content, null);
 ref.afterClosed$.subscribe(res =&gt; {
  console.log(res);
 });
}
</code></pre><h4 id="component">Component</h4><pre><code class="language-typescript">open() {
 const ref = this.overlayService.open(YesNoDialogComponent, null);
 ref.afterClosed$.subscribe(res =&gt; {
  console.log(res);
 });
}
</code></pre><p>You can also inject the <code>MyOverlayRef</code> inside the component to access data and the close method.</p><pre><code class="language-typescript">constructor(private ref: MyOverlayRef) {}
</code></pre><p>This allows you to pass data to the component and trigger the closing of the modal from within the component.</p><pre><code class="language-typescript">close(value: string) {
 this.ref.close(value);
}
</code></pre><p><strong>NB:</strong> Please remember to add the component as an <code>entryComponent</code> inside your App Module.</p><p>You can find all of the above code <a href="https://github.com/mainawycliffe/ng-cdk-overlay-demo?ref=content.mainawycliffe.dev">here</a> and the demo <a href="https://mainawycliffe.github.io/ng-cdk-overlay-demo/?ref=content.mainawycliffe.dev">here</a>.</p><h3 id="additional-resources">Additional Resources</h3><ul><li><a href="https://material.angular.io/cdk/categories?ref=content.mainawycliffe.dev">Angular Component Development Kit (CDK)</a></li><li><a href="https://netbasal.com/creating-powerful-components-with-angular-cdk-2cef53d81cea?ref=content.mainawycliffe.dev">Creating Powerful Components with Angular CDK</a></li><li><a href="https://material.angular.io/cdk/overlay/api?ref=content.mainawycliffe.dev">API reference for Angular CDK overlay</a></li><li><a href="https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/?ref=content.mainawycliffe.dev">Angular ng-template, ng-container and ngTemplateOutlet - The Complete Guide To Angular Templates</a></li></ul>]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Angular</category>
            <category>Typescript</category>
            <category>Javascript</category>
        </item>
        <item>
            <title><![CDATA[Implement Infinite Scrolling in a ListView - Flutter]]></title>
            <link>https://mainawycliffe.dev/blog/implement-infinite-scrolling-in-a-listview-flutter</link>
            <guid>https://mainawycliffe.dev/blog/implement-infinite-scrolling-in-a-listview-flutter</guid>
            <pubDate>Wed, 02 Oct 2019 21:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Infinite scrolling is a technique where loading of content is done continuously as the user scrolls down, without any action from the user. This has popularized by social media sites and apps such as Twitter, where Twitter loads more tweets as you scroll down. This is a form of pagination but requires no user input to load the next page but instead watches scroll position. When they get close to the end, the next bunch of tweets gets loaded, as shown below:</p>
<h3 id="prerequisite">Prerequisite</h3>
<ul>
<li>Flutter Installation and Setup – <a href="https://flutter.dev/docs/get-started/install?ref=content.mainawycliffe.dev">Link</a>.</li>
</ul>
<h3 id="creatingalistview">Creating a ListView</h3>
<p>We are going to start by creating a ListView to display GitHub Repositories. We will use the GraphQL package for <a href="https://github.com/zino-app/graphql-flutter/?ref=content.mainawycliffe.dev">flutter</a> and will load then in bunches of 20. We are also going to display a loading animation when adding fetching new GitHub repositories.</p>
<pre><code class="language-dart">ListView(
  children: &lt;Widget&gt;[
    for (var repository in repositories)
      // .. list of widgets
    if (result.loading)
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: &lt;Widget&gt;[
          CircularProgressIndicator(),
        ],
      ),
  ],
),
</code></pre>
<h3 id="usescrollcontrollertodetectscrollposition">Use ScrollController to Detect Scroll Position</h3>
<p>Next, we need to determine when to load more GitHub Repositories, i.e. when we are at or near the bottom of the list view. To achieve this, we are going to use ScrollController – <a href="https://api.flutter.dev/flutter/widgets/ScrollController-class.html?ref=content.mainawycliffe.dev">Link</a>. We are going to listen to ScrollController, which will let us know whenever we scroll. We can then check if we are at the end or near the end of ListView, and in that case,  we load more Repositories.</p>
<p>We will start by declaring a new widget property, named <code>_scrollController</code>.</p>
<pre><code class="language-dart">class Widget extends StatelessWidget {
  // ...
  
  ScrollController _scrollController = new ScrollController();

  @override
  Widget build(BuildContext context) {
    // ...
  }
}
</code></pre>
<p>Then, we need to attach our ScrollController to our ListView above.</p>
<pre><code class="language-dart">ListView(
  controller: _scrollController,
  children: &lt;Widget&gt;[
    // ... widgets
  ],
),
</code></pre>
<p>And finally, we need to listen to ScrollController and check where the user is at scrolling.</p>
<pre><code class="language-dart">_scrollController
  ..addListener(() {
    if (_scrollController.position.pixels ==
        _scrollController.position.maxScrollExtent) {
      // ... call method to load more repositories
    }
  });
</code></pre>
<p>From the above code, we are waiting until the scroll position is at the very end. This might not be convenient for you and you might want to trigger the method to fetch more items earlier, let’s say at 90%.</p>
<pre><code class="language-dart">_scrollController
  ..addListener(() {
    var triggerFetchMoreSize =
        0.9 * _scrollController.position.maxScrollExtent;

    if (_scrollController.position.pixels &gt;
        triggerFetchMoreSize) {
      // call fetch more method here
    }
  });
</code></pre>
<h3 id="finalthoughts">Final Thoughts</h3>
<p>This is a simple way to implement infinite scrolling inside a ListView in flutter. You can find the above demo in my GitHub account <a href="https://github.com/mainawycliffe/flutter-infinite-scrolling?ref=content.mainawycliffe.dev">here</a>.</p>
<h3 id="additionalresource">Additional Resource</h3>
<ul>
<li>GraphQL Package for Flutter – <a href="https://github.com/zino-app/graphql-flutter/?ref=content.mainawycliffe.dev">Link</a>.</li>
<li>ListView API Reference – <a href="https://api.flutter.dev/flutter/widgets/ListView-class.html?ref=content.mainawycliffe.dev">Link</a>.</li>
<li>ScrollController API Reference – <a href="https://api.flutter.dev/flutter/widgets/ScrollController-class.html?ref=content.mainawycliffe.dev">Link</a>.</li>
<li>GitHub GraphQL Explorer – <a href="https://developer.github.com/v4/explorer/?ref=content.mainawycliffe.dev">Link</a>.</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded>
            <author>me@mainawycliffe.dev (Maina Wycliffe)</author>
            <category>Flutter</category>
        </item>
    </channel>
</rss>