<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mark Thompson</title>
    <description>The latest articles on Forem by Mark Thompson (@mthompsoncode).</description>
    <link>https://forem.com/mthompsoncode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F652513%2Ffa53093b-b5b7-4ba7-a7e9-8a6087e6ea46.jpeg</url>
      <title>Forem: Mark Thompson</title>
      <link>https://forem.com/mthompsoncode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mthompsoncode"/>
    <language>en</language>
    <item>
      <title>Why Your Angular Bundle Is Bloated</title>
      <dc:creator>Mark Thompson</dc:creator>
      <pubDate>Wed, 29 Jun 2022 22:06:33 +0000</pubDate>
      <link>https://forem.com/bitovi/why-your-angular-bundle-is-bloated-p2d</link>
      <guid>https://forem.com/bitovi/why-your-angular-bundle-is-bloated-p2d</guid>
      <description>&lt;p&gt;A common reason why an Angular bundle is bloated is that it uses a library like &lt;a href="https://momentjs.com/"&gt;MomentJS&lt;/a&gt; that isn't &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking"&gt;tree-shakable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This blog post will go over how to analyze your Angular bundle and pinpoint libraries that are bloating your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why You Should Analyze Your Angular Bundle
&lt;/h2&gt;

&lt;p&gt;It's important to keep an eye on your project dependencies and call out the ones that are bloating your application. MomentJS used to be a staple in my projects until I realized how huge it was.&lt;/p&gt;

&lt;p&gt;The following section will walk through how I came to the conclusion to avoid MomentJS using this &lt;a href="https://m-thompson-code.github.io/moment-replacement/"&gt;demo application&lt;/a&gt; where I display tomorrow's date.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Analyze Your Angular Bundle
&lt;/h2&gt;

&lt;p&gt;A quick way to analyze your Angular bundle is to use &lt;a href="https://github.com/ngx-builders/source-map-analyzer#setting-up-this-builder"&gt;ngx-builders/analyze&lt;/a&gt;, a custom &lt;a href="https://angular.io/guide/cli-builder#cli-builders"&gt;Angular CLI builder&lt;/a&gt; which allows you to run &lt;code&gt;source-map-explorer&lt;/code&gt; with Angular. This will show you how your application is bundled and which dependencies are bloating your application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install &lt;code&gt;ngx-builders/analyze&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng add @ngx-builders/analyze
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install &lt;code&gt;source-map-explorer&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D source-map-explorer
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update &lt;code&gt;package.json&lt;/code&gt; to have an analyze npm script:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[YOUR_PROJECT_NAME]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Likely&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;but&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;doesn't&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;be&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ng"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ng"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"analyze"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ng run [YOUR_PROJECT_NAME]:analyze"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;find&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;angular.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;under&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;projects&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;property&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run analyze npm script&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run analyze
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should see your application build and your browser should open the results provided by &lt;code&gt;source-map-explorer&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Replace MomentJS
&lt;/h2&gt;

&lt;p&gt;This &lt;a href="https://m-thompson-code.github.io/moment-replacement/"&gt;demo&lt;/a&gt; has been implemented 3 ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using &lt;a href="https://github.com/m-thompson-code/moment-replacement/blob/main/src/app/services/date.service.ts#L10"&gt;Native Date API&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using &lt;a href="https://github.com/m-thompson-code/moment-replacement/blob/momentjs/src/app/services/date.service.ts#L11"&gt;MomentJS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using &lt;a href="https://github.com/m-thompson-code/moment-replacement/blob/date-fns/src/app/services/date.service.ts#L12"&gt;date-fns&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Tests
&lt;/h3&gt;

&lt;p&gt;Each of these solutions use the same &lt;a href="https://github.com/m-thompson-code/moment-replacement/blob/main/src/app/services/date.service.spec.ts#L21"&gt;tests&lt;/a&gt; to verify implementation achieves the expected behavior:&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing the Results
&lt;/h3&gt;

