<?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>DEV Community: Michael Mathews</title>
    <description>The latest articles on DEV Community by Michael Mathews (@micmath).</description>
    <link>https://dev.to/micmath</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%2F932075%2F1af62e80-1975-422b-8b1d-24c72c9a5a33.jpeg</url>
      <title>DEV Community: Michael Mathews</title>
      <link>https://dev.to/micmath</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/micmath"/>
    <language>en</language>
    <item>
      <title>Clickable Card Patterns and Anti-Patterns</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Tue, 16 Dec 2025 13:04:18 +0000</pubDate>
      <link>https://dev.to/micmath/clickable-card-patterns-and-anti-patterns-2hl2</link>
      <guid>https://dev.to/micmath/clickable-card-patterns-and-anti-patterns-2hl2</guid>
      <description>&lt;p&gt;A frequent design requirement is to maximize the interaction area by making an &lt;strong&gt;entire card container clickable&lt;/strong&gt;, for example, linking to a detail page.&lt;/p&gt;

&lt;p&gt;However, when this approach is combined with card text that itself may contain links (such as to an author's profile, category tags, or action buttons), it creates a conflict that violates HTML semantics and could compromise accessibility.&lt;/p&gt;

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

&lt;p&gt;The core of the problem lies in attempting to nest interactive content. Consider the following structure used to make a card fully clickable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- ⚠️ Don't do this --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/article/card-detail"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Author: &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/authors/jamil"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Jamil&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure is problematic for at least two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The HTML Specification:&lt;/strong&gt; A hyperlink (an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; element that has an &lt;code&gt;href&lt;/code&gt; attribute) is &lt;strong&gt;interactive content&lt;/strong&gt;. According to the HTML Living Standard, an interactive element must not contain other interactive or focusable elements as descendants, which effectively prohibits a hyperlink from containing elements like &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, or another &lt;code&gt;&amp;lt;a href="…"&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assistive Tech Trip-Ups:&lt;/strong&gt; For users relying on screen readers or keyboard navigation, this nesting creates confusion and redundancy. Assistive technologies encounter two different links with overlapping hit areas. Tabbing behavior becomes unpredictable, and the link name (as read out by screen readers) becomes the card's entire contents. Not great!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Use the Stretched Link Pattern
&lt;/h2&gt;

&lt;p&gt;The recommended approach to achieving a fully clickable card—while maintaining semantic validity and good accessibility—is to use the &lt;strong&gt;Stretched Link Pattern&lt;/strong&gt;, which leverages CSS positioning and stacking context (&lt;code&gt;z-index&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The goal is to ensure that only the primary element (e.g., the card title) is wrapped in the "more information" link, and then use CSS to expand its hit area to cover the entire card, deliberately positioning other interactive elements above it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Semantic HTML Structure
&lt;/h3&gt;

&lt;p&gt;The recommended structure keeps the primary link and secondary interactive elements separate and non-nested.&lt;br&gt;
&lt;/p&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;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- 💁‍♂️ Use this as the primary link for the whole card. --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/article/card-detail"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__main-link"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Article Title&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"article-thumb.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Article Thumbnail"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- 👇 More links may be in the body of the card. --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Author: &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/authors/jamil"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Jamil&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;.&lt;span class="nt"&gt;&amp;lt;/p&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;h3&gt;
  
  
  2. CSS Implementation: Stacking Context Management
&lt;/h3&gt;

&lt;p&gt;We use &lt;code&gt;position: absolute&lt;/code&gt; and &lt;code&gt;z-index&lt;/code&gt; to manage layer order, ensuring the stretched link remains visually active while internal links retain interaction priority.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;Key CSS Properties&lt;/th&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.card&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;position: relative;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Establishes the stacking context for absolute children.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.card__main-link::after&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;content: '';&lt;/code&gt; &lt;code&gt;position: absolute;&lt;/code&gt; &lt;code&gt;inset: 0;&lt;/code&gt; &lt;code&gt;z-index: 1;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Stretches the (invisible) link across the whole card to act as the primary click target.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inner Interactive Elements (&lt;code&gt;a&lt;/code&gt;, &lt;code&gt;button&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;position: relative;&lt;/code&gt; &lt;code&gt;z-index: 2;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Lifts these elements &lt;em&gt;above&lt;/em&gt; the stretched link's hit area, preserving their intended functionality and focus order.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* 1. The parent element context */&lt;/span&gt;
&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="c"&gt;/* Other styles (border, padding, etc.) */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* 2. The stretched click area */&lt;/span&gt;
&lt;span class="nc"&gt;.card__main-link&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&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="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Less than the inner interactive elements */&lt;/span&gt;
  &lt;span class="nl"&gt;pointer-events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* 3. Priority for Internal Interactive Elements */&lt;/span&gt;
&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Above the stretched click area */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Using the Stretched Link Pattern resolves the conflict between design intent (making the card itself fully clickable) and technical compliance (avoiding nested interactive elements).&lt;/p&gt;

&lt;p&gt;By prioritizing correct HTML semantics and managing the stacking context, developers and designers can ensure that components are robust, fully accessible, and provide a predictable user experience.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://www.pexels.com/@gabby-k/" rel="noopener noreferrer"&gt;gabby-k&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>html</category>
      <category>uidesign</category>
    </item>
    <item>
      <title>Who Needs CSP?</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Mon, 01 Dec 2025 11:04:50 +0000</pubDate>
      <link>https://dev.to/micmath/who-needs-csp-1dmb</link>
      <guid>https://dev.to/micmath/who-needs-csp-1dmb</guid>
      <description>&lt;p&gt;You've probably heard about &lt;a href="https://web.dev/articles/csp" rel="noopener noreferrer"&gt;Content Security Policy (CSP)&lt;/a&gt; in the context of web security. But what is CSP for, and is it appropriate for your project?&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Content Security Policy (CSP)?
&lt;/h2&gt;

&lt;p&gt;At its core, CSP is a set of security practices and a standard that can be used to tell browsers which resources your website will be allowed to load and execute. Think of it as a security guard standing at the front door of your web page—it only lets scripts, styles, and other resources inside &lt;em&gt;if&lt;/em&gt; they are on the guest list.&lt;/p&gt;

&lt;p&gt;The way you tell the web browser which resources are considered safe to allow in is with a &lt;code&gt;Content-Security-Policy&lt;/code&gt; HTTP header. An example CSP configuration heading might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.google.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration tells the browser: "By default, only load resources from my own domain (&lt;code&gt;self&lt;/code&gt;), and any scripts must come from my domain or Google's API server." It also blocks &lt;em&gt;any&lt;/em&gt; inline CSS and JS from running.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Security Problem CSP Solves
&lt;/h2&gt;

&lt;p&gt;CSP is primarily intended to protect against &lt;a href="https://owasp.org/www-community/attacks/xss/" rel="noopener noreferrer"&gt;XSS (Cross-Site Scripting) attacks&lt;/a&gt;. This class of attack occurs when a hacker injects malicious code into your web page. &lt;/p&gt;

&lt;p&gt;For example, without CSP, if a baddie injects &lt;code&gt;&amp;lt;script&amp;gt;stealAllYourUserData()&amp;lt;/script&amp;gt;&lt;/code&gt; into your web page's source code, the browser will execute it, the same as if you wrote that code yourself. But with CSP, the browser must first check whether the script originated from a pre-approved source; if not, it blocks it, preventing the hacker's code from running.&lt;/p&gt;

&lt;h3&gt;
  
  
  XSS Examples
&lt;/h3&gt;

&lt;p&gt;There are &lt;em&gt;lots of&lt;/em&gt; ways that a user could (intentionally or not) inject JS or CSS into an unprotected webpage. XSS is a possibility in any place where a user can submit content that is later displayed on your page. Some examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Comment sections, forum posts, and reviews&lt;/strong&gt; where HTML or markdown is not filtered effectively/escaped.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;User profiles&lt;/strong&gt; with custom bios, display names, or avatars that allow HTML/JS.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;File uploads&lt;/strong&gt; where SVGs (which can contain script) or text files are served as HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CSP Benefits and Trade-offs
&lt;/h2&gt;

&lt;p&gt;You may say, "But if I'm already super careful about not allowing arbitrary user code to appear in my web page, why do I need CSP as yet another layer of security?" It's a fair question.&lt;/p&gt;

&lt;p&gt;Think of CSP like seatbelts in cars. Even if you drive carefully (secure coding), maintain your vehicle (input validation), and follow traffic rules (authentication), you still wear a seatbelt (CSP) because accidents sometimes happen for reasons beyond your control. Using CSP adds another safety net in case something goes wrong unexpectedly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do You Need CSP for Your Website
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Likely yes if your website:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handles sensitive data&lt;/strong&gt;, such as financial, medical, and personal information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allows user-generated content&lt;/strong&gt;, for example, comments, posts, rich text editors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses many third-party scripts&lt;/strong&gt;, such as analytics, ads, widgets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is a high-value target&lt;/strong&gt;, such as e-commerce, banking, social platform&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Maybe not if your website:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Is a simple static site&lt;/strong&gt;, for example, a static blog, portfolio, or documentation site&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Has no user-generated content&lt;/strong&gt;, never displays user comments, for example&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Has no third-party included content&lt;/strong&gt;, for example, analytics, font, or ad services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are building internal tools&lt;/strong&gt; with limited exposure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are early in development&lt;/strong&gt;, such as a prototype, and you intend to reassess your vulnerabilities before moving to production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But honestly, there aren't many good reasons not to take security as seriously as possible these days. My advice is to be smart and be safe!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The basic goal of CSP is to use the HTTP header to authorise the resources your web page is allowed to use. So you will need to configure your web server to add a &lt;code&gt;Content-Security-Policy&lt;/code&gt; header to your HTML response.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Start Simply
&lt;/h3&gt;

&lt;p&gt;The following policy allows the page to load and execute resources (including scripts and styles) only from the same origin (domain) as the HTML document. It blocks inline scripts and styles unless you explicitly relax it with additional unsafe directives such as &lt;code&gt;script-src 'unsafe-inline'&lt;/code&gt; or &lt;code&gt;style-src 'unsafe-inline'&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Content-Security-Policy: default-src 'self'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's (very) possible to accidentally exclude legitimate resources with a CSP header, so be sure to thoroughly test your site before publishing security restrictions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use Report-Only Mode First
&lt;/h3&gt;

&lt;p&gt;Deploy in monitoring mode to see what would break:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-reports
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Gradually Add More Complex Restrictions
&lt;/h3&gt;

&lt;p&gt;Once you've identified and fixed any initial issues, switch to enforcement mode and slowly add more complex rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Focus on the Biggest Risks
&lt;/h3&gt;

&lt;p&gt;Prioritize &lt;code&gt;script-src&lt;/code&gt; and &lt;code&gt;style-src&lt;/code&gt; directives first since these are where most XSS vulnerabilities happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Basic Starter CSP
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: 
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this does:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Allows resources only from your own domain (&lt;code&gt;'self'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Blocks any inline scripts and styles (which could be injected via XSS attacks)&lt;/li&gt;
&lt;li&gt;Allows images from your domain, data URLs, and any HTTPS source&lt;/li&gt;
&lt;li&gt;Prevents connections to any external APIs except your own&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Handling Inline CSS/JS
&lt;/h2&gt;

&lt;p&gt;Adding &lt;code&gt;default-src 'self'&lt;/code&gt; not only blocks any external domains—such as popular CDNs, analytics, fonts, etc.—it also blocks all &lt;strong&gt;inline&lt;/strong&gt; CSS and JS code. If you need to allow inline CSS or JS, there are two possible approaches: hashes (best for static sites) or nonces (for dynamically generated sites).&lt;/p&gt;

&lt;p&gt;💁‍♂️ Technically, you &lt;em&gt;could&lt;/em&gt; add &lt;code&gt;script-src 'unsafe-inline'&lt;/code&gt; to, for example, allow any inline JS to execute, but that would completely defeat the whole purpose of CSP, so obviously, don't do that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Using Hashes (Best for Static Sites)
&lt;/h3&gt;

&lt;p&gt;First, identify your critical inline code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Critical above-the-fold CSS --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.hero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;/* ... more critical styles */&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Essential initialization script --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APP_CONFIG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calculate the SHA-256 hashes for each inline code and include them in your CSP header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'sha256-abc123...';
  style-src 'self' 'sha256-def456...';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember, once you generate a hash for a string of CSS or JS, changing even a single character of the code requires you to regenerate the hash and update the header again. If you rarely modify inline code or have an automated system to handle it for you, this might not be a problem, but it does introduce a footgun that might surprise someone (in a bad way) later on when they "just need to make a quick change" to your code.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to generate hashes
&lt;/h4&gt;

&lt;p&gt;Assuming you have decided to add a hash to your CSP header to authorize some inline JS, you can use any tool capable of making &lt;code&gt;sha256&lt;/code&gt; hashes of strings, such as &lt;a href="https://formulae.brew.sh/formula/openssl@3" rel="noopener noreferrer"&gt;openssl&lt;/a&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;# For a script: &amp;lt;script&amp;gt;alert('Hello');&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"alert('Hello');"&lt;/span&gt; | openssl dgst &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-binary&lt;/span&gt; | openssl &lt;span class="nb"&gt;base64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces the hash &lt;code&gt;gKHd+pSZOJ3MwBsFalomyNobAcinjJ44ArqbIKlcniQ=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You would then add the following to your CSP header to allow the browser to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;script-src 'self' 'sha256-gKHd+pSZOJ3MwBsFalomyNobAcinjJ44ArqbIKlcniQ=';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ideally, this would be set up to happen automatically during your build process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Using Nonces (Dynamic Sites)
&lt;/h3&gt;

&lt;p&gt;Using a nonce makes more sense if you have blocks of inline code you want to allow, but that may change frequently, are dynamic, or differ on every page, and generating a hash for every page is too onerous.&lt;/p&gt;

&lt;p&gt;Instead, you could configure your server to generate a unique nonce, any hard-to-guess string that is different for each request. Your server would add that value to each &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag you want to safelist (regardless of its contents), and include the nonce in the HTTP headers.&lt;br&gt;
&lt;/p&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;style &lt;/span&gt;&lt;span class="na"&gt;nonce=&lt;/span&gt;&lt;span class="s"&gt;"cryptoR4nd0m123"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* Any CSS in here to be considered safe */&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;nonce=&lt;/span&gt;&lt;span class="s"&gt;"cryptoR4nd0m123"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// Any JS in here to be considered safe&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;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 http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'nonce-cryptoR4nd0m123';
  style-src 'self' 'nonce-cryptoR4nd0m123';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember, a nonce is not just hard to guess (like a password); it must also be &lt;strong&gt;unique&lt;/strong&gt; for every single page view. Otherwise, a hacker could just hit "view source", copy whatever nonce they find, and inject their baddie code with that same &lt;code&gt;nonce&lt;/code&gt; value. By making the value unique per view, knowing an already-used nonce is useless to the hacker. &lt;/p&gt;

&lt;p&gt;The nonce approach is arguably more straightforward and performant than hashes because there is no hash generation involved, but having to modify the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; with a unique &lt;code&gt;nonce&lt;/code&gt; attribute for every page view will destroy any server-side &lt;strong&gt;caching&lt;/strong&gt; strategy you may have in place. It also means you cannot serve static web pages at all, since, by definition, a nonce is never repeated from one page view to the next.&lt;/p&gt;

&lt;p&gt;When you need server-side caching or static HTML, the hash method is your better option.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Basic Protection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Some External Resources and Inline Resources
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'sha256-abc123...' https://www.google-analytics.com https://cdnjs.cloudflare.com;
  style-src 'self' 'sha256-def456...' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' data: https: https://www.google-analytics.com;
  connect-src 'self' https://api.example.com
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Move to Stricter Protection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: 
  default-src 'none';
  script-src 'self' 'sha256-abc123...';
  style-src 'self' 'sha256-def456...';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Development vs Production
&lt;/h2&gt;

&lt;p&gt;You will likely find that you need different security policies when developing than when in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development&lt;/strong&gt; (more permissive):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy-Report-Only: 
  default-src 'self';
  script-src 'self' 'unsafe-eval';  # For hot reloading
  style-src 'self' 'unsafe-inline'; # For development convenience
  report-uri /csp-reports
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Production&lt;/strong&gt; (more restrictive):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'sha256-abc123...';
  style-src 'self' 'sha256-def456...';
  img-src 'self' data: https:;
  font-src 'self'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example: Adding CSP to an AWS CloudFront Response Headers Policy
&lt;/h2&gt;

&lt;p&gt;This is a basic, straightforward approach if you are using CloudFront content distribution caching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Response Headers Policy
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;AWS Console → CloudFront → Policies → Response headers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Click &lt;strong&gt;"Create response headers policy"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Configure a basic CSP that says only CSS and JS from files on the same domain are allowed:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-awesome-csp-policy&lt;/span&gt;
  &lt;span class="na"&gt;Headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Content-Security-Policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
        &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default-src&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'self';&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;script-src&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'self';&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;style-src&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'self'"&lt;/span&gt;
        &lt;span class="na"&gt;Override&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this will tell the browser not to run any &lt;em&gt;inline&lt;/em&gt; CSS or JS, and to allow such resources only from files hosted on the same domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Attach Policy to Specific Cache Behaviors
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;CloudFront → Distributions → Your Distribution&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Go to the &lt;strong&gt;Behaviors&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt; Edit the specific path pattern (e.g., &lt;code&gt;/*&lt;/code&gt;, &lt;code&gt;/secure/*&lt;/code&gt;, or &lt;code&gt;/checkout&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt; In &lt;strong&gt;Response headers policy&lt;/strong&gt;, select your CSP policy, "my-awesome-csp-policy" in this example&lt;/li&gt;
&lt;li&gt; Save changes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Only requests matching that path pattern will get the CSP header.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is CSP a Silver Bullet to Prevent All XSS?
&lt;/h2&gt;

&lt;p&gt;Nope. There are still plenty of ways a user &lt;em&gt;could&lt;/em&gt; inject code to run in your web page if you aren't careful. For example, if you assume that strings in a browser cookie, in the url, or from an API endpoint are "safe" and evaluate them or write them to the document with JavaScript, congratulations: you've just opened a door to XSS that CSP can't protect you from.&lt;/p&gt;

&lt;p&gt;The point is, adding CSP defences doesn't mean you can stop thinking about XSS. It's still a hard problem, and it's still your responsibility.&lt;/p&gt;

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

&lt;p&gt;Determine whether your specific use case requires CSP and whether the trade-offs are justified. Consider CSP another layer of your website defence strategy; don't neglect other methods to prevent unauthorized content injection. For your first effort using CSP, begin with a minimal configuration that blocks inline scripts and styles. If you need inline code (for performance reasons, for example), use hashes for specific, verified content. This approach will give you 80% of the security benefits at 20% of the complexity.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;photo credit: &lt;a href="https://www.pexels.com/@rulomx/" rel="noopener noreferrer"&gt;Rulo Davila&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Do You Need A Cookie Notice If You Don't Use Cookies?</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Tue, 18 Nov 2025 16:25:19 +0000</pubDate>
      <link>https://dev.to/micmath/do-you-need-a-cookie-notice-if-you-dont-use-cookies-3d3c</link>
      <guid>https://dev.to/micmath/do-you-need-a-cookie-notice-if-you-dont-use-cookies-3d3c</guid>
      <description>&lt;p&gt;Ever wondered, "If my website doesn't use cookies, do I actually need a cookie notice?" The answer to that is &lt;em&gt;maybe&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It's a myth that the EU Privacy and Electronic Communications Directive, also known as the ePrivacy Directive (ePD), applies &lt;strong&gt;only&lt;/strong&gt; to cookies. It's much more comprehensive than that.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s not (only) about cookies
&lt;/h2&gt;

&lt;p&gt;Firstly, don't call it the "cookie law." The ePD is not a law, and the original text did not even mention cookies.&lt;/p&gt;

&lt;p&gt;As a &lt;em&gt;directive&lt;/em&gt;, the ePD is not directly enforceable. Instead, it directs EU Member States to meet a set of specific goals without dictating how they do so; It is up to each EU country to pass its own laws to comply with the ePD's requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing or accessing information in the user's terminal equipment
&lt;/h2&gt;

&lt;p&gt;The section of the original directive that applies to the subject of this article does not mention cookies; it states only that…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"… the storing of information, or the gaining of access to information already stored, in the terminal equipment [such as web browsers or mobile devices] of a subscriber or user is only allowed on condition that the subscriber or user concerned has given his or her consent, having been provided with clear and comprehensive information…"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In 2009, the ePD was amended to specifically mention cookies and "similar tracking technologies," but it was not only about cookies.&lt;/p&gt;

&lt;p&gt;The ePD works alongside the General Data Protection Regulation (GDPR), which concerns the protection of users' privacy. If you are storing or transmitting personally identifiable information, that regulation may apply to you as well.&lt;/p&gt;

&lt;p&gt;While the use of cookies is the most well-known target of ePD-related regulations, they apply to &lt;em&gt;any technology&lt;/em&gt; that stores or accesses information on a user’s device.&lt;/p&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tracking Pixels:&lt;/strong&gt; Using invisible images to include information that instructs the user's device (browser or email client) to send data (e.g., an email open, page view, or IP address) to a remote server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local/Web Storage:&lt;/strong&gt; Storing and/or accessing data in the user's browser, such as with &lt;code&gt;localStorage&lt;/code&gt; via JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device Fingerprinting:&lt;/strong&gt; Compiling a unique(ish) identifier by reading the user's device characteristics (like browser plugins, hardware specs, screen resolution, installed fonts, etc.), typically used to track that ID across web pages or sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Not all data is the same
&lt;/h2&gt;

&lt;p&gt;If your site accesses or stores user data for analytics, marketing, or personalization, &lt;strong&gt;you need explicit prior consent&lt;/strong&gt; from the user, even if you never drop a single cookie.&lt;/p&gt;

&lt;p&gt;But the law recognizes different categories of data, based on their purpose.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Strictly Necessary&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Required for core website functionality&lt;/td&gt;
&lt;td&gt;Keeping you logged in as you move between web pages or remembering items in your shopping basket.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Analytics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Track website usage&lt;/td&gt;
&lt;td&gt;Recording how often you visit the site, possibly with device and location characteristics.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Marketing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Show relevant ads&lt;/td&gt;
&lt;td&gt;Displaying an ad for a product you recently viewed on a different site.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Personalization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Remember your settings&lt;/td&gt;
&lt;td&gt;The site remembers and uses your language or currency settings each time you visit.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If your website &lt;strong&gt;only&lt;/strong&gt; stores and accesses data on the user's machine for strictly necessary reasons—meaning to deliver the core service the user requested—you do not need a cookie consent banner.&lt;/p&gt;

&lt;p&gt;Examples of data access and storage that generally &lt;strong&gt;do not&lt;/strong&gt; need consent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Session management (e.g., keeping a user logged in as they move around your website).&lt;/li&gt;
&lt;li&gt;  Security tokens (e.g., protecting the user from fraud during checkout).&lt;/li&gt;
&lt;li&gt;  Remembering what is in a shopping cart.&lt;/li&gt;
&lt;li&gt;  Saving the user’s preference regarding their consent to the privacy notice itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, if you use products such as Google Analytics (even in cookieless mode), Facebook Pixels, or YouTube embeds, you are processing data beyond "strictly necessary." In these cases, you must first alert the user and obtain their consent.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if my website is not in the EU?
&lt;/h2&gt;

&lt;p&gt;The ePD applies based on the user's location, not the website. If you offer any services, process data, or allow sign-ups within the EU, you must comply, regardless of where your servers or your company are based.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick compliance checklist for 2025
&lt;/h2&gt;

&lt;p&gt;To ensure your site is compliant with applicable data tracking requirements, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Audit your stack:&lt;/strong&gt; Identify every script running on your site, including third-party plugins.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Block by default:&lt;/strong&gt; Ensure all non-essential tracking (Analytics, Ads) is paused until the user clicks "Accept."&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Categorize consent:&lt;/strong&gt; Offer granular options (Analytics vs. Marketing, for example) rather than a single "Accept All" button.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Avoid "Dark Patterns":&lt;/strong&gt; Do not use pre-ticked boxes. Acceptance by default does not constitute consent.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Enable easy withdrawal:&lt;/strong&gt; Ensure users can revoke consent (a "Reject" or "Manage Settings" button) as easily as they gave it.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  This might all change
&lt;/h2&gt;

&lt;p&gt;In November of 2025, some &lt;a href="https://blog.lukaszolejnik.com/european-commission-gdpr-modification-to-kill-cookie-consent-nightmare/" rel="noopener noreferrer"&gt;insiders are reporting&lt;/a&gt; that the rules governing how websites confirm user consent may be changing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"European Union is on a route to simplify the notorious rule that is annoying every EU citizen. Namely, the ever present "consent popups". You know them for sure as most people need to go through lots of clicks that are simply a waste of time."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea is that the web browser should record the user's consent (or rejection) and make that information available to each website.&lt;/p&gt;

&lt;h2&gt;
  
  
  In short
&lt;/h2&gt;

&lt;p&gt;"Cookieless" is not a loophole. If the user is in the EU and you store or access data on their device for purposes that are not &lt;strong&gt;strictly necessary&lt;/strong&gt;, you must get their consent; whether you use cookies or not.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;photo credit: &lt;a href="https://www.pexels.com/@jill-wellington-1638660/" rel="noopener noreferrer"&gt;Jill Wellington&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>privacy</category>
      <category>webdev</category>
    </item>
    <item>
      <title>HTML Meta Tags to Improve Sharing of your Webpages (and SEO)</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Fri, 07 Nov 2025 15:25:16 +0000</pubDate>
      <link>https://dev.to/micmath/html-meta-tags-to-improve-sharing-of-your-webpages-and-seo-3j6g</link>
      <guid>https://dev.to/micmath/html-meta-tags-to-improve-sharing-of-your-webpages-and-seo-3j6g</guid>
      <description>&lt;p&gt;If the (example) metadata about your website was:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Ultimate Guide to Making Sourdough Bread"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn the step-by-step process of creating a beautiful, crusty loaf of sourdough bread from scratch. We cover starters, folding, and baking."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pageUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-site.com/blog/sourdough-guide"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imageUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-site.com/images/sourdough-guide-1200x630.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imageWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1200"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imageHeight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"630"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imageAlt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A golden-brown, freshly baked loaf of sourdough bread on a cutting board."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"article"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"siteName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The Bread Kitchen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"twitterCardType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"summary_large_image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"twitterHandleSite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@BreadKitchen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"twitterHandleAuthor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ChefJane"&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;The template you could use to generate the optimal HTML would be:&lt;br&gt;
&lt;/p&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;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;data.title&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.description %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.title %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.description %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.type %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.pageUrl %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:site_name"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.siteName %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.imageUrl %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:width"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.imageWidth %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:height"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.imageHeight %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image:alt"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.imageAlt %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.twitterCardType %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:site"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.twitterHandleSite %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:creator"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.twitterHandleAuthor %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.title %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.description %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.imageUrl %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:image:alt"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= data.imageAlt %&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- other HEAD content here... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break that down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standard SEO Tags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Purpose &amp;amp; How It's Used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sets the title in the browser tab. It's also the main headline used by Google in search results listings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;meta name="description"&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;This is the snippet of text shown below the title in Google search results. It doesn't affect social cards, but it's crucial for SEO.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Open Graph (OG) Tags (Used by Facebook, LinkedIn, Pinterest)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Purpose &amp;amp; How It's Used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;og:title&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The headline of your share card. This is what users see first. If missing, platforms might grab your page's &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;og:description&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The summary text shown below the headline in the card. It's your "sales pitch" for the click.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;og:type&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The type of content you're sharing (e.g., &lt;code&gt;article&lt;/code&gt;, &lt;code&gt;website&lt;/code&gt;, &lt;code&gt;video.movie&lt;/code&gt;). This tells the platform how to categorize it in their system.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;og:url&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The canonical (one-and-only official) URL for the page. All shares and "likes" for this page will be grouped under this single URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;og:image&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;This is the URL for the image that will appear in the card.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;og:image:width&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;og:image:height&lt;/code&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Tells the platform the exact dimensions of your image. This helps them render the card faster and prevents the image from being cropped weirdly. (1200x630 is the standard).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;og:image:alt&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provides an accessible text description of the image for users with screen readers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;og:site_name&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Specifies the name of your overall website (e.g., "The Bread Kitchen"). It often appears as a small "via..." line on the card.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Twitter Card Tags (Used by X/Twitter)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Purpose &amp;amp; How It's Used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;twitter:card&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines the card type. &lt;code&gt;summary_large_image&lt;/code&gt; is the most popular, featuring a big image. &lt;code&gt;summary&lt;/code&gt; provides a small thumbnail.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;twitter:site&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;@username&lt;/code&gt; of your website's main Twitter account (e.g., &lt;code&gt;@BreadKitchen&lt;/code&gt;). This gets linked in the card.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;twitter:creator&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;@username&lt;/code&gt; of the content author (e.g., &lt;code&gt;@ChefJane&lt;/code&gt;). Great for giving credit to individual writers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;twitter:title&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The headline for the Twitter card. Overrides &lt;code&gt;og:title&lt;/code&gt; if present.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;twitter:description&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The summary text for the Twitter card. Overrides &lt;code&gt;og:description&lt;/code&gt; and should be kept under about 200 characters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;twitter:image&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The image for the Twitter card. Overrides &lt;code&gt;og:image&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;twitter:image:alt&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An accessible text description of the image specifically for Twitter.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Creating Share Links
&lt;/h2&gt;

&lt;p&gt;An example template is shown below. Replace the placeholders with URL-encoded values for your web page.&lt;br&gt;
&lt;/p&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;id=&lt;/span&gt;&lt;span class="s"&gt;"shareLinks"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; 
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://twitter.com/intent/tweet?url=[ENCODED_URL]&amp;amp;text=[ENCODED_TITLE]&amp;amp;via=[ENCODED_VIA]"&lt;/span&gt;
    &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"noopener"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Share on Twitter
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; 
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.facebook.com/sharer/sharer.php?u=[ENCODED_URL]"&lt;/span&gt;
    &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"noopener"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Share on Facebook
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; 
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.linkedin.com/shareArticle?mini=true&amp;amp;url=[ENCODED_URL]&amp;amp;title=[ENCODED_TITLE]"&lt;/span&gt;
    &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"noopener"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Share on LinkedIn
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; 
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:?subject=[ENCODED_TITLE]&amp;amp;body=Check%20out%20this%20article:%20[ENCODED_URL]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Share via Email
  &lt;span class="nt"&gt;&amp;lt;/a&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;p&gt;Use &lt;code&gt;target="_blank"&lt;/code&gt; and &lt;code&gt;rel="noopener"&lt;/code&gt; on your share link tags to open them in a new tab securely.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>html</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What We Mean When We Say "Native TypeScript Support"</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Wed, 27 Aug 2025 14:30:40 +0000</pubDate>
      <link>https://dev.to/micmath/what-we-mean-when-we-say-native-typescript-support-5al1</link>
      <guid>https://dev.to/micmath/what-we-mean-when-we-say-native-typescript-support-5al1</guid>
      <description>&lt;p&gt;If you’re using Node.js v23.6 or later, you probably know that you can now run TypeScript files directly, without having to apply &lt;code&gt;tsc&lt;/code&gt;, Babel, or other separate transpilation steps first.&lt;/p&gt;

&lt;p&gt;Some earlier versions of &lt;code&gt;node&lt;/code&gt; could do the same when you used flags like &lt;code&gt;--experimental-strip-types&lt;/code&gt;, but as of v23.6, the following will &lt;em&gt;just work&lt;/em&gt;, no flags required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node my-awesome-typescript-code.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, this appears to be Node.js gaining "native TypeScript support", and in a way, it has. However, that only means it can convert TypeScript into JavaScript on its own. It does &lt;em&gt;not&lt;/em&gt; mean Node understands or enforces TypeScript types at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Node Is Actually Doing
&lt;/h2&gt;

&lt;p&gt;When you run a &lt;code&gt;.ts&lt;/code&gt; file in Node 23.6+, here’s what happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Node removes TypeScript-specific syntax like &lt;code&gt;: string&lt;/code&gt;, &lt;code&gt;: number&lt;/code&gt;, &lt;code&gt;interface&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;What remains is plain old JavaScript.&lt;/li&gt;
&lt;li&gt;That JavaScript is what is actually executed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, for example, this TypeScript:&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;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&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;Is effectively turned into this before it gets executed:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&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;As a result, the &lt;em&gt;runtime&lt;/em&gt; will never see the &lt;code&gt;: string&lt;/code&gt; annotations in your original source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static Types vs Runtime Behaviour
&lt;/h2&gt;

&lt;p&gt;The core purpose of TypeScript is to add static type checking to the JavaScript developer experience. In other words, to help you and your tools (such as your IDE or the TypeScript compiler &lt;code&gt;tsc&lt;/code&gt;) understand and enforce type intentions in your code before it runs. This feature never happens during execution.&lt;/p&gt;

&lt;p&gt;This distinction matters because it’s easy to assume: “If Node can now run TypeScript, then TypeScript’s type checking must be happening inside Node.”&lt;/p&gt;

&lt;p&gt;Nope.&lt;/p&gt;

&lt;p&gt;TypeScript’s type checking is always compile-time only. It happens when you use &lt;code&gt;tsc&lt;/code&gt; or your editor’s language server, and its purpose is to catch mistakes during development.&lt;/p&gt;

&lt;p&gt;When the code is actually running, whether in Node.js or Deno, there are no type annotations and no type-checking.&lt;/p&gt;

&lt;p&gt;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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&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;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&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="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&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="c1"&gt;// compiles fine with "as any"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Node 23.6+, this runs without complaint, accepting the string "hello" as an argument annotated with &lt;code&gt;:number&lt;/code&gt;, and the output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Little Nuance
&lt;/h2&gt;

&lt;p&gt;Okay, while it's true that &lt;em&gt;type annotations&lt;/em&gt; are effectively stripped out at compile time, it's also true that some TypeScript language features &lt;em&gt;do&lt;/em&gt; make it into the runtime code. That's because TypeScript is more than just a type checker; it's also a transpiler that can convert some TypeScript-supported syntax into the equivalent JavaScript.&lt;/p&gt;

&lt;p&gt;Take the &lt;code&gt;enum&lt;/code&gt;, or &lt;a href="https://en.wikipedia.org/wiki/Enumerated_type" rel="noopener noreferrer"&gt;enumerated type&lt;/a&gt; syntax as an example. In TypeScript, &lt;code&gt;enum&lt;/code&gt;s are supported; you can write:&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;Colour&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Blue&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="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But not in JavaScript, so the TypeScript compiler will emit some equivalent JavaScript like this:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blue&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;Colour&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Colour&lt;/span&gt; &lt;span class="o"&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="nx"&gt;Colour&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the JavaScript that gets &lt;em&gt;executed&lt;/em&gt; now has an &lt;code&gt;enum&lt;/code&gt; shim added to it. This shim will do nothing to enforce types at runtime, however. It’s just syntactic sugar sprinkled in to support the TypeScript &lt;code&gt;enum&lt;/code&gt; in your source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What About Deno?
&lt;/h2&gt;

&lt;p&gt;Deno has long supported &lt;code&gt;.ts&lt;/code&gt; files directly, too, but the same story applies there: Deno removes type annotations before execution. It doesn’t enforce type safety at runtime either.&lt;/p&gt;

&lt;p&gt;As of v23.6, Node.js is essentially catching up to Deno’s convenience feature of having TypeScript transpilation built in and enabled by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  When You &lt;em&gt;Do&lt;/em&gt; Need Runtime Type Safety
&lt;/h2&gt;

&lt;p&gt;If you’re writing code that interacts with other systems &lt;em&gt;outside&lt;/em&gt; of your code, the biggest type-safety risk probably isn’t your own functions calling each other — TypeScript already helps with that at dev time. The more likely risk is unvalidated input from sources that TypeScript can't see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responses from HTTP requests&lt;/li&gt;
&lt;li&gt;JSON payloads&lt;/li&gt;
&lt;li&gt;Database queries&lt;/li&gt;
&lt;li&gt;Data returned from external API calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those cases, TypeScript won’t protect you; you’ll need &lt;em&gt;runtime validation&lt;/em&gt; libraries like &lt;a href="https://github.com/colinhacks/zod" rel="noopener noreferrer"&gt;Zod&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, with Zod:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&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;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&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;handleUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ↓ throws an error if input is not valid&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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="nx"&gt;validated&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;validated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if an API client returns &lt;code&gt;{ id: 42 }&lt;/code&gt;, Zod's runtime check will throw instead of silently letting a number through where a string is expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Node 23.6+ saves you from having to run a separate transpiler, but it doesn’t change what TypeScript is or does; Once your code is running, it’s still just plain old JavaScript.&lt;/p&gt;

&lt;p&gt;TypeScript is &lt;a href="https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals" rel="noopener noreferrer"&gt;intended to be&lt;/a&gt;, and remains, a &lt;em&gt;development-time safety net&lt;/em&gt;, not a runtime one.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What is the Impact of AI on Coding? What the METR Study Doesn't Show</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Sun, 13 Jul 2025 11:24:21 +0000</pubDate>
      <link>https://dev.to/micmath/what-is-the-impact-of-ai-on-coding-what-the-metr-study-doesnt-show-431b</link>
      <guid>https://dev.to/micmath/what-is-the-impact-of-ai-on-coding-what-the-metr-study-doesnt-show-431b</guid>
      <description>&lt;p&gt;There is something especially ironic about social media posts making blanket statements that are critical of people who make blanket statements about the usefulness of AI in coding. But we know that blanket statements are simplifications, and reality is never as cut-and-dried as a single eye-catching headline.&lt;/p&gt;

&lt;p&gt;In the wake of the recently published METR study [Becker, J., Rush, N., Barnes, B., &amp;amp; Rein, D. (2025). Measuring the impact of early-2025 AI on experienced open-source developer productivity. METR (Model Evaluation &amp;amp; Threat Research). &lt;a href="https://metr.org/Early_2025_AI_Experienced_OS_Devs_Study.pdf" rel="noopener noreferrer"&gt;https://metr.org/Early_2025_AI_Experienced_OS_Devs_Study.pdf&lt;/a&gt;], the oversimplified statement that AI will always increase coding productivity is widely being countered by the oversimplified statement that AI cannot increase productivity. My position is that neither claim is true. While that does not make for a very click-baity headline, I'd just like to ask that people consider some of the critically relevant details included in the METR study itself before they make up their minds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applies to experienced and highly-skilled developers only
&lt;/h2&gt;

&lt;p&gt;The study authors intentionally decided to "focus on highly skilled open-source developers" by "recruiting experienced engineers with years of expertise in the target repositories." They chose this focus, they said, because "there has been relatively less research in this setting." [&lt;em&gt;METR&lt;/em&gt;, page 3]&lt;/p&gt;

&lt;p&gt;But, as the study authors themselves caution, "our results are consistent with small greenfield projects or development in unfamiliar codebases seeing substantial speedup from AI assistance." [&lt;em&gt;METR&lt;/em&gt;, page 12]&lt;/p&gt;

&lt;p&gt;If you are a novice in the coding language or the project you are working on, then these study results do not apply to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does not apply to tasks the authors considered "unrepresentative of most software development work"
&lt;/h2&gt;

&lt;p&gt;The authors cite studys that found that for tasks that are, what I would call, fairly boilerplate, where the core effort is in actually remebering and physically typing the code, and where there is likely to be "a large amount of LLM training data," the use of AI showed a "65% increase in the rate of task requirements satisfied." [&lt;em&gt;METR&lt;/em&gt;, page 3]&lt;/p&gt;

&lt;p&gt;If the task you are working on is mostly about grinding out a lot of boilerplate code, then these study results do not apply to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the goal?
&lt;/h2&gt;

&lt;p&gt;A significant problem I have in this whole discussion is the definition of the goal, what the study authors call "developer productivity." Time to passing unit tests, measured in billable minutes, is obviously quite important in a setting where the goal is to ship features as fast (and, in the case of commercial projects, as economically) as possible. In that case, if you had a few novice developers tasked with churning out a lot of boilerplate code, then "Yay! AI!"&lt;/p&gt;

&lt;p&gt;On the other hand if your thinking were a little longer term, and you actually considered the skill growth of your developers to be as valuable as next week's profit margins, maybe you &lt;em&gt;want&lt;/em&gt; your team to spend longer manually researching well-known coding patterns and typing them out by hand; this could lead to deeper understanding, better future recall, and improved &lt;em&gt;longer term&lt;/em&gt; performance of the developer as a contributor to your enterprise.&lt;/p&gt;

&lt;p&gt;This is just one example, but my point is that we could draw opposite conclusions based on whether we are taking a shorter or longer-term view of how we define success. Using or not using AI could be considered equally good, depending on your goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Was there bias?
&lt;/h2&gt;

&lt;p&gt;A potential problem with the study was the author's stated goal of using "realistic" coding tasks to measure the effect of AI usage. To this end, they asked the developers themselves to select the tasks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Each developer provides a list of real issues in their repository to work on as part of this study. Issues are typically bug reports, feature requests, or work items used to coordinate development. They range from brief problem descriptions to detailed analyses and represent work ranging from minutes to hours."&lt;br&gt;
-- &lt;em&gt;METR&lt;/em&gt;, page 5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This, according to at least one of the (only 16) developers who participated in the study, influenced the types of tasks they selected, with the developer giving consideration to how the tasks might be affected by AI usage.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"There was a selection effect in which tasks I submitted to the study. (a) I didn't want to risk getting randomized to "no AI" on tasks that felt sufficiently important or daunting to do without AI assistence. [sic] (b) Neatly packaged and well-scoped tasks felt suitable for the study, large open-ended greenfield stuff felt harder to legibilize, [sic] so I didn't submit those tasks to study even though AI speed up might have been larger"&lt;br&gt;
-- Bloom, R. (@ruben_bloom). (2025, July 11). X.com post. &lt;a href="https://x.com/ruben_bloom/status/1943536052037390531" rel="noopener noreferrer"&gt;https://x.com/ruben_bloom/status/1943536052037390531&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This may or may not have skewed the results to some degree—I genuinely don't know—but it seems odd that in a study that took pains to carefully randomise some things, the pool of tasks for developers to work from was not better protected from possible bias.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I'm glad to see work like the &lt;em&gt;METR&lt;/em&gt; study being published. Having data to refer to when evaluating claims about the impact of AI on productivity in real-world scenarios is a nice change. But this is a start. It would be useful to go further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the outcome track based on the experience of the coder with the language and project?&lt;/li&gt;
&lt;li&gt;Does the complexity/creativity of the task have an effect; is AI more or less useful with tasks that are straightforward versus those that are more novel or require creative thinking?&lt;/li&gt;
&lt;li&gt;Is there a tradeoff where the developer benefits less from using AI, even if the work is completed more quickly? For example, when does the developer gain a lower level of understanding of the coding techniques provided by the AI?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Working with JavaScript Symbols</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Fri, 30 May 2025 10:48:09 +0000</pubDate>
      <link>https://dev.to/micmath/working-with-javascript-symbols-10k8</link>
      <guid>https://dev.to/micmath/working-with-javascript-symbols-10k8</guid>
      <description>&lt;p&gt;JavaScript Symbols represent a unique primitive data type introduced in ES6.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are JavaScript Symbols?
&lt;/h2&gt;

&lt;p&gt;A JavaScript symbol is &lt;a href="https://dev.to/micmath/understanding-primitives-in-javascript-gj2"&gt;a primitive data type&lt;/a&gt;, like numbers, strings, and booleans. However, symbols have the following distinguishing characteristic: each value returned from &lt;code&gt;Symbol()&lt;/code&gt; is guaranteed to be unique within that runtime context (e.g., the window, iframe, worker thread, or VM instance).&lt;/p&gt;

&lt;p&gt;Useful properties of symbols include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Are Unique&lt;/strong&gt;: Every symbol is unique within its runtime context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are Non-Enumerable&lt;/strong&gt;: By using a symbol for the name when adding a property to an object, you don't need to worry that the property will suddenly appear in any existing &lt;code&gt;for in&lt;/code&gt; loops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Won't be Automatically Type Converted&lt;/strong&gt;: JavaScript will throw an Error if you accidentally use a symbol in a way where, for example, it would be automatically converted to a string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are Immutable&lt;/strong&gt;: Like all JavaScript primitives, once a symbol value is created, that value cannot be changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to Use Symbols
&lt;/h2&gt;

&lt;p&gt;Symbols excel in several scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  Unique Property Keys to Avoid Naming Conflicts
&lt;/h3&gt;

&lt;p&gt;When building a library or working with legacy codebases, you might want to add new properties to existing objects without risking conflicts with existing (or future) properties added by users. Symbols, due to their inherent uniqueness, are perfect for this.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tag&lt;/span&gt;&lt;span class="dl"&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;setTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;setTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;admin&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="nx"&gt;user&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="c1"&gt;// 1&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// admin&lt;/span&gt;

&lt;span class="c1"&gt;// if a regular property "tag" is added it won't clash&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loggedIn&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// loggedIn&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// still "admin"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating Non-Enumerable Properties
&lt;/h3&gt;

&lt;p&gt;Properties that use symbols for their keys do not appear in &lt;code&gt;for...in&lt;/code&gt; loops or &lt;code&gt;Object.keys()&lt;/code&gt; results by default. This allows you to "hide" properties, perhaps for adding internal metadata, that shouldn't be part of an object's public interface.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idSymbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;statusSymbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test Object&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;idSymbol&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;xyz123&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;statusSymbol&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;regularProperty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I am enumerable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&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="s2"&gt;`  &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="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;obj&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// name: Test Object&lt;/span&gt;
&lt;span class="c1"&gt;// regularProperty: I am enumerable&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// [ 'name', 'regularProperty' ]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Unique Values for Constants
&lt;/h3&gt;

&lt;p&gt;Since symbols are guaranteed to be unique in their runtime context, they are perfect for defining keys to be used as constants where the actual value doesn't matter as much as its uniqueness.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;WARN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&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;logMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&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="s2"&gt;`Critical Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INFO&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;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Info: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ... other log levels&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;logMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Something went wrong!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&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="nf"&gt;logMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Application started.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating Symbols
&lt;/h2&gt;

&lt;p&gt;Creating symbols is straightforward using the global &lt;code&gt;Symbol()&lt;/code&gt; function, optionally with a description for better debugging. The description is particularly helpful as it appears when logging symbols.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mySymbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a description&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="nx"&gt;mySymbol&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Symbol(This is a description)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using Symbols as Object Property Keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just as when using any non-literal string value as a key for an object property, when using symbols as keys, you must use bracket notation. Dot notation, &lt;code&gt;object.propertyName&lt;/code&gt;, doesn't work for symbol keys because property names accessed via dot notation are treated as literal strings.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nameSymbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;nameSymbol&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Using bracket notation to define the property&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Accessing the property using the symbol&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="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;nameSymbol&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "Alice"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dynamically adding a property with a symbol key&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailSymbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;emailSymbol&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alice@example.com&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="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;emailSymbol&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "alice@example.com"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Converting Symbols to Strings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike other value types in JavaScript, a symbol cannot be automatically converted to another type. For example:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&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;world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sym&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;world&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="s2"&gt;hello &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// hello world (arr was converted to a string)&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;hello &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Cannot convert a Symbol value to a string&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converting symbols to a string requires explicit use of the &lt;code&gt;toString()&lt;/code&gt; method or the &lt;code&gt;String()&lt;/code&gt; constructor. The &lt;code&gt;description&lt;/code&gt; property (available in ES2019+) directly returns the description string provided during creation.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sym&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&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="nx"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// "Symbol(hello)"&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="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;     &lt;span class="c1"&gt;// "Symbol(hello)"&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="nx"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "hello"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This requirement for explicit conversion is one of the symbol's strengths; it prevents a whole class of bugs from arising from values being unintentionally converted to a different type in operations like concatenation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hidden Properties
&lt;/h2&gt;

&lt;p&gt;A useful feature of JavaScript symbols is their ability to create object properties that remain hidden from the usual object inspection methods. When you use symbols as property keys, for example, these properties don't appear in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Object.keys()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Object.getOwnPropertyNames()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;for...in&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JSON.stringify()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hidden nature allows developers to safely use symbols to attach metadata, internal state, or utility methods to objects without polluting the regular property namespace.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Public Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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;12345&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="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&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;inactive&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// [ 'name', 'value' ]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That said, this feature is more about preventing &lt;em&gt;unintentional&lt;/em&gt; access; symbols don't create private properties in the true sense of the word. Anyone can explicitly interrogate an object for property symbols if they really wish.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Public Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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;12345&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="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&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;inactive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;symbolKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOwnPropertySymbols&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;symbolKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;symKey&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;symKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;myObject&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;symKey&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Symbol(id): 12345&lt;/span&gt;
&lt;span class="c1"&gt;// Symbol(status): inactive&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Global Symbol Registry
&lt;/h2&gt;

&lt;p&gt;The global symbol registry provides a way to share symbols across different parts of your application. The global registry allows you to create and retrieve symbols using string keys, granting access to the same key again when it is needed in multiple locations.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Symbol.for()&lt;/code&gt; and &lt;code&gt;Symbol.keyFor()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;While &lt;code&gt;Symbol()&lt;/code&gt; creates a unique symbol every time, &lt;code&gt;Symbol.for(keyString)&lt;/code&gt; searches for an existing symbol with the given &lt;code&gt;keyString&lt;/code&gt; in the global symbol registry. If found, it returns that symbol; otherwise, it creates a new symbol with &lt;code&gt;keyString&lt;/code&gt;, stores it in the global registry, and returns it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Symbol.keyFor(symbol)&lt;/code&gt; does the reverse: it retrieves the string key associated with a global symbol from the registry.&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="c1"&gt;// Creating or retrieving a global symbol&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;globalSym1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app.uid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;globalSym2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app.uid&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="nx"&gt;globalSym1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;globalSym2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newSym&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app.uid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// not `for` so a brand new symbol&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="nx"&gt;globalSym1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;newSym&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false&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="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;globalSym1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "app.uid"&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="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newSym&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;     &lt;span class="c1"&gt;// undefined, not in the registry&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This global functionality is useful when you need consistent symbol references across different modules or even different execution contexts (e.g., iframes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Well-Known Symbols
&lt;/h2&gt;

&lt;p&gt;Well-known symbols are predefined symbols built into JavaScript that allow developers to customize how objects interact with core language features and operations. These symbols act as hooks into JavaScript's internal mechanisms, enabling you to define custom behavior for operations like iteration, type conversion, and instance checking.&lt;/p&gt;

&lt;p&gt;JavaScript includes a set of predefined &lt;strong&gt;well-known symbols&lt;/strong&gt;. These are static properties of the &lt;code&gt;Symbol&lt;/code&gt; object (e.g., &lt;code&gt;Symbol.iterator&lt;/code&gt;, &lt;code&gt;Symbol.toPrimitive&lt;/code&gt;, &lt;code&gt;Symbol.hasInstance&lt;/code&gt;). They allow developers to customize how objects behave with built-in JavaScript operations and methods.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;Symbol.iterator&lt;/code&gt; specifies the default iterator for an object, making it compatible with &lt;code&gt;for...of&lt;/code&gt; loops. &lt;code&gt;Symbol.hasInstance&lt;/code&gt; allows customization of the &lt;code&gt;instanceof&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;Here's an example of how to customize the &lt;code&gt;instanceof&lt;/code&gt; operator with &lt;code&gt;Symbol.hasInstance&lt;/code&gt;:&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="cm"&gt;/** An array of strings. */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;isListish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;List must be initialized with an array of strings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;isListish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// duck typing to decide if obj is a List&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// implement the instanceof protocol&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasInstance&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nf"&gt;isListish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr1&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;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&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;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr2&lt;/span&gt; &lt;span class="o"&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;one&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;two&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&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="nx"&gt;arr1&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&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="nx"&gt;arr2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true (array of strings)&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="nx"&gt;arr3&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false (array items are not strings)&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="nx"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// false (not an array)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More Use Cases and Patterns
&lt;/h2&gt;

&lt;p&gt;Symbols enable sophisticated programming patterns beyond basic property hiding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Custom Iterators with &lt;code&gt;Symbol.iterator&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Symbol.iterator&lt;/code&gt; is a well-known symbol that allows you to define custom iteration behavior for your objects, making them compatible with &lt;code&gt;for...of&lt;/code&gt; loops and the spread syntax (&lt;code&gt;...&lt;/code&gt;).&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Range&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// implement the iterator protocol&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&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;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myRange&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;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// using for...of&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;myRange&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="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1, 2, 3, 4 (on separate lines)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// using spread syntax&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbersArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;myRange&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="nx"&gt;numbersArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [ 1, 2, 3, 4 ]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Metaprogramming
&lt;/h3&gt;

&lt;p&gt;Symbols are useful in metaprogramming scenarios, particularly with Proxies or decorators. They provide stable, unique identifiers for storing metadata or internal logic that won't clash with regular object properties. This separation is crucial for frameworks or libraries that add functionality to user objects without visible side effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registries and Caching
&lt;/h3&gt;

&lt;p&gt;Symbols can create unique, hidden keys for caching mechanisms or registry patterns. By using symbols as keys (e.g., in &lt;code&gt;WeakMap&lt;/code&gt;s or as property names for cache storage), developers can create data structures isolated from user code but accessible to the implementing library. This offers stronger encapsulation than convention-based private property naming (like &lt;code&gt;_cacheKey&lt;/code&gt;).&lt;/p&gt;

</description>
    </item>
    <item>
      <title>JavaScript Variable Scope by Example</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Thu, 29 May 2025 21:34:57 +0000</pubDate>
      <link>https://dev.to/micmath/javascript-variable-scope-by-example-3970</link>
      <guid>https://dev.to/micmath/javascript-variable-scope-by-example-3970</guid>
      <description>&lt;p&gt;Variable scope is a fundamental concept that must be mastered in JavaScript. Knowing how &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, and &lt;code&gt;const&lt;/code&gt; behave, and how &lt;strong&gt;hoisting&lt;/strong&gt; and &lt;strong&gt;closure&lt;/strong&gt; affect access to variable values will allow you to write more fluent and predictable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Scope?
&lt;/h2&gt;

&lt;p&gt;In JavaScript, scope refers to the current context of execution in which values and expressions are "visible" or accessible.&lt;/p&gt;

&lt;p&gt;In JavaScript, there are two main types of scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Global scope&lt;/strong&gt;: Variables declared at the "top-level," outside any function or block.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local scope&lt;/strong&gt;: Variables declared inside a function or block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JavaScript also has the concept of &lt;strong&gt;lexical scoping&lt;/strong&gt;, which means that a function's access to variables is determined by where it is written in the code, not where it's called from. Inner functions can access variables from their outer (enclosing) functions, creating a nested "scope chain."&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, and &lt;code&gt;const&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;JavaScript provides three keywords for declaring variables: &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, and &lt;code&gt;const&lt;/code&gt;. Each has distinct scoping behaviors.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;var&lt;/code&gt;: Function Scope and Hoisting
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;var&lt;/code&gt; is function-scoped, which means it can be accessed anywhere within the function in which it is declared (even before its value is initialized). Or if it is used outside of a function, it is global. It is also &lt;strong&gt;hoisted&lt;/strong&gt;, meaning the code acts as if the declaration were moved to the top of its scope at runtime (but not the assignment).&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;f&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined (not ReferenceError)&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;f&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ReferenceError: x is not defined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, the declaration of &lt;code&gt;x&lt;/code&gt; is hoisted to the top of the function, so the first &lt;code&gt;console.log&lt;/code&gt; doesn’t throw an error, even though the value assignment hasn’t happened yet. Outside of the function, &lt;code&gt;x&lt;/code&gt; does not exist, so it will throw an error.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt;: Block Scope and Temporal Dead Zone
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; are block-scoped, meaning they are only accessible within the nearest set of &lt;code&gt;{}&lt;/code&gt; braces.&lt;/p&gt;

&lt;p&gt;Unlike &lt;code&gt;var&lt;/code&gt;, which hoists the variable declaration to the top of its scope, &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt; follow a model called The Temporal Dead Zone (TDZ). This refers to the scope between the start of a block and the point where the variable is declared. During this period, the variable exists but cannot be accessed; any attempt to do so will throw a &lt;code&gt;ReferenceError&lt;/code&gt;&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;demonstrateTdz&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&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="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ReferenceError: Cannot access 'y' before initialization&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1 2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;demonstrateTdz&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; helps avoid confusion caused by hoisting, making code more predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Block Scope Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&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="c1"&gt;// a is accessible here&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;b&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="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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&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="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are block-scoped, so they are not available &lt;em&gt;outside&lt;/em&gt; their enclosing block. &lt;code&gt;a&lt;/code&gt; is available to the &lt;em&gt;inner&lt;/em&gt; scope, however. &lt;code&gt;c&lt;/code&gt; is declared with &lt;code&gt;var&lt;/code&gt;, so it's scoped to the function it is declared in or, as in this case, the global scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closures
&lt;/h2&gt;

&lt;p&gt;A closure is a function scope that maintains access to the variables available in whatever scope it was defined in, regardless of where it is called from.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// from the outer scope&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;count&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeCounter&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="nf"&gt;counter&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;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="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Closures are fundamental in JavaScript and commonly used in web development, particularly in event handlers and asynchronous code.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;var&lt;/code&gt; is function-scoped or globally scoped and hoisted.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; are block-scoped and do not behave as if hoisted (&lt;code&gt;TDZ&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;const&lt;/code&gt; or &lt;code&gt;let&lt;/code&gt; to limit the scope of your variables and avoid hoisting.&lt;/li&gt;
&lt;li&gt;Scope and closures are key to many JavaScript patterns, including modules and callbacks.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Understanding Primitives in JavaScript</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Thu, 29 May 2025 15:48:11 +0000</pubDate>
      <link>https://dev.to/micmath/understanding-primitives-in-javascript-gj2</link>
      <guid>https://dev.to/micmath/understanding-primitives-in-javascript-gj2</guid>
      <description>&lt;p&gt;In JavaScript, every value is either a primitive or an object.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primitives are immutable, passed by value, and cannot have properties.&lt;/li&gt;
&lt;li&gt;Objects are everything else, including arrays, functions, dates, and regular objects. These are mutable and passed by reference. Objects can have properties and methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Meet the primitives
&lt;/h2&gt;

&lt;p&gt;The latest ECMAScript standard (ECMAScript 2024 / ES15) defines &lt;strong&gt;seven&lt;/strong&gt; primitive types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Undefined
&lt;/h3&gt;

&lt;p&gt;A variable that has been declared but not assigned a value has the &lt;code&gt;undefined&lt;/code&gt; value:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Null
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;null&lt;/code&gt; literal signifies the &lt;em&gt;intentional&lt;/em&gt; absence of any value:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reason&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// there is no reason&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="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Boolean
&lt;/h3&gt;

&lt;p&gt;Two Boolean literals represent logical truth values:&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="kc"&gt;true&lt;/span&gt;
&lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Number
&lt;/h3&gt;

&lt;p&gt;All numeric values (including integers, floats, &lt;code&gt;NaN&lt;/code&gt;, and &lt;code&gt;Infinity&lt;/code&gt;) are of the Number type:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&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="c1"&gt;// integer&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// float&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// yes, the "not a number" value is a number&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// and beyond!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  String
&lt;/h3&gt;

&lt;p&gt;A sequence of characters, such as some words or text:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Hi, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  BigInt
&lt;/h3&gt;

&lt;p&gt;Represents integers of arbitrary length, created by appending &lt;code&gt;n&lt;/code&gt; to the end of an integer literal:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1234567890123456789012345678901234567890&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Symbol
&lt;/h3&gt;

&lt;p&gt;A unique (within the runtime environment) value that can be used as object property keys:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sym&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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;h2&gt;
  
  
  What's your type?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;typeof&lt;/code&gt; operator returns a string indicating the operand type. There are seven possible return values for primitive types.&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="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="k"&gt;typeof&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// undefined&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="k"&gt;typeof&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;              &lt;span class="c1"&gt;// boolean&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="k"&gt;typeof&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// number&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="k"&gt;typeof&lt;/span&gt; &lt;span class="mi"&gt;9007199254740991&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// bigint&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="k"&gt;typeof&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// string&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;          &lt;span class="c1"&gt;// symbol&lt;/span&gt;

&lt;span class="c1"&gt;// and then there's null... read more below&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="k"&gt;typeof&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;              &lt;span class="c1"&gt;// object?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;null&lt;/code&gt; is a special case
&lt;/h3&gt;

&lt;p&gt;I want to call attention to a common point of confusion in JavaScript: the &lt;code&gt;null&lt;/code&gt; value. However, it is not an object and has no object wrapper. However, it blatantly lies and &lt;em&gt;claims&lt;/em&gt; to be an object when you use the &lt;code&gt;typeof&lt;/code&gt; operator on it.&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;nope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// object (no, it's not)&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="nx"&gt;nope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Cannot read properties of null (reading 'toString')&lt;/span&gt;
&lt;span class="nx"&gt;nope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&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="c1"&gt;// TypeError: Cannot set properties of null (setting 'x')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Brendan Eich, the Creator of JavaScript, admitted that &lt;code&gt;typeof null === "object"&lt;/code&gt; is a bug, but fixing it would break a lot of code on the web. So, we must always work around this bug.&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="c1"&gt;// randomly assign either an object or null&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// don't forget to check for null&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&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;The value is a (real) object.&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dressing primitives up like objects
&lt;/h2&gt;

&lt;p&gt;Primitive values are not objects. They are immutable and cannot have methods or properties. You might be surprised by this statement, after all, it's pretty standard to see code that &lt;em&gt;appears&lt;/em&gt; to call methods on and get/set properties on primitive values.&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="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;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// 5&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;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// HELLO&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="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;        &lt;span class="c1"&gt;// 10.00&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="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;        &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's happening here? The primitive types in the preceding example each have a corresponding object wrapper they can climb into whenever they need to do object-like things. For example, you can wrap a string primitive in a &lt;code&gt;String&lt;/code&gt; object by calling &lt;code&gt;new String("hello")&lt;/code&gt;. Think of the resulting object as a box with the primitive inside. You can always get the primitive value back by calling &lt;code&gt;valueOf&lt;/code&gt; on the object. &lt;/p&gt;

&lt;p&gt;JavaScript performs automatic "boxing" for you by temporarily wrapping any String, Number, or Boolean values in an object whenever you try to access properties or methods. For example, &lt;code&gt;"hello".toUpperCase()&lt;/code&gt; works because JavaScript creates a &lt;code&gt;String&lt;/code&gt; object behind the scenes before calling its &lt;code&gt;toUpperCase&lt;/code&gt; method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping primitives
&lt;/h3&gt;

&lt;p&gt;JavaScript doesn't always wrap primitives in Objects for you. For example, &lt;code&gt;undefined&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt; can't be wrapped.&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Cannot read properties of undefined (reading 'toString')&lt;/span&gt;
&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;      &lt;span class="c1"&gt;// TypeError: Cannot read properties of null (reading 'toString')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to force them into object boxes explicitly, their values disappear.&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="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// returns an empty object {}&lt;/span&gt;
&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// returns an empty object {}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Strings, Numbers, and Booleans have dedicated object wrappers you can call yourself if you wish. In practice, there are very few reasons for doing this, but you might find some APIs that &lt;em&gt;require&lt;/em&gt; objects when all you have are primitives, for example, when creating an entry in a WeakMap that requires an object for the key.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s&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;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// "object"&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="nx"&gt;s&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&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="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;         &lt;span class="c1"&gt;// "hello" (gets the primitive value)&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="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                   &lt;span class="c1"&gt;// calls valueOf for you &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, you can explicitly wrap numbers and booleans.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&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;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&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;b&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;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last two primitives don't have their own dedicated object wrapper but can be objectified using the &lt;code&gt;Object()&lt;/code&gt; function if you need to.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="nx"&gt;n&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// "object"&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="nx"&gt;big&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&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="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;         &lt;span class="c1"&gt;// "123n" (gets the primitive value)&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="nx"&gt;big&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                   &lt;span class="c1"&gt;// [BigInt: 123n] (calls toString)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sym&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key&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="nx"&gt;sym&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                   &lt;span class="c1"&gt;// [Symbol: Symbol(key)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Counting Stars with JavaScript: Using the BigInt Type</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Tue, 27 May 2025 16:21:05 +0000</pubDate>
      <link>https://dev.to/micmath/counting-the-stars-with-javascript-the-use-case-for-the-bigint-primitive-1be0</link>
      <guid>https://dev.to/micmath/counting-the-stars-with-javascript-the-use-case-for-the-bigint-primitive-1be0</guid>
      <description>&lt;p&gt;JavaScript's native &lt;code&gt;Number&lt;/code&gt; type is a 64-bit floating-point value (IEEE 754 double-precision). While this gives you a massive range, JavaScript integer Numbers are still limited. In JavaScript, integer values are only precise up to 2⁵³ - 1.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The number 2⁵³ represents the result you get when you multiply the number 2 by itself, 53 times in a row. So the maximum safe integer number is &lt;code&gt;2**53 - 1&lt;/code&gt; or 9,007,199,254,740,991, about nine quadrillion, give or take a few trillion.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But don't bother trying to remembering that number; JavaScript has helpfully given it an easy-to-recall name: &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt;.&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="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="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_SAFE_INTEGER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 9007199254740991&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the name implies, once you start working with integer Numbers larger than &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt;, you can't safely assume the accuracy of any result.&lt;/p&gt;

&lt;p&gt;There is also a corresponding &lt;code&gt;Number.MIN_SAFE_INTEGER&lt;/code&gt; value. It represents JavaScript's &lt;em&gt;smallest&lt;/em&gt; safe integer value, or -(2⁵³ - 1).&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="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="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MIN_SAFE_INTEGER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -9007199254740991&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By "safe," we mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accurately represented:&lt;/strong&gt; A safe integer won't get rounded to a different value due to insufficient precision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correctly compared:&lt;/strong&gt; Comparisons between safe integers will yield mathematically correct results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To illustrate, let's try something with a couple of &lt;em&gt;unsafe&lt;/em&gt; values and see how it can go mathematically wrong:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_SAFE_INTEGER&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="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true! (but not correct)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's the point?
&lt;/h2&gt;

&lt;p&gt;You might think, I'll just stick to numbers smaller than nine quadrillion -- it's a plenty big-enough number after all. That's true. In fact, if you ever tried to count up to 9 quadrillion, even at one number per second and without any breaks, it would take you about &lt;strong&gt;285 million&lt;/strong&gt; years!&lt;/p&gt;

&lt;p&gt;While working with such massive numbers is not typical, it wouldn't be &lt;em&gt;inconceivable&lt;/em&gt;. Here are a few examples of real integer values where &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt; isn't big enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  Genes in the human body
&lt;/h3&gt;

&lt;p&gt;The estimated number of gene copies in an adult human body (spread across our 30 to 40 trillion cells) is about 2 × 10¹⁸ (2 quintillion). &lt;code&gt;MAX_SAFE_INTEGER&lt;/code&gt; is &lt;strong&gt;222 times too small&lt;/strong&gt; to represent the number of gene copies in the human body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Milliseconds since the Big Bang
&lt;/h3&gt;

&lt;p&gt;The universe's age is about 13.8 billion years, or about 4.4 × 10²⁰ milliseconds (440 quintillion ms). &lt;code&gt;MAX_SAFE_INTEGER&lt;/code&gt; is about &lt;strong&gt;50,000 times too small&lt;/strong&gt; to represent the number of milliseconds since the dawn of time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stars in the observable universe
&lt;/h3&gt;

&lt;p&gt;The estimated number of stars in the observable universe is between 10²² and 10²⁴ (1 septillion). &lt;code&gt;MAX_SAFE_INTEGER&lt;/code&gt; is about &lt;strong&gt;100 million times too small&lt;/strong&gt; to represent the number of stars in the observable universe.&lt;/p&gt;

&lt;p&gt;So while &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt; is big, it's not big enough for some values in astronomy, geography, genetics, cryptography, or large financial systems. That's when we reach for the &lt;code&gt;BigInt&lt;/code&gt; primitive type. &lt;code&gt;BigInt&lt;/code&gt; can handle values &lt;em&gt;way&lt;/em&gt; beyond &lt;code&gt;Numbers&lt;/code&gt;'s 64-bit limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet &lt;code&gt;BigInt&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;BigInt&lt;/code&gt; is a primitive type introduced in ES2020 that can represent integers with &lt;strong&gt;arbitrary precision&lt;/strong&gt;. That means you can work with much larger integer values. There is no upper maximum specified for BigInt; the implementation of the JavaScript engine you use and the available memory on your machine are the only practical limits.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;BigInt&lt;/code&gt; value is created by appending the letter &lt;code&gt;n&lt;/code&gt; to the end of an integer literal or calling the &lt;code&gt;BigInt()&lt;/code&gt; function and giving it an integer or string value.&lt;/p&gt;

&lt;p&gt;Here's how it works:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_SAFE_INTEGER&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="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false, now works correctly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key characteristics
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Literal syntax&lt;/strong&gt;: Append &lt;code&gt;n&lt;/code&gt; to create a BigInt literal (&lt;code&gt;123n&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distinct Type&lt;/strong&gt;: It's one of the built-in primitive types in JavaScript (&lt;code&gt;typeof 1n&lt;/code&gt; returns &lt;code&gt;"bigint"&lt;/code&gt;). &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No decimals&lt;/strong&gt;: BigInt can only represent whole numbers (integers) (&lt;code&gt;BigInt(1.1)&lt;/code&gt; throws a &lt;code&gt;RangeError&lt;/code&gt;).
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;There are several limitations you must keep in mind when working with BigInt values.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON serialization
&lt;/h3&gt;

&lt;p&gt;BigInt values aren't supported in JSON.&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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: Do not know how to serialize a BigInt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integers only
&lt;/h3&gt;

&lt;p&gt;As the "Int" in the name implies, BigInt is for integers (whole numbers) only. If you forget about this limitation you might be surprised.&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="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="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10n&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="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3n (but not correct)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Don't mix
&lt;/h3&gt;

&lt;p&gt;BigInt values cannot be combined with regular Number values (&lt;code&gt;1n + 1&lt;/code&gt; is a TypeError, but &lt;code&gt;1n + 1n&lt;/code&gt; is okay).&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch your speed
&lt;/h3&gt;

&lt;p&gt;Expect code that uses BigInt values to be at least slightly slower than the same code using ordinary Numbers. This is because floating-point arithmetic (used by Number) is implemented directly in the computer hardware, while arbitrary-precision arithmetic, used by BigInt, is implemented in software. Your computer hardware is far faster than any software!&lt;/p&gt;

&lt;h2&gt;
  
  
  What about TypeScript?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;bigint&lt;/code&gt; type is fully supported in TypeScript, just like any other primitive type. However, you must set the &lt;code&gt;"target"&lt;/code&gt; property inside the &lt;code&gt;"compilerOptions"&lt;/code&gt; object in your &lt;code&gt;tsconfig.json&lt;/code&gt; file, to &lt;code&gt;"ES2020"&lt;/code&gt; or later.&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;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1234567890123456789012345678901234567890&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1234567890123456789012345678901234567890&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ERROR Type 'number' is not assignable to type 'bigint'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fun fact
&lt;/h2&gt;

&lt;p&gt;Reading long numerical values can be confusing for humans, if not for computers. By convention, we tend to add digit grouping characters to make them more readable. For example, a comma separates the thousands in long numbers in English-speaking countries, like "1,000,000". Other countries use different symbols; you might see that written as "1’000’000" in Switzerland and Liechtenstein, "1.000.000" in other European countries, or even "1 000 000" in some scientific settings.&lt;/p&gt;

&lt;p&gt;JavaScript supports using an underscore character to group digits. So while your computer has no problem understanding &lt;code&gt;1000000&lt;/code&gt;, you &lt;em&gt;can&lt;/em&gt; write &lt;code&gt;1_000_000&lt;/code&gt; instead if it's easier to read.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using Tuples in TypeScript</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Tue, 27 May 2025 11:39:13 +0000</pubDate>
      <link>https://dev.to/micmath/using-tuples-in-typescript-ao4</link>
      <guid>https://dev.to/micmath/using-tuples-in-typescript-ao4</guid>
      <description>&lt;p&gt;In TypeScript, a &lt;strong&gt;tuple&lt;/strong&gt; allows you to describe a structured array, where the &lt;em&gt;position&lt;/em&gt; of each element is meaningful and dictates what type each is expected to be.&lt;/p&gt;

&lt;p&gt;For example, you might use a tuple to store the data associated with a &lt;code&gt;User&lt;/code&gt; type. You could declare this type mandating that the first value in a &lt;code&gt;User&lt;/code&gt; tuple must be a number (representing the user's &lt;code&gt;id&lt;/code&gt;), and the second a string (representing their &lt;code&gt;displayName&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="c1"&gt;// Declaring a User type consisting of an array with&lt;/span&gt;
&lt;span class="c1"&gt;// a number at `[0]` followed by a string at `[1]`&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Alice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Bob&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ERROR Type 'string' is not assignable to type 'number'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;small&gt;&lt;a href="https://www.typescriptlang.org/play/?#code/PTAEBEFMGMBsEMBOBLAdgc1PUBVAzpIqAC4CeADpKNAPap7J7FqY0BmWqWii8poAd2TEAFgCgQWUKgCuAWwBGhLMVAADANoAGALprQbGrFg0BkACagF-bExQYV6jQEY9YspVwEiAXlAbZRUIAGlA7Fh0AbjExWnpVAEFYZGhIAC4vZT8XACYAZlCAciSUyEKo0EkAeQBpWLomUAAhGgUM-Cz-QpaFcsjKsABRACVhquHQABUKKkLwjELQRmkaVXg8BnRUeAVYKmIaEhnQQsClREKAOjEgA" rel="noopener noreferrer"&gt;try in playground&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;You could make this more explicit by using &lt;strong&gt;named tuple elements&lt;/strong&gt; in your type declaration. While the names make no functional difference, they will give you better hints in your IDE when you refer to an element in a tuple. For example, with named tuple elements, TypeScript can tell you that &lt;code&gt;Alice[1]&lt;/code&gt; refers to the &lt;code&gt;displayName&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&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="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Alice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// OK&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="nx"&gt;Alice&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="c1"&gt;// (property) 1: string (displayName)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;small&gt;&lt;a href="https://www.typescriptlang.org/play/?#code/C4TwDgpgBAqgzhATlAvFA2gSwCYC4oB2ArgLYBGSANFNpnGADYCGIAckyRPnMIpgQHMAugG4AUGIDGAewI8oAQQaZJXWAmRp0ARgBMAZmoByJSohHRUAPRWoAeQDSU2XGkMIAOgbSBAClOqOkIAlCLWtr5giNKQiKDBUNrcvPwCUL609MxsHBDBYkA" rel="noopener noreferrer"&gt;try in playground&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Tuples?
&lt;/h2&gt;

&lt;p&gt;You might wonder why anyone would use an array to hold structured data like this; wouldn't an object be a more natural choice?&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Alice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&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;While objects with explicit keys and values are generally considered more readable, there are legitimate use cases for using structured arrays instead. For example, if user data were read from a database or file, working with whatever format it was returned in might be more efficient rather than converting it to an object.&lt;/p&gt;

&lt;p&gt;Tuples are particularly useful for representing a small set of related, ordered values.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Coordinates: &lt;code&gt;[latitude: number, longitude: number]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;RGB color values: &lt;code&gt;[red: number, green: number, blue: number]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;API responses: &lt;code&gt;[status: number, message: string]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example Uses of Tuples in TypeScript:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Named Tuple Elements
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&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="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// OK&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="nx"&gt;user&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="c1"&gt;// (property) 0: number (id)&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="nx"&gt;user&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="c1"&gt;// (property) 1: string (displayName)&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&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;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ERROR Type 'string' is not assignable to type 'number'.&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ERROR Type '[number, string, boolean]' is not assignable to type 'User'. Source has 3 element(s) but target allows only 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;small&gt;&lt;a href="https://www.typescriptlang.org/play/?#code/C4TwDgpgBAqgzhATlAvFA2gSwCYC4oB2ArgLYBGSANFNpnGADYCGIAckyRPnMIpgQHMAugG4AUGIYRgUIgkT54SVBgCMAJgDM1AEQBBBpgDGEHaKgB6C1ADyAaQlGA9gThOpAOgZOBACjlI6AAMQgCUIpbWvmCITpCIoKFQQfjE5Mq+OKFizq7uEF4+-vLoqmERVlDRsfGJUKrcvPwCVbT0zGwcENliAcho6PqGJjrUGprmlQCiAEozNjNQACrg0ADkPHyCa1B0hE4yTHBwmAIETGRSUMBO16tQa2kUiGsevfIq6AAsAKwAbLoAEJOMija6IIgQSbWWbzRYrSAPdBPKhQTbNahkJz5JgEIQ7PYEA5QI4nM4XK43O6ItZKF4eKAAZScREQJigAAsjlBNFAIFJOARgL44EkyEQZMAmIgBNISQxvAB3OBQFwMEBQdRAA" rel="noopener noreferrer"&gt;try in playground&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional Tuple Elements
&lt;/h3&gt;

&lt;p&gt;You can make elements in a tuple optional by appending a &lt;code&gt;?&lt;/code&gt; to their type. Optional elements must come &lt;em&gt;after&lt;/em&gt; any required elements.&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;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&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;John&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;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&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;Jane&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;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&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;Jack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ERROR Type 'number' is not assignable to type 'string'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;small&gt;&lt;a href="https://www.typescriptlang.org/play/?#code/C4TwDgpgBAChBOBnA9gOygXigbQGYEslgA5AQwFsIAuKRYefVAcwBooAbUusymuh5m1JMIAfhqoAruQBGCALoBuAFDKAxmjpRISNAEYacXeizYARAClkAC1Rm2ZgCLIIZpVAD0HqAHkA0uqawNoIKKgATIahaJg4lqSorg7OSVAALOHuXr4BgahaOmEAzFHGseYWpGoA1vZQepmKnt4AogBKbT5tUAAq4NAA5FKyCANQ+IhQqMjBXIj4TKikMuzQwMhQoJBQA-yMTAMAdMpAA" rel="noopener noreferrer"&gt;try in playground&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Rest Elements in Tuple Types
&lt;/h3&gt;

&lt;p&gt;Rest elements allow you to define a tuple with some fixed elements at the beginning, followed by an unknown number of elements of a specific type.&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;type&lt;/span&gt; &lt;span class="nx"&gt;LogEntry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;timestamp&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;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INFO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;WARN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&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;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="c1"&gt;// NOTE Can be zero or more messages.&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;entry1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LogEntry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INFO&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User logged in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LogEntry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERROR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to connect to database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Network error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Retry attempts: 3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;small&gt;&lt;a href="https://www.typescriptlang.org/play/?#code/C4TwDgpgBAMg9gcwKIDtgCcRQLxQNoBQUUwAlgLYQDOwAhuWAFxQoCu5ARhOgDRFQAbCADcIA5gHIAkgDkAYgHkJUAD5QJAdQCCAJRnK1EpDp0KdEvsQB0NylSq0E1ZjXSkUCPAF0eUAPR+UDIKACpIUADCtChQXFAAXtxwUHDoUOSp0HYOTlRWBF4A3AQEAMZwKDRQEGiYAIzM8Mi1WLh4ACK0wBBWKHAA7gAUAJS+0vJKYwCqVNyCiE4AJlDuEkVlFVU1GCAATI2IqDs4+Pyd3b0DI5bqxqbmNxJytKRCy8DJ5SgoEKXAJMlFl1aBxaLMLPwJDIIMB+qkANbVdDoVIQ4gSHQwzBQLrdBjAKjMADMEKKQA" rel="noopener noreferrer"&gt;try in playground&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Readonly Tuples
&lt;/h3&gt;

&lt;p&gt;You can make a tuple immutable using the &lt;code&gt;readonly&lt;/code&gt; modifier. This prevents modification to the tuple's elements (e.g., &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt;, direct assignment to an index).&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;type&lt;/span&gt; &lt;span class="nx"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;x&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;y&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;p&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="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="c1"&gt;// ERROR Cannot assign to '0' because it is a read-only property.&lt;/span&gt;
&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ERROR Property 'push' does not exist on type 'Point'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;small&gt;&lt;a href="https://www.typescriptlang.org/play/?ssl=6&amp;amp;ssc=68&amp;amp;pln=1&amp;amp;pc=1#code/C4TwDgpgBACg9gSwHbCgXigJwgQwCZxIA2IUA2gB4BcUSArgLYBGEmANFCDfc6wLoBuAFBCiEVGBrxkqDGQAMHeYJFgFfdFACMAqAHo9UAKIAlEwHkTUAMI4kSOKhwBnZwgDmSKMDhQA5PJ+UCwAxjh0ztAIqAjOUDhYuHgAtIQkUGCYcJCYoAB0QmB5YBEAFgAUAKwAlLoGxmaWsFk5oP4lzqVBBBBxDqgQFLGohN7g0H7SKH55QA" rel="noopener noreferrer"&gt;try in playground&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Manage Multiple Versions of PHP with Homebrew</title>
      <dc:creator>Michael Mathews</dc:creator>
      <pubDate>Sat, 15 Oct 2022 22:09:12 +0000</pubDate>
      <link>https://dev.to/micmath/manage-multiple-versions-of-php-with-homebrew-4dba</link>
      <guid>https://dev.to/micmath/manage-multiple-versions-of-php-with-homebrew-4dba</guid>
      <description>&lt;p&gt;Using &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; is a handy way to install multiple versions of PHP on MacOS. For example, to have both &lt;code&gt;php&lt;/code&gt; 7.4 and 8.0 installed, use the &lt;code&gt;brew install&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;First install the 7.4 version, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% brew &lt;span class="nb"&gt;install &lt;/span&gt;php@7.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax for specifying a specific version of a package with Homebrew is &lt;code&gt;brew install &amp;lt;packageName&amp;gt;@&amp;lt;version&amp;gt;&lt;/code&gt;. In this case the package name is &lt;code&gt;php&lt;/code&gt; and the version is &lt;code&gt;7.4&lt;/code&gt; (defaulting to &lt;code&gt;7.4.32&lt;/code&gt; as of this writing). If you leave off the &lt;code&gt;@&amp;lt;version&amp;gt;&lt;/code&gt; part entirely, Homebrew will install whatever the latest version available is (&lt;code&gt;8.1&lt;/code&gt; as of this writing).&lt;/p&gt;

&lt;p&gt;To check that version 7.4 of &lt;code&gt;php&lt;/code&gt; is correctly installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% /opt/homebrew/opt/php@7.4/bin/php &lt;span class="nt"&gt;-v&lt;/span&gt;  
  PHP 7.4.32 &lt;span class="o"&gt;(&lt;/span&gt;cli&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;built: Sep 29 2022 10:45:51&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; NTS &lt;span class="o"&gt;)&lt;/span&gt;
  Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; The PHP Group
  Zend Engine v3.4.0, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; Zend Technologies
    with Zend OPcache v7.4.32, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt;, by Zend Technologies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ideally we would like to refer to &lt;code&gt;/opt/homebrew/opt/php@7.4/bin/php&lt;/code&gt; simply as &lt;code&gt;php&lt;/code&gt; on our command line. This requires another step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% brew &lt;span class="nb"&gt;link&lt;/span&gt; &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="nt"&gt;--overwrite&lt;/span&gt; php@7.4
  Linking /opt/homebrew/Cellar/php@7.4/7.4.32... 812 symlinks created.

  If you need to have this software first &lt;span class="k"&gt;in &lt;/span&gt;your PATH instead consider running:
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="/opt/homebrew/opt/php@7.4/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="/opt/homebrew/opt/php@7.4/sbin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a result of running &lt;code&gt;brew link&lt;/code&gt; we can now find the linked version of &lt;code&gt;php&lt;/code&gt; at this path: &lt;code&gt;/opt/homebrew/bin/php&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="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /opt/homebrew/bin/php
  lrwxr-xr-x  1 myuser  admin  32 15 Oct 18:34 /opt/homebrew/bin/php -&amp;gt; ../Cellar/php@7.4/7.4.32/bin/php
% /opt/homebrew/bin/php &lt;span class="nt"&gt;-v&lt;/span&gt;
  PHP 7.4.32 &lt;span class="o"&gt;(&lt;/span&gt;cli&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;built: Sep 29 2022 10:45:51&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; NTS &lt;span class="o"&gt;)&lt;/span&gt;
  Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; The PHP Group
  Zend Engine v3.4.0, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; Zend Technologies
    with Zend OPcache v7.4.32, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt;, by Zend Technologies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of running &lt;code&gt;brew link&lt;/code&gt; has a suggestion that we append two lines to the end of our &lt;code&gt;~/.zshrc&lt;/code&gt; file to tell our terminal that when we refer to &lt;code&gt;php&lt;/code&gt; it should look for it first in the &lt;code&gt;/opt/homebrew/opt/php@7.4/bin&lt;/code&gt; folder. You can do this but every time you &lt;code&gt;brew link&lt;/code&gt; to a different version of &lt;code&gt;php&lt;/code&gt; you will have to edit those lines. Instead I will take a slightly modified approach:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'export PATH="/opt/homebrew/sbin:/opt/homebrew/bin:$PATH"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.zshrc
% &lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our terminal will find the linked version of &lt;code&gt;php&lt;/code&gt; at &lt;code&gt;/opt/homebrew/bin&lt;/code&gt; first whenever we refer to &lt;code&gt;php&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;% which php    
  /opt/homebrew/bin/php
% php &lt;span class="nt"&gt;-v&lt;/span&gt;
  PHP 7.4.32 &lt;span class="o"&gt;(&lt;/span&gt;cli&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;built: Sep 29 2022 10:45:51&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; NTS &lt;span class="o"&gt;)&lt;/span&gt;
  Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; The PHP Group
  Zend Engine v3.4.0, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; Zend Technologies
    with Zend OPcache v7.4.32, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt;, by Zend Technologies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have &lt;code&gt;php&lt;/code&gt; version 7.4 installed we can continue by installing &lt;code&gt;php&lt;/code&gt; version 8.0 too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% brew &lt;span class="nb"&gt;install &lt;/span&gt;php@8.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we tell brew to link to the new version of &lt;code&gt;php&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;% brew &lt;span class="nb"&gt;link&lt;/span&gt; &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="nt"&gt;--overwrite&lt;/span&gt; php@8.0
  Unlinking /opt/homebrew/Cellar/php@7.4/7.4.32... 328 symlinks removed.
  Linking /opt/homebrew/Cellar/php@8.0/8.0.24... 232 symlinks created.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the output from this command we again see the suggestion to run two commands containing the command &lt;code&gt;export PATH...&lt;/code&gt; but due to the steps we took above, this won't be necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% which php    
  /opt/homebrew/bin/php
% php &lt;span class="nt"&gt;-v&lt;/span&gt;
  PHP 8.0.24 &lt;span class="o"&gt;(&lt;/span&gt;cli&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;built: Sep 30 2022 08:39:20&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; NTS &lt;span class="o"&gt;)&lt;/span&gt;
  Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; The PHP Group
  Zend Engine v4.0.24, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; Zend Technologies
    with Xdebug v3.1.5, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt; 2002-2022, by Derick Rethans
    with Zend OPcache v8.0.24, Copyright &lt;span class="o"&gt;(&lt;/span&gt;c&lt;span class="o"&gt;)&lt;/span&gt;, by Zend Technologies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can switch from versions of 7.4 to 8.0 by relinking from one to the other: &lt;code&gt;brew link --force --overwrite php@7.4&lt;/code&gt; or &lt;code&gt;brew link --force --overwrite php@8.0&lt;/code&gt; for example.&lt;/p&gt;

&lt;p&gt;If you're not sure what versions are available to link to, try this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% brew &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;--versions&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'^php[ @]'&lt;/span&gt;
  php@7.4 7.4.32
  php@8.0 8.0.24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, below is the source code of a more full featured script that I call &lt;code&gt;phpswitch&lt;/code&gt;. This script can be set to be &lt;a href="https://support.apple.com/en-gb/guide/terminal/apdd100908f-06b3-4e63-8a87-32e71241bab4/mac"&gt;executable&lt;/a&gt; and then run from the terminal like &lt;code&gt;phpswitch 8.0&lt;/code&gt; or &lt;code&gt;phpswitch 7.4&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;#!/bin/bash&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;1&amp;gt;&amp;amp;2 &lt;span class="s2"&gt;"USAGE: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;phpVersion&amp;gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;INSTALLED_VERSIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;find /opt/homebrew/opt | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'php@'&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/\/opt\/homebrew\/opt\/php@//'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /opt/homebrew/opt/php@&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/bin/php &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;1&amp;gt;&amp;amp;2 &lt;span class="s2"&gt;"/opt/homebrew/opt/php@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/php was not found"&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'valid options:\n%s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INSTALLED_VERSIONS&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi

for &lt;/span&gt;VERSION &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INSTALLED_VERSIONS&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;brew &lt;span class="nb"&gt;unlink &lt;/span&gt;php@&lt;span class="nv"&gt;$VERSION&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1
    brew services stop php@&lt;span class="nv"&gt;$VERSION&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;span class="k"&gt;done

&lt;/span&gt;brew &lt;span class="nb"&gt;link&lt;/span&gt; &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="nt"&gt;--overwrite&lt;/span&gt; php@&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1
brew services start php@&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>php</category>
      <category>homebrew</category>
      <category>macos</category>
    </item>
  </channel>
</rss>
