<?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: Bosco Domingo</title>
    <description>The latest articles on Forem by Bosco Domingo (@boscodomingo).</description>
    <link>https://forem.com/boscodomingo</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%2F1250908%2F7d9a4eef-212d-4529-8d20-bfa0bad75435.jpeg</url>
      <title>Forem: Bosco Domingo</title>
      <link>https://forem.com/boscodomingo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/boscodomingo"/>
    <language>en</language>
    <item>
      <title>JavaScript imports guide (Everything you need to know, in 5 minutes)</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Wed, 27 Aug 2025 14:22:18 +0000</pubDate>
      <link>https://forem.com/boscodomingo/javascript-imports-guide-725</link>
      <guid>https://forem.com/boscodomingo/javascript-imports-guide-725</guid>
      <description>&lt;h2&gt;
  
  
  Default import
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MY_VAR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Imports the module’s default export (if one exists). &lt;/li&gt;
&lt;li&gt;Shorthand for &lt;code&gt;import { default as X } from "Y"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the default export is an object (for example the &lt;code&gt;process&lt;/code&gt; object in Node.js), calling methods via that object (e.g., &lt;code&gt;process.on(...)&lt;/code&gt;) uses the correct object as the this context.&lt;/li&gt;
&lt;li&gt;Use this when the module exports a stateful object or one “main” entity.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Named import
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MY_VAR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Brings only the explicitly exported property as a raw, static reference.&lt;/li&gt;
&lt;li&gt;If you import a function or method via named import and then call it without its owning object, you may lose the original this binding (so &lt;code&gt;this&lt;/code&gt; may be &lt;code&gt;undefined&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Reduces bundle size (although tree-shakers are quite good at this, it will make compilation faster).&lt;/li&gt;
&lt;li&gt;Still runs code in the imported module.&lt;/li&gt;
&lt;li&gt;Usage: pure or stateless functions and constants, reducing import size.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Namespace import
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;process&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MY_VAR&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MY_VAR&lt;/span&gt; &lt;span class="c1"&gt;// "All good!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Collects &lt;strong&gt;all exports&lt;/strong&gt; into a single &lt;strong&gt;frozen module namespace object&lt;/strong&gt; (properties are immutable).&lt;/li&gt;
&lt;li&gt;Renames the default export to &lt;code&gt;default&lt;/code&gt;. All others are kept the same.&lt;/li&gt;
&lt;li&gt;Methods called via &lt;code&gt;namespace.method()&lt;/code&gt; will still have &lt;code&gt;namespace&lt;/code&gt; as the calling object (so &lt;code&gt;this&lt;/code&gt; inside the method will refer to &lt;code&gt;namespace&lt;/code&gt;, assuming the method uses &lt;code&gt;this&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Usage: accessing all exports from a module without having to import each one.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Side-effect import
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Add a comment to explain why that import is there&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Runs the module’s top-level code but imports nothing.&lt;/li&gt;
&lt;li&gt;Usage: polyfills, patches, or setup code.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Mixed imports
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Combine default and named imports in one statement.&lt;/li&gt;
&lt;li&gt;Handy when you want both the live object &lt;strong&gt;and&lt;/strong&gt; specific named bindings.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Type-only import (TypeScript)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./MyComponent.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** @see MyComponent */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponentLazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./MyComponent.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Imports only type information, erased at runtime.&lt;/li&gt;
&lt;li&gt;Guarantees no runtime code is included.&lt;/li&gt;
&lt;li&gt;Usage: bringing type info, linking to lazily imported modules&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  JSON import (with import assertions)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./config.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Imports a JSON file directly as a parsed object.&lt;/li&gt;
&lt;li&gt;Errors if assertion is not passed&lt;/li&gt;
&lt;li&gt;You get type-checking and autocomplete for free!&lt;/li&gt;
&lt;li&gt;Used to be &lt;code&gt;asserts&lt;/code&gt; instead of &lt;code&gt;with&lt;/code&gt;, you may see that some places. The correct one is &lt;code&gt;with&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Rule of thumb&lt;/strong&gt;:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;default import&lt;/strong&gt; for live objects that have methods with &lt;code&gt;this&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;named import&lt;/strong&gt; when you need just a piece of the module.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;namespace import&lt;/strong&gt; only for modules with pure functions/values.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;type import&lt;/strong&gt; to keep type dependencies clean (TS only).&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;JSON import&lt;/strong&gt; for configs/data files that should be parsed automatically.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;side-effect import&lt;/strong&gt; &lt;em&gt;very&lt;/em&gt; sparingly, for things that must run once globally, and make sure to document it.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>TL;DR CSS measurement units</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Sun, 24 Aug 2025 16:37:12 +0000</pubDate>
      <link>https://forem.com/boscodomingo/tldr-css-measurement-units-41co</link>
      <guid>https://forem.com/boscodomingo/tldr-css-measurement-units-41co</guid>
      <description>&lt;p&gt;A simple reference to check when in doubt about which unit to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Relative To&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;px&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Device Screen&lt;/td&gt;
&lt;td&gt;Fixed-size elements, &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;box-shadow&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rem&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Root (&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;) font-size&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Modern standard.&lt;/strong&gt; &lt;code&gt;font-size&lt;/code&gt;, &lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;, most layout values.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;em&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Parent element's font-size&lt;/td&gt;
&lt;td&gt;Sizing elements relative to their own font-size (e.g., &lt;code&gt;padding&lt;/code&gt; on a button).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;vh&lt;/code&gt;/&lt;code&gt;vw&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Viewport height/width&lt;/td&gt;
&lt;td&gt;Full-screen sections, elements sized relative to window height/width.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Parent element's size&lt;/td&gt;
&lt;td&gt;Responsive layouts, sizing elements inside a container.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Simple takeaway (rule-of-thumb)
&lt;/h2&gt;

&lt;p&gt;For most projects, a good strategy is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Use &lt;code&gt;rem&lt;/code&gt;&lt;/strong&gt; for font sizes and spacing (&lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Use &lt;code&gt;px&lt;/code&gt;&lt;/strong&gt; for tiny, non-scalable values like border widths.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Use &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;vw&lt;/code&gt;, or &lt;code&gt;vh&lt;/code&gt;&lt;/strong&gt; for high-level layout containers.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"font-size: 1.2em;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Computes to 1.2 * 16px = 19.2px --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"font-size: 1.2em;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Computes to 1.2 * 19.2px = 23.04px --&amp;gt;&lt;/span&gt;
        Some text.
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
Table of Contents

&lt;ol&gt;
&lt;li&gt;
1. Absolute Units

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;px&lt;/code&gt; (Pixels)&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

2. Relative Units

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;rem&lt;/code&gt; (Root &lt;code&gt;em&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;em&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vh&lt;/code&gt; (Viewport Height) and &lt;code&gt;vw&lt;/code&gt; (Viewport Width)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;%&lt;/code&gt; (Percentage)&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Absolute Units
&lt;/h2&gt;

&lt;p&gt;Absolute units are fixed and do not change based on any other element's size or screen settings. The most common absolute unit is the pixel (&lt;code&gt;px&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;px&lt;/code&gt; (Pixels)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;What it is:&lt;/strong&gt; A single pixel on the screen. &lt;code&gt;1px&lt;/code&gt; is one dot on your display.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Relative to:&lt;/strong&gt; The device's screen resolution.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case:&lt;/strong&gt; Use &lt;code&gt;px&lt;/code&gt; when you need a fixed size that should not scale. It's great for things like borders (&lt;code&gt;border: 1px solid black;&lt;/code&gt;) or box-shadows where you want a crisp, consistent line.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Downside:&lt;/strong&gt; Using &lt;code&gt;px&lt;/code&gt; for everything, especially for font sizes and spacing, can harm accessibility. Users who have set a larger default font size in their browser will not see &lt;code&gt;px&lt;/code&gt;-based text scale up, making it harder to read.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Relative Units
&lt;/h2&gt;

&lt;p&gt;Relative units are flexible because they are measured in relation to another value. This makes them ideal for building responsive and accessible websites.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;rem&lt;/code&gt; (Root &lt;code&gt;em&lt;/code&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;What it is:&lt;/strong&gt; A unit relative to the font size of the &lt;strong&gt;root element&lt;/strong&gt; (the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Relative to:&lt;/strong&gt; The &lt;code&gt;font-size&lt;/code&gt; of the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element. The browser default is typically &lt;code&gt;16px&lt;/code&gt;, so by default, &lt;code&gt;1rem = 16px&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case:&lt;/strong&gt; This is the &lt;strong&gt;most recommended unit for modern web development&lt;/strong&gt;. Use it for &lt;code&gt;font-size&lt;/code&gt;, &lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;—almost everything. If a user changes their browser's default font size for better accessibility, your entire layout will scale proportionally.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Example:&lt;/strong&gt; If the root font size is &lt;code&gt;16px&lt;/code&gt;, then &lt;code&gt;font-size: 1.5rem;&lt;/code&gt; computes to &lt;code&gt;24px&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;em&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;What it is:&lt;/strong&gt; A unit relative to the font size of its &lt;strong&gt;direct parent element&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Relative to:&lt;/strong&gt; The &lt;code&gt;font-size&lt;/code&gt; of the parent element.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case:&lt;/strong&gt; Useful when you want an element's size to be based on its parent's font size. For example, setting the &lt;code&gt;padding&lt;/code&gt; of a button in &lt;code&gt;em&lt;/code&gt;s will make the padding scale with the button's text size.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Downside (The "Compounding" Effect):&lt;/strong&gt; If you nest elements with &lt;code&gt;em&lt;/code&gt; units, the sizes can compound in unexpected ways. For example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"font-size: 1.2em;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Computes to 1.2 * 16px = 19.2px --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"font-size: 1.2em;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Computes to 1.2 * 19.2px = 23.04px --&amp;gt;&lt;/span&gt;
    Some text.
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This is why &lt;code&gt;rem&lt;/code&gt; is often preferred, as it always relates back to a single, predictable source (&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;vh&lt;/code&gt; (Viewport Height) and &lt;code&gt;vw&lt;/code&gt; (Viewport Width)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;What it is:&lt;/strong&gt; A percentage of the browser window's (viewport's) height or width.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Relative to:&lt;/strong&gt; The viewport (the visible area of the web page). &lt;code&gt;1vh&lt;/code&gt; is 1% of the viewport height, and &lt;code&gt;1vw&lt;/code&gt; is 1% of the viewport width.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case:&lt;/strong&gt; Perfect for creating elements that should take up the full screen or a specific portion of it, regardless of the screen size. A common example is a hero banner that fills the entire screen.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Example:&lt;/strong&gt; &lt;code&gt;height: 100vh;&lt;/code&gt; will make an element exactly as tall as the current browser window.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;%&lt;/code&gt; (Percentage)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;What it is:&lt;/strong&gt; A percentage of the parent element's corresponding property.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Relative to:&lt;/strong&gt; The parent element.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case:&lt;/strong&gt; Mostly used for layout and sizing elements within a container. For example, setting &lt;code&gt;width: 50%;&lt;/code&gt; on an element will make it half the width of its parent.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difference from &lt;code&gt;vw&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;width: 100%&lt;/code&gt; makes an element fill its parent container, while &lt;code&gt;width: 100vw&lt;/code&gt; makes it fill the entire browser window's width, which can cause horizontal scrolling if the parent has padding.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Notion - Create a date range for current week (Mon-Sun)</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Wed, 16 Jul 2025 11:13:26 +0000</pubDate>
      <link>https://forem.com/boscodomingo/notion-create-a-date-range-for-current-week-mon-sun-din</link>
      <guid>https://forem.com/boscodomingo/notion-create-a-date-range-for-current-week-mon-sun-din</guid>
      <description>&lt;p&gt;To create a dynamic date range in Notion that spans the current week (Mon-Sun) at the time of use, you can use the following formula (substitute &lt;code&gt;&amp;lt;Today&amp;gt;&lt;/code&gt; for the actual Today() function):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;dateRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dateSubtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Today&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Today&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;day&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;days&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;dateAdd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Today&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;-&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Today&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;day&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;days&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What it does is simply to take the current date and find the difference to that week's Monday (by subtracting days) and to Sunday (by adding days).&lt;/p&gt;

&lt;p&gt;To use it, simply chuck it into any formula input (such as in a Button that performs actions, or in Automations).&lt;/p&gt;

&lt;p&gt;I personally suggest you create a variable (such as &lt;code&gt;thisWeek&lt;/code&gt;) and reference that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbzi2kup2w1zq8h1cbop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbzi2kup2w1zq8h1cbop.png" alt="Showcase of the use of the formula for this week" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Shameless plug&lt;/strong&gt;: this comes from my &lt;a href="https://boscodomingo.notion.site/Training-Learnings-e204f1c0b51c47698b2bbb5777debd21?source=copy_link" rel="noopener noreferrer"&gt;Weekly Learning page&lt;/a&gt;, where I write about what I learn as I go. It's how I create new pages without having to manually set the weekly range. Quite convenient!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>notion</category>
      <category>formula</category>
    </item>
    <item>
      <title>Go string concatenation benchmark</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Thu, 01 May 2025 18:51:23 +0000</pubDate>
      <link>https://forem.com/boscodomingo/go-string-concatenation-benchmark-2392</link>
      <guid>https://forem.com/boscodomingo/go-string-concatenation-benchmark-2392</guid>
      <description>&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;strings.Builder&lt;/code&gt; is the fastest and takes least memory.&lt;br&gt;
&lt;code&gt;+&lt;/code&gt; is tied in memory but slightly less performant (although much more convenient).&lt;br&gt;
&lt;code&gt;strings.Join&lt;/code&gt; is not a bad alternative for arrays.&lt;br&gt;
&lt;code&gt;fmt.Sprintf&lt;/code&gt; is trash.&lt;/p&gt;

&lt;p&gt;Check &lt;a href="https://github.com/BoscoDomingo/go-string-concatenation-benchmark" rel="noopener noreferrer"&gt;the repo in which I share the benchmarks&lt;/a&gt; so you can test them too!&lt;/p&gt;



&lt;p&gt;Have you ever wondered what the fastest way to concatenate strings is?&lt;/p&gt;

&lt;p&gt;Well I did today, so I whipped up a &lt;a href="https://github.com/BoscoDomingo/go-string-concatenation-benchmark" rel="noopener noreferrer"&gt;quick benchmark&lt;/a&gt; (since a Google search was not yielding me any conclusive results) and as of today, 1st of May 2025, these are the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goos: linux
goarch: amd64
pkg: scratchpad-go
cpu: AMD Ryzen 5 5600X 6-Core Processor             
BenchmarkConcatStrings_Plus-12                      51331621            21.97 ns/op        8 B/op          1 allocs/op
BenchmarkConcatStrings_Sprintf-12                   11596424           102.9 ns/op        40 B/op          3 allocs/op
BenchmarkConcatStrings_StringsBuilder-12            64022565            18.46 ns/op        8 B/op          1 allocs/op
BenchmarkConcatStrings_Join-12                      42522718            27.70 ns/op        8 B/op          1 allocs/op
BenchmarkConcatStringAndInt_Plus-12                 51975021            22.21 ns/op        5 B/op          1 allocs/op
BenchmarkConcatStringAndInt_Sprintf-12              12212780            98.96 ns/op       21 B/op          2 allocs/op
BenchmarkConcatStringAndInt_StringsBuilder-12       56754538            20.43 ns/op        8 B/op          1 allocs/op
BenchmarkConcatStringAndInt_Join-12                 38538142            28.96 ns/op        8 B/op          1 allocs/op
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>go</category>
      <category>benchmark</category>
      <category>performance</category>
    </item>
    <item>
      <title>Why `response.json()` must be awaited</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Tue, 05 Nov 2024 15:17:18 +0000</pubDate>
      <link>https://forem.com/boscodomingo/why-responsejson-must-be-awaited-cbd</link>
      <guid>https://forem.com/boscodomingo/why-responsejson-must-be-awaited-cbd</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?app=desktop&amp;amp;v=Ki64Cnyf_cA" rel="noopener noreferrer"&gt;Credit to the source&lt;/a&gt;, I'm just putting it in writing for easier access!&lt;/p&gt;

&lt;p&gt;It turns out &lt;code&gt;json()&lt;/code&gt; must be awaited because &lt;code&gt;fetch()&lt;/code&gt; will resolve or reject when it receives the response headers, regardless of what the body is! The body is likely to be much larger in size, and may even take a long time to arrive and/or might do so in chunks, thus it has to be awaited even after &lt;code&gt;fetch()&lt;/code&gt; has finished.&lt;/p&gt;

&lt;p&gt;I had no idea why this behaviour existed until now (and it comes from  HTTP btw, it's not JS-specific), so it feels great understanding why.&lt;/p&gt;

&lt;p&gt;Again, watch &lt;a href="https://www.youtube.com/watch?app=desktop&amp;amp;v=Ki64Cnyf_cA" rel="noopener noreferrer"&gt;the video&lt;/a&gt; for a better and more visual explanation! (it's 6 minutes long, worth every second)&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>node</category>
      <category>react</category>
    </item>
    <item>
      <title>Set up Go with mise (version management) and the VS Code/Cursor extension</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Fri, 06 Sep 2024 15:29:56 +0000</pubDate>
      <link>https://forem.com/boscodomingo/set-up-go-with-version-management-and-vs-code-extension-n5d</link>
      <guid>https://forem.com/boscodomingo/set-up-go-with-version-management-and-vs-code-extension-n5d</guid>
      <description>&lt;p&gt;&lt;strong&gt;2025 update&lt;/strong&gt;: Go is natively supported by mise so the asdf plugin is no longer needed. The bug I mention below was fixed too, so it's even easier now!&lt;/p&gt;




&lt;p&gt;This comes from my answer in &lt;a href="https://github.com/golang/vscode-go/issues/971#issuecomment-2334296811" rel="noopener noreferrer"&gt;the official Go - VS Code Extension repo&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;For &lt;a href="https://github.com/jdx/mise" rel="noopener noreferrer"&gt;mise&lt;/a&gt; &lt;strong&gt;the solution is to point to wherever &lt;code&gt;mise where go&lt;/code&gt; points to&lt;/strong&gt; (or &lt;code&gt;which go&lt;/code&gt;, but the former is preferred), which should be the mise folder.&lt;/p&gt;

&lt;p&gt;Resulting &lt;code&gt;settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"go.alternateTools"&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;"go"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.local/share/mise/installs/go/latest/go/bin/go"&lt;/span&gt;&lt;span class="w"&gt;
&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;del&gt;However, this will pin it to one specific version due to &lt;a href="https://github.com/jdx/mise/issues/2275" rel="noopener noreferrer"&gt;what seems like a bug&lt;/a&gt; (in my case &lt;code&gt;mise install go@latest&lt;/code&gt; installed 1.23.0 instead of 1.23.1 as of writing, and saved it to &lt;code&gt;~/.local/share/mise/installs/go/1.23.0&lt;/code&gt;).&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;del&gt;To fix this, use the &lt;a href="https://github.com/asdf-community/asdf-golang" rel="noopener noreferrer"&gt;asdf-golang plugin&lt;/a&gt; (&lt;code&gt;mise p i https://github.com/asdf-community/asdf-golang&lt;/code&gt;) which will install it correctly to &lt;code&gt;~/.local/share/mise/installs/go/latest/go/bin/go&lt;/code&gt; which you can then add to your &lt;code&gt;settings.json&lt;/code&gt;:&lt;/del&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>vscode</category>
      <category>mise</category>
      <category>linux</category>
    </item>
    <item>
      <title>On Agile Development (ft. Dr. John Ousterhout)</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Mon, 05 Aug 2024 17:26:56 +0000</pubDate>
      <link>https://forem.com/boscodomingo/on-agile-development-ft-dr-john-ousterhout-4j9o</link>
      <guid>https://forem.com/boscodomingo/on-agile-development-ft-dr-john-ousterhout-4j9o</guid>
      <description>&lt;p&gt;Talking about how modern Agile Development interacts with the advice he gives in his (awesome) book &lt;em&gt;A Philosophy of Software Design&lt;/em&gt;, Dr John Ousterhout wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Developing incrementally is generally a good idea, &lt;strong&gt;but the increments of development should be abstractions, not features"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;I &lt;strong&gt;deeply&lt;/strong&gt; resonate with this quote. So much so, I had to share it in a blog post.&lt;/p&gt;

&lt;p&gt;Far too many times I've seen the quick-and-dirty, "make it work now" style of programming - what the author calls &lt;em&gt;tactical&lt;/em&gt; - just evolve into a massive, unmaintainable piece of garbage that most likely had to be rewritten, costing more time and effort than doing it right in the first place and slowly iterating towards better design would've (not to mention the cost of sanity and burnout from the developers).&lt;/p&gt;




&lt;p&gt;Please develop with the future in mind. Making it work now &lt;em&gt;is&lt;/em&gt; important, yes. &lt;strong&gt;Making sure it doesn't crumble in 6-12 months even more so&lt;/strong&gt;. Your future self will thank you.&lt;/p&gt;

&lt;p&gt;Note: &lt;strong&gt;Apply this advice pragmatically&lt;/strong&gt;. Do not over-engineer every piece of software you build from now on, but do apply best practices, and please, if you have to revisit software, then make it better, not worse. If you're building what it supposed to be a core product, build it over a strong foundation, not on &lt;em&gt;sand, hopes and wishes&lt;/em&gt;. Take pride in your work. That's it.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>softwareengineering</category>
      <category>softwaredesign</category>
      <category>programming</category>
    </item>
    <item>
      <title>The best Design Patterns repository</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Mon, 05 Aug 2024 08:13:04 +0000</pubDate>
      <link>https://forem.com/boscodomingo/best-repository-of-design-patterns-31nl</link>
      <guid>https://forem.com/boscodomingo/best-repository-of-design-patterns-31nl</guid>
      <description>&lt;p&gt;Quick one today: the other day I got an RSS notification that &lt;a href="https://martinfowler.com/" rel="noopener noreferrer"&gt;Martin Fowler&lt;/a&gt; had published a &lt;a href="https://martinfowler.com/articles/2024-eaa-catalog-refresh.html" rel="noopener noreferrer"&gt;new article&lt;/a&gt; to quickly mention that he'd updated his &lt;a href="https://martinfowler.com/eaaCatalog/" rel="noopener noreferrer"&gt;&lt;em&gt;Catalog of Patterns of Enterprise Application Architecture&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I had never heard of said &lt;em&gt;catalogue&lt;/em&gt;, but decided to pop in for a look, and boy was I happy I did. This is a fantastic repository of some of the best Design Patterns, complete with examples, diagrams and use cases, organised by topic. I highly recommend you check it out if you're at all interested in bettering your Software Design/Architecture skills. &lt;a href="https://martinfowler.com/eaaCatalog/" rel="noopener noreferrer"&gt;Link here again for ease&lt;/a&gt;&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>programming</category>
      <category>martinfowler</category>
    </item>
    <item>
      <title>TypeScript Enums are *more than ok*</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Fri, 14 Jun 2024 12:21:01 +0000</pubDate>
      <link>https://forem.com/boscodomingo/typescript-enums-are-more-than-ok-ed6</link>
      <guid>https://forem.com/boscodomingo/typescript-enums-are-more-than-ok-ed6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Update 2025-08-24: I've started to favour objects + &lt;code&gt;as const&lt;/code&gt; over Enums mostly to be able to easily use their keys and to avoid TypeScript magic (better JS compatibility), but the takeaways from this article still stand and Enums are still quite ok!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;As long as you use text-based ones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In TypeScript, enums by default assign numbers as the values in the order the keys are defined. This means that changing existing enums can lead to unwanted changes:&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="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;key0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
    &lt;span class="nx"&gt;key1&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Later commit, disaster strikes&lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;key0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
    &lt;span class="nx"&gt;key2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 1 - this was taken over&lt;/span&gt;
    &lt;span class="nx"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
    &lt;span class="nx"&gt;key3&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// And again, at a later commit just mayhem&lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;key2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
    &lt;span class="nx"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
    &lt;span class="nx"&gt;key3&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We definitely want to avoid that. That's why you should assign values to your enums' keys, the best option being text (numbers still do weird things, watch the videos below to understand more).&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;as const&lt;/code&gt; objects
&lt;/h1&gt;

&lt;p&gt;The biggest opponent to enums is the controversial &lt;code&gt;as const&lt;/code&gt; object. The implementation goes something like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ENUM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;key0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;key1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EnumKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ENUM&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "key0" | "key1"&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;EnumValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ENUM&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;EnumKeys&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// "0" | "1"&lt;/span&gt;

&lt;span class="c1"&gt;// Which allows for&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EnumKeys&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="nx"&gt;EnumValues&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Both have intellisense&lt;/span&gt;
&lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ENUM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Just like regular enums&lt;/span&gt;
&lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key1&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="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// But values are accepted too&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the thing is string-based enums can already do that:&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="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Enum2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;key0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;key1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Which allows for&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Enum2Keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Enum2&lt;/span&gt; &lt;span class="c1"&gt;// "key0" | "key1"&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Enum2Values&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;Enum2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="c1"&gt;// "0" | "1"&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Enum2Keys&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="nx"&gt;Enum2Values&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Both have intellisense&lt;/span&gt;
&lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Enum2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key1&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="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Now values are accepted too&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No need for extra convoluted code that people unfamiliar with TypeScript won't even understand. A much simpler and nicer way to achieve the same goal, using vanilla TS and string interpolation.&lt;/p&gt;

&lt;p&gt;And this article doesn't even cover computed values and other awesome features enums have. I genuinely think they are a great addition, and hope the &lt;a href="https://github.com/rbuckton/proposal-enum" rel="noopener noreferrer"&gt;TC39 proposal&lt;/a&gt; to implement them in base JS goes through. They are present in almost any modern language for a reason, folks.&lt;/p&gt;




&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?app=desktop&amp;amp;si=p9AA8VHcoEy1KM3B&amp;amp;v=jjMbPt_H3RQ&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;Enums considered harmful&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/typescript/comments/yr4vv5/typescript_enums_are_terrible_heres_why/" rel="noopener noreferrer"&gt;TypeScript Enums are terrible. Here's why&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>The difference between Promise.all() vs Promise.allSettled() vs Promise.any() vs Promise.race() in 30 seconds</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Fri, 26 Apr 2024 17:45:26 +0000</pubDate>
      <link>https://forem.com/boscodomingo/the-difference-between-promiseall-vs-promiseallsettled-vs-promiseany-vs-promiserace-in-30-seconds-onp</link>
      <guid>https://forem.com/boscodomingo/the-difference-between-promiseall-vs-promiseallsettled-vs-promiseany-vs-promiserace-in-30-seconds-onp</guid>
      <description>&lt;p&gt;If you're writing code in JavaScript or TypeScript (or CoffeeScript for whatever reason!) you'll come across Promises. One of the best features they provide is concurrency, which is usually achieved with &lt;code&gt;Promise.all()&lt;/code&gt;. That being said, I'd like to quickly explore the differences between the available methods: &lt;code&gt;all()&lt;/code&gt;, &lt;code&gt;allSettled()&lt;/code&gt;, &lt;code&gt;any()&lt;/code&gt; and &lt;code&gt;race()&lt;/code&gt; (this last one I hadn't even heard of until researching for this article!).&lt;/p&gt;

&lt;h1&gt;
  
  
  At a glance
&lt;/h1&gt;

&lt;p&gt;All of them start the Promises &lt;strong&gt;concurrently&lt;/strong&gt; (not necessarily in parallel!). They all &lt;strong&gt;ignore non-promises&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;all()&lt;/code&gt;: &lt;strong&gt;Resolves only if &lt;em&gt;all&lt;/em&gt; promises resolve&lt;/strong&gt;. Early reject if any one promise rejects. Returns an array of the settled values in the order they were inserted, not settled. &lt;code&gt;Promise.all()&lt;/code&gt; resolves synchronously if and only if the iterable passed is &lt;code&gt;[]&lt;/code&gt;. Even if you pass &lt;code&gt;[1, 'abc', {}]&lt;/code&gt;, it will resolve asynchronously.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allSettled()&lt;/code&gt;: Resolves only if all promises resolve. Reject if any one promise rejects (just like &lt;code&gt;all()&lt;/code&gt; so far) &lt;strong&gt;BUT WAITS FOR ALL OTHERS TO FINISH&lt;/strong&gt;. Returns an array of the settled status and values in the order they were inserted, not settled.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;any()&lt;/code&gt;: &lt;strong&gt;Resolves if any promise resolves&lt;/strong&gt;. Rejects only if all the promises reject (opposite to &lt;code&gt;all()&lt;/code&gt;). Returns the first resolved value.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;race()&lt;/code&gt;: &lt;strong&gt;Rejects or resolves according to whatever the first settled promise does&lt;/strong&gt;. Returns the first resolved value.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Don't forget to check out all my other content for more guides like this one!&lt;/p&gt;




&lt;p&gt;Here is some code you can test yourself to check the results. Feel free to test it out and comment any findings you may have!&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/BoscoDomingo/js-promise-concurrency" rel="noopener noreferrer"&gt;the GitHub repo&lt;/a&gt; too. Give it a star ⭐ while you're at it!&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;/* All of them start the Promises concurrently (not in parallel necessarily!). They all ignore non-promises.

- all(): Resolves only if all promises resolve. Early reject if any one promise rejects.
    Returns an array of the settled values in the order they were inserted, not settled.
    Promise.all() resolves synchronously if and only if the iterable passed is []. Even if you pass [1,'abc',{}], it will resolve asynchronously.

- allSettled(): Resolves only if all promises resolve. Reject if any one promise rejects BUT WAITS FOR ALL OTHERS TO FINISH.
    Returns an array of the settled stati and values in the order they were inserted, not settled.

- any(): Resolves if any promise resolves. Rejects only if all the promises reject (opposite to all()).
    Returns the first resolved value.

- race(): Rejects or resolves according to whatever the first settled promise does.
    Returns the first settled value.
*/&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&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;nonPromise&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;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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;function&lt;/span&gt; &lt;span class="nf"&gt;setPromises&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;immediateResolve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&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="nx"&gt;nonPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&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;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Resolved after timeout&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setPromises&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.all 1: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output (after at least 1000ms): Array [3, 42, "foo"]&lt;/span&gt;

  &lt;span class="nf"&gt;setPromises&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&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;resultWithRejection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Immediate reject&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.all 2: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultWithRejection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Never reached, rejection causes interruption&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setPromises&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&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;resultWithCaughtRejection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Immediate reject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&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="p"&gt;]);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.all 3: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultWithCaughtRejection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected: [ 3, 42, 'Resolved after timeout', undefined ]. Rejection is never bubbled up&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseAllSettled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setPromises&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.allSettled 1: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Expected output: [{ status: 'fulfilled', value: 3 }, { status: 'fulfilled', value: 42 }, { status: 'fulfilled', value: 'Resolved after timeout' }]&lt;/span&gt;

  &lt;span class="nf"&gt;setPromises&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&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;resultWithRejection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Immediate reject&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.allSettled 2: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultWithRejection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Expected output: [{ status: 'fulfilled', value: 3 }, { status: 'fulfilled', value: 42 }, { status: 'fulfilled', value: 'Resolved after timeout' }, { status: 'rejected', reason: 'Immediate reject' }]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseAny&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setPromises&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.any 1: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: 3, not 2, as it doesn't come from a promise&lt;/span&gt;

  &lt;span class="nf"&gt;setPromises&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&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;resultWithRejection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Immediate reject&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.any 2: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultWithRejection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Always reached unless they all rejected&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseRace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setPromises&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.race 1: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: 3&lt;/span&gt;

  &lt;span class="nf"&gt;setPromises&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;try&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;resultWithRejection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;immediateResolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;nonPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;timeoutPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Immediate reject&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.race 2: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultWithRejection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Never reached&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Starting test:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.allSettled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseAllSettled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.allSettled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.any&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseAny&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.any&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.race&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;tryPromiseRace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Promise.race&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Sources: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all" rel="noopener noreferrer"&gt;&lt;code&gt;all()&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled" rel="noopener noreferrer"&gt;&lt;code&gt;allSettled()&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any" rel="noopener noreferrer"&gt;&lt;code&gt;any()&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race" rel="noopener noreferrer"&gt;&lt;code&gt;race()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Node Test Runner vs Bun Test Runner (with TypeScript and ESM)</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Fri, 26 Apr 2024 17:01:51 +0000</pubDate>
      <link>https://forem.com/boscodomingo/node-test-runner-vs-bun-test-runner-with-typescript-and-esm-44ih</link>
      <guid>https://forem.com/boscodomingo/node-test-runner-vs-bun-test-runner-with-typescript-and-esm-44ih</guid>
      <description>&lt;p&gt;I've recently gotten the chance to play with both of these while looking for a long-term testing framework at my job.&lt;br&gt;
I also considered Node-TAP, Vitest, Jest and Mocha, but none truly convinced me as much as these two for a multitude of reasons (annoying config, lack of ESM support, speed, etc), so I'll focus on them.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;a href="https://nodejs.org/api/test.html" rel="noopener noreferrer"&gt;Node Test Runner&lt;/a&gt;
&lt;/h1&gt;
&lt;h2&gt;
  
  
  The good
&lt;/h2&gt;

&lt;p&gt;Built-in. That's it, so simple, so nice. Plus it works with ESM too! &lt;/p&gt;
&lt;h2&gt;
  
  
  Use
&lt;/h2&gt;

&lt;p&gt;It has everything you'd expect (&lt;code&gt;describe/it&lt;/code&gt;, &lt;code&gt;mock&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;beforeEach&lt;/code&gt;, etc...) and uses &lt;code&gt;assert&lt;/code&gt; instead of the usual &lt;code&gt;expect&lt;/code&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="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;expectedId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The bad
&lt;/h2&gt;

&lt;p&gt;No TS support out-of-the-box. So much so, that you need to do a hacky workaround in your &lt;code&gt;package.json&lt;/code&gt; scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"glob -c &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;tsx --test --test-reporter spec &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./test/**/*.test.ts&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need both a loader (&lt;code&gt;tsx&lt;/code&gt; or similar) and a way to tell it where your tests are (in this case, &lt;code&gt;glob&lt;/code&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This snippet comes from &lt;a href="https://dev.to/boscodomingo/the-ultimate-node-test-runner-typescript-env-variables-guide-1hlj"&gt;the guide I made on setting up Node Test Runner for TypeScript&lt;/a&gt;, so check it out if you want more info!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://bun.sh/docs/cli/test" rel="noopener noreferrer"&gt;Bun Test Runner&lt;/a&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The good
&lt;/h2&gt;

&lt;p&gt;It's fast. Like twice as fast as Node's runner, which was already faster than Jest and Vitest. It also is as easy to set up as Node's Test Runner, and includes TS support as well!&lt;/p&gt;

&lt;h2&gt;
  
  
  Use
&lt;/h2&gt;

&lt;p&gt;It has a decent compatibility with both Jest and Vitest's APIs (you can track progress &lt;a href="https://github.com/oven-sh/bun/issues/1825" rel="noopener noreferrer"&gt;here&lt;/a&gt;) so you can use it as almost a drop-in replacement for either. &lt;br&gt;
Just as Node's, it has &lt;code&gt;describe/it&lt;/code&gt;, &lt;code&gt;mock&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt; and others, but with the &lt;code&gt;expect&lt;/code&gt; syntax (which I find more readable). For example:&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expectedId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The bad
&lt;/h2&gt;

&lt;p&gt;Iffy debugging support. It requires the VS Code extension if you use VS Code, and I'm not sure how well other IDEs are supported. It also requires installing Bun as a dependency in &lt;code&gt;package.json&lt;/code&gt; if you still use npm/pnpm/yarn to pin the right version.&lt;/p&gt;

&lt;h1&gt;
  
  
  Verdict
&lt;/h1&gt;

&lt;p&gt;If you already use Bun, or don't mind having to use additional tools for debugging, then Bun is definitely the choice to make. It's easier to use and faster, and has about the same functionality if not more than Node's.&lt;/p&gt;

&lt;p&gt;If on the other hand you care about "native" experience, want the best CI installation times, or just want to use all-Node, then the good news is that Node's Test Runner is not far behind, and you won't feel like you're being left out for not using the most &lt;em&gt;blazingly fast&lt;/em&gt;™ tool.&lt;/p&gt;

&lt;p&gt;In any case, either one should be a good choice as they are seeing active development (&lt;a href="https://nodejs.org/en/blog/announcements/v22-release-announce" rel="noopener noreferrer"&gt;Node just released version 22&lt;/a&gt;, and &lt;a href="https://bun.sh/blog/bun-v1.1" rel="noopener noreferrer"&gt;Bun announced v1.1 three weeks ago&lt;/a&gt; as of the time of writing) and aim to be easy-to-use, fast tools.&lt;/p&gt;




&lt;p&gt;Hope this article was of use in helping you decide which one to go for, and don't forget to check all my other stuff for more posts like this one!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>node</category>
      <category>bunjs</category>
      <category>typescript</category>
    </item>
    <item>
      <title>The ultimate Node Test Runner + TypeScript + ENV variables guide</title>
      <dc:creator>Bosco Domingo</dc:creator>
      <pubDate>Thu, 25 Apr 2024 13:38:39 +0000</pubDate>
      <link>https://forem.com/boscodomingo/the-ultimate-node-test-runner-typescript-env-variables-guide-1hlj</link>
      <guid>https://forem.com/boscodomingo/the-ultimate-node-test-runner-typescript-env-variables-guide-1hlj</guid>
      <description>&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/BoscoDomingo/a06329ca1a2f36ccb7c168d4a8de6c92" rel="noopener noreferrer"&gt;Check the GitHub Gist I made&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This also works in a monorepo ;). If you're working on a single project, adapt the paths accordingly. The expected folder structure is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts-project/
├── tsconfig.json
└── apps/
    └── app-1/
        ├── tsconfig.json
        ├── package.json
        └── test/
            └── tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows modern IDEs to detect the different configs per folder and correctly adapt to them. It also allows for shared/common TS options + custom ones per app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;First install &lt;code&gt;tsx&lt;/code&gt; and &lt;code&gt;glob&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use whatever package manager you prefer&lt;/span&gt;
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; tsx glob

&lt;span class="c"&gt;# For a single app in a monorepo&lt;/span&gt;
&lt;span class="c"&gt;# pnpm add -F your-app -D tsx glob&lt;/span&gt;

&lt;span class="c"&gt;# For the global package.json in a monorepo&lt;/span&gt;
&lt;span class="c"&gt;# pnpm add -wD tsx glob&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Environment variables
&lt;/h2&gt;

&lt;p&gt;Assuming you want environment variable control, create a &lt;code&gt;.env&lt;/code&gt; and a &lt;code&gt;.env.test&lt;/code&gt; at the root of the app you want to configure (optional, since Node throws an error if they don't exist, &lt;del&gt;&lt;a href="https://github.com/nodejs/node/pull/53060" rel="noopener noreferrer"&gt;although I'm working on it&lt;/a&gt;&lt;/del&gt; and you can use &lt;code&gt;--env-file-if-exists&lt;/code&gt; from Node 22.9.0 onwards in such cases).&lt;/p&gt;

&lt;h2&gt;
  
  
  Scripts
&lt;/h2&gt;

&lt;p&gt;Add this to your app's &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Node &amp;gt;=22.9.0 (if you want optionality for the &lt;code&gt;.env&lt;/code&gt; files)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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="err"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"glob -c &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;tsx --env-file-if-exists .env --env-file-if-exists .env.test --test --test-reporter spec &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./test/**/*.test.ts&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Node &amp;lt; 22.9.0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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="err"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"glob -c &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;tsx --env-file .env --env-file .env.test --test --test-reporter spec &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./test/**/*.test.ts&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What that &lt;code&gt;test&lt;/code&gt; script does is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;load your &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;.env.test&lt;/code&gt; files (the latter overwrites the former in case of conflict),&lt;/li&gt;
&lt;li&gt;asks &lt;code&gt;glob&lt;/code&gt; to process the &lt;code&gt;"./test/**/*.test.ts\"&lt;/code&gt; (which will load all Typescript files in the &lt;code&gt;./test&lt;/code&gt; folder ending in &lt;code&gt;.test.ts&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;runs the tests via &lt;code&gt;tsx&lt;/code&gt; with a human-readable output (&lt;code&gt;--test-reporter spec&lt;/code&gt;). This last step is equivalent to &lt;code&gt;node --import tsx --test&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  TS Configs
&lt;/h2&gt;

&lt;p&gt;Finally, adapt your &lt;code&gt;tsconfig.json&lt;/code&gt;s to include your tests if you want imports, linting and others:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;app&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="err"&gt;/tsconfig.json&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;Needed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;because&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;VS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;IDEs&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;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;it&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;decide&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;files&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;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;apply&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;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;config's&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rules&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;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"../../tsconfig.json"&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;Base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;monorepo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${configDir}/dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;already&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;present&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;in&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;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;config.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Otherwise&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;delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`compilerOptions`&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist"&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;"include"&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="s2"&gt;"./src/**/*"&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;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;app&lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="err"&gt;/test/tsconfig.json&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;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"../tsconfig.json"&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;Your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;app's&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;above).&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;also&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;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;monorepo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&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;"noEmit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowImportingTsExtensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;These&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;don't&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;work&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Runner&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;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Bun.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Purely&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;optional&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;QoL&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;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&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="nl"&gt;"paths"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"@src/*"&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="s2"&gt;"../src/*"&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="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;"include"&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="s2"&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;/div&gt;



&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;And that should be it, really. Hope it is of help when setting up your TypeScript testing environment!&lt;/p&gt;

&lt;p&gt;For more information on setup and other user's info, check &lt;a href="https://github.com/nodejs/help/issues/3902" rel="noopener noreferrer"&gt;this GitHub issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also made a &lt;a href="https://gist.github.com/BoscoDomingo/a06329ca1a2f36ccb7c168d4a8de6c92" rel="noopener noreferrer"&gt;GitHub Gist to go along with this guide&lt;/a&gt; which will probably be more up-to-date than this article. Check it out just in case!&lt;/p&gt;




&lt;h2&gt;
  
  
  Changelog
&lt;/h2&gt;

&lt;p&gt;&lt;u&gt;Update 2024-09-18&lt;/u&gt;: &lt;a href="https://github.com/nodejs/node/pull/53060" rel="noopener noreferrer"&gt;My PR adding &lt;code&gt;--env-file-if-exists&lt;/code&gt;&lt;/a&gt; landed and was released in Node 22.9.0, so if you are using any version equal or higher, you can use that new flag for the &lt;code&gt;env&lt;/code&gt; files! I've updated the post accordingly&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Update 2024-09-23&lt;/u&gt;: Updated the &lt;code&gt;tsconfig.json&lt;/code&gt;s to use a better structure based on my own experience:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I have come up with a better way for &lt;code&gt;tsconfig.json&lt;/code&gt;s setup, find it in the &lt;a href="https://gist.github.com/BoscoDomingo/a06329ca1a2f36ccb7c168d4a8de6c92" rel="noopener noreferrer"&gt;aforementioned Gist&lt;/a&gt;. The reason for this is having the &lt;code&gt;baseUrl&lt;/code&gt; and &lt;code&gt;paths&lt;/code&gt; set up in your &lt;code&gt;tsconfig.json&lt;/code&gt; will also affect imports in the source code, which doesn't work with Node (but does with Bun) plus it works better to have a base &lt;code&gt;app/tsconfig.json&lt;/code&gt; and a &lt;code&gt;app/test/tsconfig.json&lt;/code&gt; (at least with VS Code). &lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>testing</category>
      <category>node</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