&lt;p&gt;Analyzing how each solution affects the overall bundle for my demo shows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Total Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Native Date API&lt;/td&gt;
&lt;td&gt;202 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MomentJS&lt;/td&gt;
&lt;td&gt;575.18 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;date-fns&lt;/td&gt;
&lt;td&gt;222.65 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://m-thompson-code.github.io/moment-replacement/assets/sme-result-native-date.html"&gt;Using Native Date API&lt;/a&gt; negatively impacts my bundle size the least. Total size is &lt;strong&gt;202 KB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdt2rtmchqby7q9iqqfgp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdt2rtmchqby7q9iqqfgp.png" alt="native data api bundle graph" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This makes sense since by avoiding any extra libraries, there's no risk of bloating my bundle size. Only downside is that implementation took much longer than using an existing library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://m-thompson-code.github.io/moment-replacement/assets/sme-result-momentjs.html"&gt;Using MomentJS&lt;/a&gt; impacts my bundle size the most. Total size is &lt;strong&gt;575.18 KB&lt;/strong&gt;. Using MomentJS bloats my application significantly resulting in being &lt;strong&gt;64.8%&lt;/strong&gt; of my total bundle size. This is because &lt;strong&gt;MomentJS is not &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking"&gt;tree-shakable&lt;/a&gt; and results in importing the entire library regardless of how little it is used.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ytdft14wp54j0ij99ba.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ytdft14wp54j0ij99ba.gif" alt="MomentJS bundle graph" width="600" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://m-thompson-code.github.io/moment-replacement/assets/sme-result-date-fns.html"&gt;Using date-fns&lt;/a&gt; increases my bundle size by &lt;strong&gt;20.79 KB&lt;/strong&gt;. Total size is &lt;strong&gt;222.65 KB&lt;/strong&gt; resulting in being &lt;strong&gt;9.3%&lt;/strong&gt; of my total bundle size. This is a huge improvement over importing MomentJS. This is because date-fns is &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking"&gt;tree-shakable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vmayc4ow1ikpt8b4j7q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vmayc4ow1ikpt8b4j7q.gif" alt="data-fns bundle graph" width="600" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;When considering adding a library to an Angular application, tools such as &lt;a href="https://github.com/ngx-builders/source-map-analyzer#setting-up-this-builder"&gt;ngx-builders&lt;/a&gt; and &lt;a href="https://github.com/danvk/source-map-explorer#readme"&gt;source-map-explorer&lt;/a&gt; can verify that the library won't bloat that application's bundle size.&lt;/p&gt;

&lt;p&gt;Depending on how much time I want to spend implementing all my features from scratch, I might avoid using any library. But if I want to spend less time reinventing the wheel, I'll reach for a well-known libraries such as &lt;a href="https://date-fns.org/"&gt;date-fns&lt;/a&gt; that are &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking"&gt;tree-shakable&lt;/a&gt;. One thing is certain, I'll avoid libraries like &lt;a href="https://momentjs.com/"&gt;MomentJS&lt;/a&gt; since they result in an unnecessary increase in bundle size.&lt;/p&gt;

&lt;p&gt;Long story short, please consider the &lt;a href="https://momentjs.com/docs/#/-project-status/recommendations/"&gt;alternatives&lt;/a&gt; to MomentJS.&lt;/p&gt;

&lt;p&gt;Want to read more blog posts by Bitovi? Check out more posts at &lt;a href="https://www.bitovi.com/blog/rfc-strictly-typed-reactive-forms-gotchas-every-angular-developer-needs-to-know"&gt;our blogs at Bitovi.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Need help analyzing your Angular application? Bitovi is here to help! &lt;a href="https://bitovi.com/angular"&gt;Contact us today&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>RFC: Strictly Typed Reactive Forms Gotchas Every Angular Developer Needs to Know</title>
      <dc:creator>Mark Thompson</dc:creator>
      <pubDate>Thu, 19 May 2022 19:41:23 +0000</pubDate>
      <link>https://forem.com/bitovi/rfc-strictly-typed-reactive-forms-gotchas-every-angular-developer-needs-to-know-hee</link>
      <guid>https://forem.com/bitovi/rfc-strictly-typed-reactive-forms-gotchas-every-angular-developer-needs-to-know-hee</guid>
      <description>&lt;p&gt;Angular is a robust framework suitable for large codebases and enterprise applications. One significant contributing factor is Angular’s support for &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;. Angular is built entirely in TypeScript, and because TypeScript is Angular’s primary language, Angular’s documentation treats TypeScript as a first-class citizen.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;RFC: Strictly Typed Reactive Forms complete&lt;/a&gt;, many expect to have strictly typed reactive forms in the upcoming Angular 14 update. After playing around with the &lt;a href="https://github.com/angular/angular/discussions/44513#user-content-prototype"&gt;Strictly Typed Reactive Forms prototype&lt;/a&gt;, I am super excited about this upcoming feature. Not only are we getting strict types for reactive forms, but we are also getting a minor feature: the &lt;code&gt;initialValueIsDefault&lt;/code&gt; option for &lt;code&gt;FormControlOptions&lt;/code&gt; which will allow for resetting form values back to their initial value rather than &lt;code&gt;null&lt;/code&gt; by default:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1fckmz6ojdvwqr1jgrp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1fckmz6ojdvwqr1jgrp.png" alt="initialValueIsDefault old comparison" width="800" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xoj7xsowewl24oey111.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xoj7xsowewl24oey111.png" alt="initialValueIsDefault new comparison" width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Strictly Typed Reactive Forms Gotchas
&lt;/h1&gt;

&lt;p&gt;Strictly typed &lt;a href="https://angular.io/guide/reactive-forms"&gt;Reactive Forms&lt;/a&gt; should be enough of a selling point to migrate to Angular 14, but it doesn’t come without flaws:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reactive Forms have tricky types involving &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;FormArray&lt;/code&gt; generic doesn’t support Tuples.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;FormBuilder&lt;/code&gt; syntactic sugar doesn’t infer proper generic types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://angular.io/guide/forms"&gt;Template-driven Forms&lt;/a&gt; and &lt;a href="https://angular.io/guide/reactive-forms#adding-a-basic-form-control"&gt;Control Bindings&lt;/a&gt; mismatch underlying control type and bound &lt;code&gt;FormControl&lt;/code&gt; type.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will go over each one of these gotchas and provide explanations so you can spend less time debugging and have more time building complex forms.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reactive Forms Have Tricky Types Involving null and undefined
&lt;/h1&gt;

&lt;p&gt;Reactive Forms having tricky types isn’t specific to the &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;Strictly Typed Reactive Forms update&lt;/a&gt;, but if you’re not aware of how &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; play a role in Reactive Forms, you’re likely to run into &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#null-and-undefined"&gt;type errors&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;null&lt;/code&gt; is a common type when considering that &lt;code&gt;FormControl&lt;/code&gt; value can be &lt;code&gt;null&lt;/code&gt; whenever &lt;code&gt;.reset()&lt;/code&gt; is called. This is documented and explained in &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;RFC: Strictly Typed Reactive Forms&lt;/a&gt; under &lt;strong&gt;Nullable Controls and Reset&lt;/strong&gt;. &lt;code&gt;initialValueIsDefault&lt;/code&gt; option for &lt;code&gt;FormControloptions&lt;/code&gt; can be used to avoid this situation by passing true. This will make the &lt;code&gt;FormControl&lt;/code&gt; value non-nullable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff75adxqc2kfj8wnimicb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff75adxqc2kfj8wnimicb.gif" alt="Generic types example" width="600" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any disabled control’s value can be excluded from its &lt;code&gt;FormGroup&lt;/code&gt; or &lt;code&gt;FormArray&lt;/code&gt; value. In these situations, it’s easy to stumble upon undefined when expecting some nested control value. This is documented and explained in &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;RFC: Strictly Typed Reactive Forms&lt;/a&gt; under &lt;strong&gt;Disabled Controls&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And because &lt;code&gt;FormGroup&lt;/code&gt; provides &lt;code&gt;.removeControl()&lt;/code&gt; and &lt;code&gt;.addControl()&lt;/code&gt;, you will have to explicitly mark that control’s key in the &lt;code&gt;FormGroup&lt;/code&gt; as &lt;a href="https://www.typescriptlang.org/docs/handbook/2/objects.html#optional-properties"&gt;optional&lt;/a&gt;. This is documented and explained in RFC: Strictly Typed Reactive Forms under &lt;strong&gt;Adding and Removing Controls&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  FormArray generic doesn’t support Tuples
&lt;/h1&gt;

&lt;p&gt;Currently, &lt;code&gt;FormArrays&lt;/code&gt; are homogeneous - every control in a &lt;code&gt;FormArray&lt;/code&gt; is of the same type. Attempting to use a Tuple of &lt;code&gt;FormControls&lt;/code&gt; for its generic type will result in a type error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntzehzt4q8wnwx36guxj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntzehzt4q8wnwx36guxj.gif" alt="Tuple example" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luckily the &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;Strictly Typed Reactive Forms update&lt;/a&gt; anticipates that most projects will not be 100% compatible with the update and provide a backward-compatible workaround. You can opt-out of strictly typed Reactive Forms by providing the explicit any generic to the &lt;code&gt;FormArray&lt;/code&gt;. Or, in this specific situation, you can union the expected generic types for each &lt;code&gt;FormControl&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fky8jskkirj6crpntcq17.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fky8jskkirj6crpntcq17.gif" alt="Tuple workaround example" width="600" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, we’ll have to settle for &lt;code&gt;FormArrays&lt;/code&gt; with a single-typed &lt;code&gt;FormControl&lt;/code&gt; array as its generic. Support for Tuple-typed &lt;code&gt;FormArrays&lt;/code&gt; will likely become added in a follow-up update.&lt;/p&gt;

&lt;h1&gt;
  
  
  FormBuilder Syntactic Sugar Doesn’t Infer Proper Generic Types
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;FormBuilder&lt;/code&gt; provides syntactic sugar that shortens creating instances of &lt;code&gt;FormControl&lt;/code&gt;, &lt;code&gt;FormGroup&lt;/code&gt;, or &lt;code&gt;FormArray&lt;/code&gt;. Typically this reduces the amount of boilerplate needed to build complex forms. Still, since &lt;code&gt;FormBuilder&lt;/code&gt; can’t infer the generic types like how &lt;code&gt;FormGroup&lt;/code&gt; or &lt;code&gt;FormArray&lt;/code&gt; constructor does, you end up with type errors complaining that &lt;code&gt;AbstractControl&lt;/code&gt; isn’t assignable to type &lt;code&gt;FormControl&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feckyf1gt277mj6o62eru.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feckyf1gt277mj6o62eru.gif" alt="FormBuilder example" width="507" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Template-driven Forms and Control Bindings
&lt;/h1&gt;

&lt;p&gt;Angular's template type checking engine will not be able to assert that the value produced by the underlying control (described by its &lt;code&gt;ControlValueAccessor&lt;/code&gt;) is of the same type as the &lt;code&gt;FormControl&lt;/code&gt;. This is documented and explained in &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;RFC: Strictly Typed Reactive Forms&lt;/a&gt; under &lt;strong&gt;Control Bindings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The above restriction also applies to &lt;code&gt;NgModel&lt;/code&gt; and &lt;a href="https://angular.io/guide/forms-overview#setup-in-template-driven-forms"&gt;template-driven forms&lt;/a&gt;. This is documented and explained in &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;RFC: Strictly Typed Reactive Forms&lt;/a&gt; under &lt;strong&gt;Template-driven Forms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You won’t get a type error when binding a &lt;code&gt;FormControl&lt;/code&gt; with a string value to a DOM element that has a numeric value.&lt;/p&gt;

&lt;p&gt;This is a limitation introduced by the current template type-checking mechanism where a &lt;code&gt;FormControlDirective&lt;/code&gt; which binds to a control does not have access to the type of the &lt;code&gt;ControlValueAccessor&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://github.com/angular/angular/discussions/44513"&gt;RFC: Strictly Typed Reactive Forms&lt;/a&gt; may not be perfect, but it’s a feature that has been &lt;a href="https://github.com/angular/angular/issues/13721#issue-198158565"&gt;asked for since 2016&lt;/a&gt; and is highly anticipated by many seasoned Angular developers. Strict types for Reactive Forms in Angular will help developers write better code and help significantly with debugging. It will ensure better code quality, but it will provide an easier comprehension of how the &lt;a href="https://angular.io/guide/reactive-forms"&gt;Reactive Forms API&lt;/a&gt; works in general.&lt;/p&gt;

&lt;p&gt;Please try out the &lt;a href="https://github.com/angular/angular/discussions/44513#user-content-prototype"&gt;Strictly Typed Reactive Forms prototype&lt;/a&gt;, fork the &lt;a href="https://github.com/dylhunn/typed-forms-example-app"&gt;demo repo&lt;/a&gt;, and share your thoughts.&lt;/p&gt;

&lt;p&gt;I've done a presentation on this topic if you want to &lt;a href="https://www.youtube.com/watch?v=pxqLyvIvMwY"&gt;check it out&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Want to read more blog posts by Bitovi? Check out more posts at &lt;a href="https://www.bitovi.com/blog/rfc-strictly-typed-reactive-forms-gotchas-every-angular-developer-needs-to-know"&gt;our blogs at Bitovi.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>forms</category>
      <category>rfc</category>
      <category>update</category>
    </item>
    <item>
      <title>Why Good Interviewers Still Use FizzBuzz</title>
      <dc:creator>Mark Thompson</dc:creator>
      <pubDate>Sun, 09 Jan 2022 21:25:54 +0000</pubDate>
      <link>https://forem.com/bitovi/solving-fizzbuzz-challenge-in-under-150-lines-of-code-341c</link>
      <guid>https://forem.com/bitovi/solving-fizzbuzz-challenge-in-under-150-lines-of-code-341c</guid>
      <description>&lt;h2&gt;
  
  
  Why Interviewers Use the FizzBuzz Problem
&lt;/h2&gt;

&lt;p&gt;FizzBuzz is a well-known, simple coding assignment that is commonly used as an entry, technical whiteboard exercise in interviews.&lt;/p&gt;

&lt;p&gt;Since the problem is "simple", the focus isn't on whether or not someone can solve it, but how one goes about solving problems and gives that developer a chance to showcase their process on writing maintainable code as a member of a team.&lt;/p&gt;

&lt;p&gt;Bad interviewers only care whether or not the interviewee can actually solve the problem. Good interviewers are looking out for strong coding habits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Writing self-documenting/commented code&lt;/li&gt;
&lt;li&gt;Naturally writing/refactoring code to be DRY&lt;/li&gt;
&lt;li&gt;Deliver code that can be easily maintained&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's go over some solutions for the FizzBuzz problem and highlight bad patterns to avoid in an interview. &lt;/p&gt;

&lt;p&gt;We'll also highlight good alternatives that demonstrate an understanding on how to write maintainable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The FizzBuzz Problem
&lt;/h2&gt;

&lt;p&gt;There are many variations of this problem, we'll be using:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://m-thompson-code.github.io/fizz-buzz/"&gt;[interactive demo]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write a function that accepts one argument: Array of possible whole numbers.

The return of the function should map each value of the Array to some string given these cases:

1. If the number is divisible by 3, map to "Fizz"
2. If the number is divisible by 5, map to "Buzz"
3. If the number is divisible by 3 and 5, map to "Fizzbuzz" instead
4. If the number is NOT divisible by 3 or 5, map number to itself
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've always hated how the instructions for displaying "Fizzbuzz" came somewhere in the middle or the end when in most cases displaying "Fizzbuzz" handled first. I would suggest clarifying that order matters and request that the requirements reflect it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. If the number is divisible by 3 and 5...
2. If the number is divisible by 3...
3. If the number is divisible by 5...
4. Else...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I believe exercises start with badly ordered requirements on purpose to simulate the real world: you're likely to get badly ordered requirements. In this situation, it's important for developers to be proactive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions to the FizzBuzz Problem
&lt;/h2&gt;

&lt;p&gt;Here is a &lt;em&gt;clever&lt;/em&gt; solution to the problem: &lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.01.ts"&gt;[01]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Map an Array of numeric values to Fizzbuzz values
 * @param values Array of numeric values
 * @returns Fizzbuzz values
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFizzbuzzValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this was an open PR, I'd suggest a refactor that made the code changes more clear on what's going on. One-liner solutions are all fun and games until someone reports a bug and I have to cypher all this madness.&lt;/p&gt;

&lt;p&gt;Here's a quick refactor to break down the &lt;em&gt;one-liner&lt;/em&gt; solution: &lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.02.ts"&gt;[02]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="cm"&gt;/**
   * Map an Array of numeric values to Fizzbuzz values
   * @param values Array of numeric values
   * @returns Fizzbuzz values
   */&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFizzbuzzValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm happier with this solution since it is more readable. I value readability over optimization every time since when trying to achieve both, it's always easier to refactor readable code. To further improve the readability of the code, I'd then suggest avoiding nested if statements: &lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.03.ts"&gt;[03]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="cm"&gt;/**
   * Map an Array of numeric values to Fizzbuzz values
   * @param values Array of numeric values
   * @returns Fizzbuzz values
   */&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFizzbuzzValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'm happy, but it could be better. One big problem is that this code is &lt;a href="https://www.bitovi.com/blog/understand-declarative-vs-imperative-code-using-array-functions"&gt;imperative&lt;/a&gt;. Since we know that there is a direct mapping of values of the Array. Why not use &lt;code&gt;Array.map&lt;/code&gt;? &lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.04.ts"&gt;[04]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="cm"&gt;/**
   * Map an Array of numeric values to Fizzbuzz values
   * @param values Array of numeric values
   * @returns Fizzbuzz values
   */&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFizzbuzzValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'm very happy: code is declarative. Any seasoned developer should understand what this code is doing at a glance.&lt;/p&gt;

&lt;p&gt;But if we wanted to consider some optimizations, &lt;code&gt;!(value % 3)&lt;/code&gt; is done twice. And there could be minor confusion on how the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder"&gt;remainder operator&lt;/a&gt; works to determine if something is divisible by another number: &lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.05.ts"&gt;[05]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Checks if a number (dividend) is divisible by another number (divsor)
 * @param dividend - number being checked if divisible
 * @param divisor {number} - what is used to determine if number is divisible by
 * @returns number is divisible
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDivisible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// modulo operation will return 0 if there's no remainders =&amp;gt; divisible&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dividend&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Map an Array of numeric values to Fizzbuzz values
 * @param values Array of numeric values
 * @returns Fizzbuzz values
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFizzbuzzValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divisibleByThree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;isDivisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divisibleByFive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;isDivisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;divisibleByThree&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;divisibleByFive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;divisibleByThree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;divisibleByFive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'm pretty happy. There should be a very clear understanding on what each part does. Now there's enough information for even those who don't know how the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder"&gt;remainder operator&lt;/a&gt; works.&lt;/p&gt;

&lt;p&gt;Only thing I'd suggest is that we migrate the logic for getting a "Fizzbuzz value" to its own function since determining a "Fizzbuzz value" isn't dependent on the Array of values as a whole, but instead depends on each specific value.&lt;/p&gt;

&lt;p&gt;Also, how do we explain that the order of the if statements matter: write some comments! &lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.ts"&gt;[06]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** fizz-buzz.ts */&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Checks if a number (dividend) is divisible by another number (divsor)
 * @param dividend - number being checked if divisible by some other number (divsor)
 * @param divisor {number} - what is used to determine if a number (dividend) is divisible
 * @returns number (dividend) is divisible
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDivisible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dividend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dividend&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;divisor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Get a Fizzbuzz value based on a numeric value
 * @param value Numeric value
 * @returns Fizzbuzz value
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFizzbuzzValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divisibleByThree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;isDivisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divisibleByFive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;isDivisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Check if value is divisible by 3 and 5 first&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;divisibleByThree&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;divisibleByFive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// It is important to check if number is divisible 3 after checking if divisible by 3 and 5&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;divisibleByThree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// It is important to check if number is divisible 5 after checking if divisible by 3 and 5&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;divisibleByFive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Default case: return numeric value as a string&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Map an Array of numeric values to Fizzbuzz values
 * @param values Array of numeric values
 * @returns Fizzbuzz values
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFizzbuzzValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getFizzbuzzValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And how do I ensure that the implementation actually works: write some tests! &lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.spec.ts"&gt;[07]&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** fizz-buzz.spec.ts */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;lib&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./fizz-buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fizz-bizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isDivisible()&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return false if NOT divisible by&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDivisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDivisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return true if divisible by&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDivisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getFizzbuzzValue()&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return Fizzbuzz if divisible by 3 and 5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFizzbuzzValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return Fizz if divisible by 3 and NOT 5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFizzbuzzValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return Fizz if divisible by 5 and NOT 3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFizzbuzzValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return input number if NOT divisible by 5 or 3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFizzbuzzValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getFizzbuzzValues()&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;restoreAllMocks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should use getFizzbuzzValue to create its return value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getFizzbuzzValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockImplementation&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_mock`&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFizzbuzzValues&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;])).&lt;/span&gt;&lt;span class="nf"&gt;toStrictEqual&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;9_mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;35_mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;30_mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;101_mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;]);&lt;/span&gt;

      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenNthCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenNthCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenNthCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenNthCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should map values of the input array to Fizzbuzz values&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFizzbuzzValues&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;])).&lt;/span&gt;&lt;span class="nf"&gt;toStrictEqual&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fizzbuzz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;101&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome, now I'm super happy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We have comments to show that the order matters. &lt;/li&gt;
&lt;li&gt;Our code is fully tested to help ensure it doesn't break.&lt;/li&gt;
&lt;li&gt;Code is very readable and declarative.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Maybe there's even more improvements you'd suggest. Or maybe you'd prefer different test cases or patterns to be used. Please leave a comment to share your thoughts!&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Good interviewers don't only care whether or not the developer can find a solution to a problem.&lt;/p&gt;

&lt;p&gt;They want to know if a developer can ask the right questions to clarify requirements and to convey they understand the problem. They care about hiring developers that can deliver maintainable code.&lt;/p&gt;

&lt;p&gt;In an interview setting where time is a critical factor. We might not have enough time to go over everything we've discussed in this post:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avoiding complex one-liner solutions&lt;/li&gt;
&lt;li&gt;Avoiding nested if statements to make code more readable&lt;/li&gt;
&lt;li&gt;When to use comments&lt;/li&gt;
&lt;li&gt;Moving duplicate code into separate functions&lt;/li&gt;
&lt;li&gt;Writing declarative code over imperative code&lt;/li&gt;
&lt;li&gt;Writing tests to ensure code is working as expected&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's okay! Discussion is an important part of technical interviews. Use discussion to save time and demonstrate an understanding of these concepts.&lt;/p&gt;

&lt;p&gt;Wanna learn more about imperative vs declarative code? Check out this informative &lt;a href="https://www.bitovi.com/blog/understand-declarative-vs-imperative-code-using-array-functions"&gt;post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/m-thompson-code/fizz-buzz/blob/main/src/fizz-buzz/fizz-buzz.ts"&gt;FizzBuzz solution&lt;/a&gt; | &lt;a href="https://m-thompson-code.github.io/fizz-buzz/"&gt;interactive demo&lt;/a&gt; | &lt;a href="https://github.com/m-thompson-code/fizz-buzz"&gt;demo repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>beginners</category>
      <category>testing</category>
      <category>challenge</category>
    </item>
    <item>
      <title>How to Support IE11 Users as You Move to Angular 13</title>
      <dc:creator>Mark Thompson</dc:creator>
      <pubDate>Thu, 11 Nov 2021 16:54:00 +0000</pubDate>
      <link>https://forem.com/bitovi/how-to-support-ie11-users-as-you-move-to-angular-13-179j</link>
      <guid>https://forem.com/bitovi/how-to-support-ie11-users-as-you-move-to-angular-13-179j</guid>
      <description>&lt;p&gt;IE 11 won't be supported in Angular 13. You can support it in 12 while you migrate to 13, or drop support. Either way, you need to act.&lt;/p&gt;

&lt;p&gt;Internet Explorer 11 is a legacy browser and support for it in Angular 13 is being dropped officially. Sticking with Angular 12 is not a viable long term option. Here are ways to support your users when upgrading your Angular version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Update tsconfig.json and populate polyfills&lt;/li&gt;
&lt;li&gt;Use Differential Loading&lt;/li&gt;
&lt;li&gt;How to Customize User Experience for IE 11&lt;/li&gt;
&lt;li&gt;How to Drop Support for IE 11 the Good Way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an Angular developer, you want to provide support for as many browsers as you can, but in the case of Internet Explorer 11, this is becoming increasingly difficult, and soon will no longer be possible. Current market share is &lt;a href="https://gs.statcounter.com/browser-market-share#monthly-202103-202103-bar"&gt;likely less than 1%&lt;/a&gt; and will drop even more as &lt;a href="https://docs.microsoft.com/en-us/lifecycle/faq/internet-explorer-microsoft-edge"&gt;Microsoft retires IE 11 in June 2022&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Even more challenging is that Angular 12 doesn't offer support for IE 11 by default, and Angular 13, coming out next week, is &lt;a href="https://github.com/angular/angular/issues/41840"&gt;completely dropping support&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular.io/guide/browser-support"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4phx885s2uzyxk1bb300.jpeg" alt="Angular browser support" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose a Support Path
&lt;/h2&gt;

&lt;p&gt;There are two ways you can support IE 11 with Angular 12 as you prepare to migrate to Angular 13:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Update &lt;code&gt;tsconfig.json&lt;/code&gt; to use ES5 and update polyfills.ts for ES6/ES7&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Differential Loading&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or you could decide to drop support for IE 11.  You should customize the user experience because if you don't, users will get a blank screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update tsconfig.json and populate polyfills &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;By default, Angular compiles ES6 or ES7. IE 11 only supports ES5. You can update your &lt;code&gt;tsconfig.json&lt;/code&gt; to target ES5. You'll also need to populate your Angular project polyfills.&lt;/p&gt;

&lt;p&gt;Advantages of updating tsconfig.json and including polyfills:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configuration prepares building and local development for IE 11 support&lt;/li&gt;
&lt;li&gt;Faster builds than using Differential Loading&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Imports a lot of polyfills and bloat bundle for legacy AND modern browsers&lt;/li&gt;
&lt;li&gt;This approach has been abandoned as a standard after Angular 7&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Definitions
&lt;/h3&gt;

&lt;p&gt;You'll change the target variable in tsconfig.json, and populate the polyfills file that came with the Angular project. If you're not familiar with these things, here's what they are.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;target&lt;/b&gt;: JavaScript language version for emitted JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Angular polyfills&lt;/b&gt; are fallbacks for missing JavaScript behavior. There are two types:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser polyfills that are applied before loading ZoneJS.&lt;/li&gt;
&lt;li&gt;Application imports that are files imported after ZoneJS that should be loaded before your main file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Polyfills are applied in this order: Browser polyfills → Import ZoneJS → Application imports. You will only need to focus on browser polyfills.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;tsconfig.json&lt;/code&gt; and update &lt;code&gt;target&lt;/code&gt; to &lt;code&gt;es5&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhcbt52k8zifu8fiou0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhcbt52k8zifu8fiou0a.png" alt="tsconfig example with target es2017" width="410" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;polyfills.js&lt;/code&gt; found in the src directory and add &lt;code&gt;import 'core-js';&lt;/code&gt; under browser polyfills.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrlznhb3rzlr37y8jqv2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrlznhb3rzlr37y8jqv2.jpeg" alt="es5 polyfill example" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NOTE: When serving the application, the build was at 505.3 kB. After adding the import of core-js,  it's 1.2 MB. 😬&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Differential Loading &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Differential Loading is the more modern technique introduced in Angular 8. The approach here is  to make two builds. One uses ES5 syntax and a more modern one that uses ES6 syntax. The ES6 build won't include as many polyfills and  going to be much smaller. The ES5 build will have polyfills and be more bloated. &lt;/p&gt;

&lt;h3&gt;
  
  
  Considerations
&lt;/h3&gt;

&lt;p&gt;Advantages of using differential loading:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Smaller bundle sizes for modern browsers&lt;/li&gt;
&lt;li&gt;ES5 bundle includes all required polyfills for legacy browser support automatically&lt;/li&gt;
&lt;li&gt;Latest approach to supporting legacy browsers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates two bundles so longer build times&lt;/li&gt;
&lt;li&gt;Extra configuration is required for local development for legacy browsers&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Find your browser's list file. Depending on the version of Angular, it will be &lt;code&gt;.browserslistrc&lt;/code&gt; or &lt;code&gt;browserslist&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove the word "not" from the IE 11 line.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdqg4dcxep5dv5srijjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdqg4dcxep5dv5srijjq.png" alt="where to update browsers list for IE 11 support" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before I continue, I'll explain what just happened.&lt;/p&gt;

&lt;p&gt;After you changed the browser's list file, when you look at your Angular project through Inspector, you'll see three additional scripts. Here's what it looked like before:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50ibik1v1t2e09h1pwhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F50ibik1v1t2e09h1pwhu.png" alt="No differential loading dom example" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And after:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokz6ej0irbs8wwa9f0hc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokz6ej0irbs8wwa9f0hc.png" alt="Using differential loading dom example" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will have two runtimes, two polyfills, and two mains. Modern browsers will only run the top script that is of type &lt;code&gt;module&lt;/code&gt;. Legacy browsers like IE 11 will run the second one, the &lt;code&gt;nomodule&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftq8te6jzcsrtnssxsv9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftq8te6jzcsrtnssxsv9z.png" alt="module vs nomodule scripts examples example" width="800" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NOTE: The rest of these steps are only needed if you want to run the project locally in development mode if you only use differential loading.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Next up, you're going to create two new custom files in your application, a &lt;code&gt;polyfills.es5.js&lt;/code&gt; in the src directory and &lt;code&gt;tsconfig.es5.json&lt;/code&gt; at the root of your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next steps are similar what you did for older &lt;code&gt;tsconfig.json&lt;/code&gt; method above. Populate the polyfills file with your import. Then switch the tsconfig target to ES5 and to include your new polyfills file.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18s95616drt7zkbf1n7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18s95616drt7zkbf1n7q.png" alt="es5 custom polyfill and tsconfig example" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Now you're going to update &lt;code&gt;angular.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswaidcz0rqk3ex3hclno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswaidcz0rqk3ex3hclno.png" alt="angular json custom es5 build configuration example" width="800" height="663"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add a new build configuration. You can see on line 72 that I've added &lt;code&gt;development-es5&lt;/code&gt;, where I copied all of the properties for &lt;code&gt;development&lt;/code&gt;, and added two extra ones:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"tsConfig": "tsconfig.es5.json",&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"polyfills": "src/polyfills.es5.ts"&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To use this build when you serve locally, you need to add this new build configuration to the serve configurations. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4uooec98cfzvdkt7q8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4uooec98cfzvdkt7q8k.png" alt="angular json custom es5 serve configuration example" width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I did starting at line 94 above, use the same identifier, &lt;code&gt;development-es5&lt;/code&gt;, and set &lt;code&gt;browserTarget&lt;/code&gt; to "&lt;code&gt;handling-ie:build:development-es5"&lt;/code&gt;. Now you can serve your project for IE 11 using &lt;code&gt;ng serve --configuration development-es5&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why You Shouldn't Just Drop Support
&lt;/h2&gt;

&lt;p&gt;You could drop support for IE 11. If you do, here's what an IE 11 user will see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz7bnustz576t86c6tbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz7bnustz576t86c6tbe.png" alt="blank page using IE 11 since IE 11 is trash" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not a good user experience. Instead, we can change a few things to let our visitor know that they need a different browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Customize User Experience for IE 11 &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You don't want IE 11 users to see a white page. Instead, you can warn them about their browser or tell them to do something. Instead, you can use the same approach as you did with Differential Loading. Set a flag and take advantage of that flag to write specific code for legacy browsers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mdnmi8wzjjkjeusnc4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mdnmi8wzjjkjeusnc4z.png" alt="module vs nomodule scripts example" width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you can call a &lt;code&gt;no-es6.js&lt;/code&gt; script that will only run for legacy browsers by using the &lt;code&gt;nomodule&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95wd9ir04xhjwt9al82o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95wd9ir04xhjwt9al82o.png" alt="no-es6 script example" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this script, I set a property, &lt;code&gt;nomodule&lt;/code&gt;, to true on &lt;code&gt;window&lt;/code&gt;. Throughout my application, I can check for that value and I can see whether or not you are using IE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzh9sdgsenngmotp9vzvo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzh9sdgsenngmotp9vzvo.png" alt="custom property on window example to flag IE 11" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;nomodule&lt;/code&gt; is a custom property. That's not something that &lt;code&gt;window&lt;/code&gt; has. Create a &lt;code&gt;window.d.ts&lt;/code&gt;  in the src directory and add that property to &lt;code&gt;global&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsn437spsoek9hvmmxa0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsn437spsoek9hvmmxa0v.png" alt="types support for custom property on window or global example" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Drop Support for IE 11 the Good Way &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Finally, there will probably come a time when you offer no support for IE 11 and you've turned off differential loading or whatever you were using. How do you still provide a good user experience?&lt;/p&gt;

&lt;p&gt;You can update your browser's list to say not IE, but your users will see a blank page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffqqykrvu6flk1mm2lx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffqqykrvu6flk1mm2lx3.png" alt="example of where to include not to drop support for IE 11 in browsers list" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead, you can update the &lt;code&gt;no-es6.js&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3klzibtgy8ncu92zye6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3klzibtgy8ncu92zye6a.png" alt="redirecting from legacy browser example" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can do all sorts of things here. In my example, I check for iIE. If I think you’re using IE, I’m going to try to use the &lt;code&gt;microsoft-edge&lt;/code&gt; handler and open Edge to navigate the site. On IE, I’ll navigate you to a &lt;a href="https://support.microsoft.com/en-us/topic/this-website-works-better-in-microsoft-edge-160fa918-d581-4932-9e4e-1075c4713595"&gt;Microsoft support page&lt;/a&gt; that explains that IE is dropping support soon. If you're not using IE, I navigate you to a generic "hey, your browser is bad"page.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Will You Do?
&lt;/h2&gt;

&lt;p&gt;To sum it all up, there are two main ways to support IE 11. You can update your &lt;code&gt;tsconfig.json&lt;/code&gt;, or you can use Differential Loading.&lt;/p&gt;

&lt;p&gt;And you can provide a better user experience when you are dropping support and you can also provide a better user experience when you fully drop support. It's definitely time to decide what you'll do. &lt;/p&gt;

&lt;p&gt;What do you think you'll do? Have these methods been helpful? Do you have other techniques for managing IE 11 and Angular 13? We'd love to know your thoughts. Drop us a note in the comments section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://angular.io/guide/browser-support#enabling-polyfills-with-cli-projects"&gt;Angular polyfills docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zloirock/core-js/tree/master/packages/core-js/es"&gt;core-js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://angular.io/guide/deprecations#internet-explorer-11"&gt;Angular 13 deprecating IE 11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.angular.io/version-8-of-angular-smaller-bundles-cli-apis-and-alignment-with-the-ecosystem-af0261112a27"&gt;Angular blog on Differential Loading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#other_differences_between_modules_and_standard_scripts"&gt;Javascript modules vs standard scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation"&gt;Adding custom properties to Window type&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>tutorial</category>
      <category>codequality</category>
      <category>ie11</category>
    </item>
  </channel>
</rss>
