<?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: Zachary Lee</title>
    <description>The latest articles on DEV Community by Zachary Lee (@zacharylee).</description>
    <link>https://dev.to/zacharylee</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%2F1453981%2F914dd71f-2f46-4a0f-9e5f-67613437d5c8.png</url>
      <title>DEV Community: Zachary Lee</title>
      <link>https://dev.to/zacharylee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zacharylee"/>
    <language>en</language>
    <item>
      <title>The Differences Between "export default xx" and "export {xx as default}"</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Tue, 21 Oct 2025 03:57:14 +0000</pubDate>
      <link>https://dev.to/zacharylee/the-differences-between-export-default-xx-and-export-xx-as-default-4ab3</link>
      <guid>https://dev.to/zacharylee/the-differences-between-export-default-xx-and-export-xx-as-default-4ab3</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published in&lt;/em&gt; &lt;a href="https://upweb.dev/posts/differences-between-export-default" rel="noopener noreferrer"&gt;my newsletter&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basics of JavaScript Modules
&lt;/h2&gt;

&lt;p&gt;Modules are self-contained pieces of code that can be imported and used in other modules. They help developers keep code organized, maintainable, and easy to understand.&lt;/p&gt;

&lt;p&gt;To work with modules, you need to understand the import and export syntax. Here’s a quick recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;import&lt;/code&gt;: Used to import named exports or default exports from other modules.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;export&lt;/code&gt;: Used to export values, functions, or classes from a module, making them available for other modules to import.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are two types of exports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Named exports: You can have multiple named exports in a module. They are explicitly imported using their names.&lt;/li&gt;
&lt;li&gt;Default exports: Each module can have only one default export. They are imported without specifying a name.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Behavior of export { xxx as default }
&lt;/h2&gt;

&lt;p&gt;In JavaScript, imports are live bindings, or references, rather than values. This means that when you import a variable from another module, you’re importing a reference to that variable, not a copy of its value.&lt;/p&gt;

&lt;p&gt;Consider the following 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="c1"&gt;// math.js&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;888&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./math.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ?&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, guess what &lt;code&gt;value&lt;/code&gt; is printed?&lt;/p&gt;

&lt;p&gt;The answer is &lt;code&gt;888&lt;/code&gt; not &lt;code&gt;1&lt;/code&gt;. This is because &lt;code&gt;export&lt;/code&gt; exports references.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Behavior of export default xxx
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;export default&lt;/code&gt; syntax is used to export a default value from a module. However, when you use &lt;code&gt;export default value&lt;/code&gt;, the current value is exported, not a live reference.&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;// math.js&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;888&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./math.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, when the &lt;code&gt;value&lt;/code&gt; variable in &lt;code&gt;math.js&lt;/code&gt; changes, the &lt;code&gt;value&lt;/code&gt; variable in &lt;code&gt;app.js&lt;/code&gt; does not change. This is because &lt;code&gt;value&lt;/code&gt; holds the current value at import time, not a live reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Export Reference Data Types
&lt;/h2&gt;

&lt;p&gt;As you can see, we exported primitive data types earlier, but what if we exported reference data 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="c1"&gt;// math.js&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;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="mi"&gt;888&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// OR&lt;/span&gt;
&lt;span class="c1"&gt;// export { value as default };&lt;/span&gt;
&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./math.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="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="nx"&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="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, there is no difference between &lt;code&gt;export default xxx&lt;/code&gt; and &lt;code&gt;export { xxx as default }&lt;/code&gt; when dealing with reference data types. It can be understood that they are always reference types in JavaScript, and they will not be &lt;a href="https://webdeveloper.beehiiv.com/p/get-perfect-deep-copy-javascript" rel="noopener noreferrer"&gt;deeply copied&lt;/a&gt; when exported.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices and Recommendations
&lt;/h2&gt;

&lt;p&gt;While both &lt;code&gt;export default xxx&lt;/code&gt; and &lt;code&gt;export { xxx as default }&lt;/code&gt; can be used to export default values, but their behavior differs in certain scenarios. Here are some recommendations to help you choose the right syntax:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;export default xxx&lt;/code&gt; when you want to export a value, such as a string, or number, and you don't need live bindings.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;export { xxx as default }&lt;/code&gt; when you need live binding, especially when the exported value may change over time (not recommended).&lt;/li&gt;
&lt;li&gt;For reference data types, either syntax can be used, since they always export a reference.&lt;/li&gt;
&lt;li&gt;A related suggestion: For code readability and maintainability, it is recommended to use named exports instead of default exports, &lt;a href="https://webdeveloper.beehiiv.com/p/avoid-default-exports-javascript-modules" rel="noopener noreferrer"&gt;here is why&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The differences between &lt;code&gt;export default xxx&lt;/code&gt; and &lt;code&gt;export { xxx as default }&lt;/code&gt; in JavaScript may appear subtle, but they can have an impact on your code's behavior. Hope this article is helpful to you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you find this helpful, &lt;a href="https://upweb.dev/" rel="noopener noreferrer"&gt;please consider subscribing&lt;/a&gt; to my newsletter for more insights on web development. Thank you for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How does HTTPS work</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Tue, 21 Oct 2025 03:39:22 +0000</pubDate>
      <link>https://dev.to/zacharylee/how-does-https-work-2i68</link>
      <guid>https://dev.to/zacharylee/how-does-https-work-2i68</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published in&lt;/em&gt; &lt;a href="https://upweb.dev/posts/how-does-https-work" rel="noopener noreferrer"&gt;&lt;em&gt;my newsletter&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hypertext Transfer Protocol (HTTP) is an application-layer protocol for transmitting hypermedia documents, such as HTML. It was originally designed for communication between web browsers and web servers, but with later development, its application is not limited here, the mature software and hardware environment makes it the infrastructure of the Internet. I believe you must have been exposed to it, it is just like water or air in software development, it’s all too common.&lt;/p&gt;

&lt;p&gt;But as programmers, we may ignore a lot of key information because of its commonness, resulting in some problems in daily work development and do not know how to solve them. Then this article will introduce you to one of the key pieces of information — HTTPS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why HTTPS?
&lt;/h3&gt;

&lt;p&gt;Why does it appear? What problem does it appear to solve?&lt;/p&gt;

&lt;p&gt;To answer the above questions, we need to first analyze the characteristics of HTTP.&lt;/p&gt;

&lt;p&gt;The characteristics of HTTP are simple, flexible, and easy to extend, but at the same time it is stateless (you can use Cookie technology to achieve “stateful”), and it is transmitted in clear text, which means that its data is completely visible and easy to be eavesdropped or forgery.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bpfgpujje703m7bakul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bpfgpujje703m7bakul.png" alt="img" width="665" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the same time, HTTP is widely used, so scenarios with high-security requirements such as online payment require corresponding security measures, so HTTPS appeared.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is HTTPS?
&lt;/h3&gt;

&lt;p&gt;The RFC document of HTTPS has very little content. It specifies a new protocol name “HTTPS” and the default port number is 443, which is to insert a “security layer” between TCP and HTTP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8beonk4vzt398bpmwmpm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8beonk4vzt398bpmwmpm.png" alt="img" width="411" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This security layer, as the name implies, encrypts the data sent and decrypts the data received so that the middleman cannot steal the information. Then as long as you understand this security layer, you also understand HTTPS.&lt;/p&gt;

&lt;p&gt;SSL is the Secure Sockets Layer, which is at layer 6 (Presentation) in the &lt;a href="https://en.wikipedia.org/wiki/OSI_model?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=how-does-https-work" rel="noopener noreferrer"&gt;OSI model&lt;/a&gt;. It was invented by Netscape in 1994. There are two versions, v2 and v3, and v1 was never disclosed because of its flaws.&lt;/p&gt;

&lt;p&gt;When SSL developed to v3, it proved itself to be a very good secure communication protocol, so the Internet Engineering Group IETF renamed it TLS (Transport Layer Security) in 1999, and officially standardized, the version number from 1.0 is recalculated, so TLS1.0 is actually SSL 3.1.&lt;/p&gt;

&lt;p&gt;At present, TLS has developed three versions, namely 1.1 in 2006, 1.2 in 2008, and 1.3 in 2018, and each new version is continuously enhancing security and performance. The most widely used TLS 1.2 at present, so let’s unravel the secrets of TLS 1.2!&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTPS (TLS 1.2) secret
&lt;/h3&gt;

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

&lt;p&gt;Let me explain the above image first:&lt;/p&gt;

&lt;p&gt;Handshake phase:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client generates a client-random and then passes the symmetric cipher suites and asymmetric cipher suites it supports to the server.&lt;/li&gt;
&lt;li&gt;After the server receives it, it will select the encryption algorithm to use from the encryption suite, generate a server-random and pass the certificate of the service to the client.&lt;/li&gt;
&lt;li&gt;After the client receives it, it will first verify the certificate. If the certificate is valid, it will generate a pre-master random number, encrypt it with the public key in the certificate and the selected &lt;strong&gt;asymmetric encryption algorithm&lt;/strong&gt; , and then pass it to the server. It will also come with a Client finished confirmation message.&lt;/li&gt;
&lt;li&gt;The server receives the encrypted pre-master and can decrypt it using the private key. A confirmation message of the Server finished will then be passed to the Client.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Transfer stage:&lt;/p&gt;

&lt;p&gt;After the handshake phase, both ends already have client-random, server-random, and pre-master. Mix them to generate the final master secret, and use the previously selected &lt;strong&gt;symmetric encryption algorithm&lt;/strong&gt; to encrypt and decrypt the required transmitted data.&lt;/p&gt;

&lt;p&gt;God, is it so troublesome that I just want to send data? I thought the same thing when I first saw it.&lt;/p&gt;

&lt;p&gt;Let’s be patient and take a closer look, it’s actually not that difficult.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are symmetric encryption and asymmetric encryption?
&lt;/h3&gt;

&lt;p&gt;Let’s first explain the symmetric encryption and asymmetric encryption mentioned above.&lt;/p&gt;

&lt;p&gt;Symmetric encryption means that the same key is used for encryption and decryption. Asymmetric encryption has two keys, A and B. If you use the A key to encrypt, you can only use the B key to decrypt; conversely, If you want the B key to encrypt, you can only use the A key to decrypt.&lt;/p&gt;

&lt;p&gt;In the handshake phase of HTTPS, we use asymmetric encryption, why? Suppose we use symmetric encryption:&lt;/p&gt;

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

&lt;p&gt;As can be seen from the above figure, the client-random and service-random and symmetric encryption suites passed in are in clear text, which leads to the fact that if a hacker gets the data, they can generate the same key, which can be cracked data.&lt;/p&gt;

&lt;p&gt;If we use asymmetric encryption, the pre-master encrypted by the client can only decrypt the key stored by the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a CA certificate?
&lt;/h3&gt;

&lt;p&gt;Because once the hacker uses DNS hijacking and replaces the IP address that the user wants to access with the hacker’s IP address, the request will be sent directly to the hacker’s service. He implements the public key and private key on his service, and the client completely does not know!&lt;/p&gt;

&lt;p&gt;So we need the CA (Certificate Authority) certificate authority to help us prove that this service is the service we want to access!&lt;/p&gt;

&lt;h3&gt;
  
  
  How to check the validity of the CA certificate?
&lt;/h3&gt;

&lt;p&gt;The client will verify according to the following process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check if the certificate has expired&lt;/li&gt;
&lt;li&gt;Check if revoked by CA&lt;/li&gt;
&lt;li&gt;Check whether the certificate is issued by the CA authority. We will use the original certificate information to calculate the message digest, use the CA public key to decrypt the digital signature in the certificate, and then compare the message digest with the digital signature.&lt;/li&gt;
&lt;li&gt;Prove the legitimacy of the CA organization. The CA certification chain is a tree structure, and the root CA certificate is found step by step. The root CA certificate (self-signed certificate) is built into the system. The requirements are very strict. If the root CA certificate is valid, it also proves that the certificate is valid. But if malware injects an illegitimate root CA certificate into a user’s system, there’s no way around it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why is the transmission phase symmetric encryption?
&lt;/h3&gt;

&lt;p&gt;This is because the symmetric encryption algorithm usually uses bit operations, and the asymmetric encryption is mainly the calculation of some large number multiplications in RSA, so the efficiency of asymmetric encryption is very low, which will seriously affect the transmission speed and make the user experience very poor. And the master secret we generated in the handshake phase is secure enough, so we can use symmetric encryption in the transfer phase.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you find this helpful, &lt;a href="https://upweb.dev/" rel="noopener noreferrer"&gt;please consider subscribing&lt;/a&gt; to my newsletter for more insights on web development. Thank you for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Ditch Git Checkout: Use Git Switch and Git Restore Instead</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Mon, 14 Oct 2024 02:45:48 +0000</pubDate>
      <link>https://dev.to/zacharylee/ditch-git-checkout-use-git-switch-and-git-restore-instead-51e6</link>
      <guid>https://dev.to/zacharylee/ditch-git-checkout-use-git-switch-and-git-restore-instead-51e6</guid>
      <description>&lt;p&gt;If you use Git in your daily work, &lt;code&gt;git checkout&lt;/code&gt; is a common command. It's often used to switch branches, and if you look at the &lt;a href="https://git-scm.com/docs/git-checkout?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=ditch-git-checkout-use-git-switch-and-git-restore-instead" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;, you can see the phrase &lt;em&gt;"switch branches or restore working tree files"&lt;/em&gt;. But UNIX should be &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Unix_philosophy?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=ditch-git-checkout-use-git-switch-and-git-restore-instead#Do_One_Thing_and_Do_It_Well" rel="noopener noreferrer"&gt;Do One Thing and Do It Well&lt;/a&gt;&lt;/em&gt;. This was confusing, so Git 2.23 brought a pair of commands to replace it.&lt;/p&gt;




&lt;p&gt;Before introducing how it works, we need to briefly understand its associated Git concepts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Working copy (working tree file): It refers to the file in the repository that appears on the hard disk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Index (staging area or cache): it refers to you have &lt;code&gt;git add&lt;/code&gt;-ed, or, what would be committed if you were to run &lt;code&gt;git commit&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HEAD: It refers to the “current” or “active” branch, when we need to check out a branch (referring to your attempt to match the branch with what is in the working copy), only one can be checked out at a time.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git checkout&lt;/code&gt; can checkout a branch or create a new branch and checkout into it:&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;# Switched to branch 'test'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# Switched to a new branch 'test'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# Switch back to the previous branch&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout -

&lt;span class="c"&gt;# Switched to a commit&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout master~1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;git switch&lt;/code&gt; is used to take over branch related, so it can also do:&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;# Switched to branch 'test'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git switch &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# Switched to a new branch 'test'&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git switch &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# Switch back to the previous branch&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git switch -

&lt;span class="c"&gt;# Switched to a commit&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git switch &lt;span class="nt"&gt;-d&lt;/span&gt; master~1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as we said at the beginning, &lt;code&gt;git checkout&lt;/code&gt; can also restore working tree files. This part of the feature is taken over by &lt;code&gt;git restore&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the past, we could use &lt;code&gt;git checkout -- main.c&lt;/code&gt; to restore the working tree file from the index, the syntax was &lt;code&gt;git checkout [treeish] -- &amp;lt;filename&amp;gt;&lt;/code&gt;, where &lt;code&gt;treeish&lt;/code&gt; could be specified as the source. Simple examples:&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;# Restoring the working tree from the index&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c

&lt;span class="c"&gt;# Restoring index content from HEAD&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c

&lt;span class="c"&gt;# Restoring the working tree and index from HEAD&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout HEAD &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that when restoring index content from HEAD, we can only use &lt;code&gt;git reset&lt;/code&gt;, and &lt;code&gt;git checkout&lt;/code&gt; has no corresponding option.&lt;/p&gt;

&lt;p&gt;Show with a graph:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpi3apahzkb7w0mlgvj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffpi3apahzkb7w0mlgvj2.png" width="712" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git restore&lt;/code&gt; makes it easier to determine which files will be restored, and where they will be restored. The following options specify the restore location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-W
--worktree
-S
--staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, &lt;code&gt;-W&lt;/code&gt; and &lt;code&gt;--worktree&lt;/code&gt; will restore the working tree from the index, the same as if no options were specified (like &lt;code&gt;git restore -- ./main.c&lt;/code&gt; ). Whereas &lt;code&gt;-S&lt;/code&gt; and &lt;code&gt;--staged&lt;/code&gt; will restore the index contents from HEAD. When passing both, the index and working tree will be restored from HEAD.&lt;/p&gt;

&lt;p&gt;For instance:&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;# Restoring the working tree from the index&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c
&lt;span class="c"&gt;# Equivalent to&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="nt"&gt;--worktree&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c

&lt;span class="c"&gt;# Restoring index content from HEAD&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="nt"&gt;--staged&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c

&lt;span class="c"&gt;# Restoring the working tree and index from HEAD&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="nt"&gt;--staged&lt;/span&gt; &lt;span class="nt"&gt;--worktree&lt;/span&gt; ./main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Show with a graph:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78o5zsphiw7ogxf7z65o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78o5zsphiw7ogxf7z65o.png" width="780" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above-mentioned is the default, if we want to restore from a different commit, we can use the &lt;code&gt;--source&lt;/code&gt; option. E.g:&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;# Restore `./main.c` in the working tree with the last commit&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="nt"&gt;-s&lt;/span&gt; HEAD^ &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c
&lt;span class="c"&gt;# Equivalent to&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="nt"&gt;--source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;HEAD^ &lt;span class="nt"&gt;--&lt;/span&gt; ./main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another useful &lt;code&gt;git restore&lt;/code&gt; case might be restoring a mishandled file. E.g:&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;# Incorrectly deleted files&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ./main.c

&lt;span class="c"&gt;# Quickly restore main.c from index&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore ./main.c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For batch recovery:&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;# Restore all C source files to match the version in the index&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="s1"&gt;'*.c'&lt;/span&gt;

&lt;span class="c"&gt;# Restore all files in the current directory&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Restore all working tree files with top pathspec magic&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git restore :/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The features of &lt;code&gt;git checkout&lt;/code&gt; are clearly separated: &lt;code&gt;git switch&lt;/code&gt; is used to switch branches, while &lt;code&gt;git restore&lt;/code&gt; is used to restore working tree files. They provide more explicit semantics, in line with the UNIX philosophy.&lt;/p&gt;

&lt;p&gt;Both commands were proposed in 2019, and as of now, they are experimental. There may be changes, but usually not by much, so you can use them now, they are easier to understand and less confusing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;em&gt;&lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;&lt;/em&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Secrets of JavaScript Object Property Order</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Mon, 14 Oct 2024 02:44:09 +0000</pubDate>
      <link>https://dev.to/zacharylee/the-secrets-of-javascript-object-property-order-4oh4</link>
      <guid>https://dev.to/zacharylee/the-secrets-of-javascript-object-property-order-4oh4</guid>
      <description>&lt;p&gt;Someone asked me recently, are JavaScript object properties necessarily unordered and unpredictable?&lt;/p&gt;

&lt;p&gt;Developers with early exposure to JavaScript might answer that &lt;code&gt;Object.keys()&lt;/code&gt; or &lt;code&gt;for...in&lt;/code&gt; returns an unpredictable order of object properties. But is that still the case?&lt;/p&gt;

&lt;p&gt;As you might expect, there are now rules to follow.&lt;/p&gt;

&lt;p&gt;Starting with ECMAScript 2020, &lt;code&gt;Object.keys&lt;/code&gt;, &lt;code&gt;for...in&lt;/code&gt;, &lt;code&gt;Object.getOwnPropertyNames&lt;/code&gt;, and &lt;code&gt;Reflect.ownKeys&lt;/code&gt; all follow the same order of specification. They are:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Own properties are array indexes, in ascending numeric index order
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzavmc45316mmk966ui3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzavmc45316mmk966ui3.png" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An array index is a String-valued property key that is a canonical numeric String. And a &lt;a href="http://www.ecma-international.org/ecma-262/10.0/?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=the-secrets-of-javascript-object-property-order#sec-canonicalnumericindexstring" rel="noopener noreferrer"&gt;canonical numeric String&lt;/a&gt; is a String representation of a number that would be produced by &lt;code&gt;ToString&lt;/code&gt;, or the string "-0". So for instance, "012" is &lt;em&gt;not&lt;/em&gt; a canonical numeric String, but "12" is.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Other own String properties, in ascending chronological order of property creation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fis23frjnsc87zefdc90a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fis23frjnsc87zefdc90a.png" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above code adds the knowledge point of the event loop. Because &lt;code&gt;setTimeout&lt;/code&gt; is an asynchronous macro task, the &lt;code&gt;c&lt;/code&gt; property has not been added to &lt;code&gt;obj&lt;/code&gt; when &lt;code&gt;console.log&lt;/code&gt; is output.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Own Symbol properties, in ascending chronological order of property creation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpeo1wai5ebcf7a4il6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpeo1wai5ebcf7a4il6d.png" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Symbol property is the same as the String property, in ascending chronological order of property creation. But the &lt;code&gt;Object.keys&lt;/code&gt;, &lt;code&gt;for...in&lt;/code&gt;, &lt;code&gt;Object.getOwnPropertyNames&lt;/code&gt; methods cannot get the object's Symbol properties, &lt;code&gt;Reflect.ownKeys&lt;/code&gt; and &lt;code&gt;Object.getOwnPropertySymbols&lt;/code&gt; can.&lt;/p&gt;

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

&lt;p&gt;When an object’s property keys are a combination of the above types, the object’s non-negative integer keys (enumerable and non-enumerable) are first added to the array in ascending order, then String keys are added in insertion order. Finally, Symbol keys are added in insertion order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5xbh0qcswd6y4rih3wi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5xbh0qcswd6y4rih3wi.png" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But if you strongly depend on the insertion order, then &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=the-secrets-of-javascript-object-property-order" rel="noopener noreferrer"&gt;Map&lt;/a&gt; guarantees that for you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;&lt;em&gt;subscribing to my newsletter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding the infer Keyword in TypeScript</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Fri, 27 Sep 2024 14:58:34 +0000</pubDate>
      <link>https://dev.to/zacharylee/understanding-the-infer-keyword-in-typescript-20mg</link>
      <guid>https://dev.to/zacharylee/understanding-the-infer-keyword-in-typescript-20mg</guid>
      <description>&lt;p&gt;TypeScript, a statically-typed superset of JavaScript, has gained massive popularity in the tech community due to its ability to catch errors early and improve code readability. One of TypeScript’s powerful features is the &lt;code&gt;infer&lt;/code&gt; keyword, which allows developers to write more expressive and dynamic types.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Infer Keyword
&lt;/h1&gt;

&lt;p&gt;Introduced in TypeScript 2.8, the &lt;code&gt;infer&lt;/code&gt; keyword is used within conditional types to create temporary type variables. These type variables can then be used to infer types within a true or false branch of a conditional type. The &lt;code&gt;infer&lt;/code&gt; keyword enables developers to write more dynamic and expressive types, as it allows TypeScript to determine a specific type based on the context in which it's used.&lt;/p&gt;

&lt;p&gt;To better understand how &lt;code&gt;infer&lt;/code&gt; works, let's take a look at the basic syntax of a conditional 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;MyConditionalType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;SomeType&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;TrueType&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FalseType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, &lt;code&gt;T&lt;/code&gt; is a generic type parameter, and &lt;code&gt;SomeType&lt;/code&gt; represents a type that &lt;code&gt;T&lt;/code&gt; is being compared to. If &lt;code&gt;T&lt;/code&gt; extends &lt;code&gt;SomeType&lt;/code&gt;, the type of &lt;code&gt;MyConditionalType&amp;lt;T&amp;gt;&lt;/code&gt; will be &lt;code&gt;TrueType&lt;/code&gt;. If not, it will be &lt;code&gt;FalseType&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, let’s introduce the &lt;code&gt;infer&lt;/code&gt; keyword into the mix:&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;MyInferredType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;SomeType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;U&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;U&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FalseType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use the &lt;code&gt;infer&lt;/code&gt; keyword to create a temporary type variable &lt;code&gt;U&lt;/code&gt; within the true branch of the conditional type. If &lt;code&gt;T&lt;/code&gt; extends &lt;code&gt;SomeType&lt;/code&gt;, TypeScript will try to infer the type of &lt;code&gt;U&lt;/code&gt; based on the type of &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;ReturnType&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ReturnType&lt;/code&gt; is a utility type that extracts the return type of a function. It's a perfect example of how the &lt;code&gt;infer&lt;/code&gt; keyword can be used to create dynamic types. Here's the definition of &lt;code&gt;ReturnType&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="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this definition, &lt;code&gt;T&lt;/code&gt; is a function type that takes any number of arguments and returns any type. Using the &lt;code&gt;infer&lt;/code&gt; keyword, we create a temporary type variable &lt;code&gt;R&lt;/code&gt; to represent the return type of the function. If &lt;code&gt;T&lt;/code&gt; is a function, TypeScript infers the return type and assigns it to &lt;code&gt;R&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see &lt;code&gt;ReturnType&lt;/code&gt; in action:&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="s2"&gt;`Hello, &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;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GreetReturnType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// GreetReturnType is inferred as 'string'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;ReturnType&lt;/code&gt; is used to infer the return type of the &lt;code&gt;greet&lt;/code&gt; function, which is &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Parameters&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Another useful utility type that leverages the &lt;code&gt;infer&lt;/code&gt; keyword is &lt;code&gt;Parameters&lt;/code&gt;. This type extracts the parameter types of a function as a tuple. The definition of &lt;code&gt;Parameters&lt;/code&gt; is as follows:&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="nb"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&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="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we create a temporary type variable &lt;code&gt;P&lt;/code&gt; to represent the parameter types of the function. If &lt;code&gt;T&lt;/code&gt; is a function, TypeScript infers the parameter types and assigns them to &lt;code&gt;P&lt;/code&gt; as a tuple.&lt;/p&gt;

&lt;p&gt;Let’s look at an example using &lt;code&gt;Parameters&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;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="err"&gt;​&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AddParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// AddParameters is inferred as [number, number]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;Parameters&lt;/code&gt; is used to infer the parameter types of the &lt;code&gt;add&lt;/code&gt; function, which is a tuple &lt;code&gt;[number, number]&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;PromiseType&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;PromiseType&lt;/code&gt; utility type can be used to extract the type that a &lt;code&gt;Promise&lt;/code&gt; resolves to. This is particularly useful when dealing with asynchronous functions. Here's the definition of &lt;code&gt;PromiseType&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;PromiseType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;U&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;U&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we create a temporary type variable &lt;code&gt;U&lt;/code&gt; to represent the type that the &lt;code&gt;Promise&lt;/code&gt; resolves to. If &lt;code&gt;T&lt;/code&gt; is a &lt;code&gt;Promise&lt;/code&gt;, TypeScript infers the resolved type and assigns it to &lt;code&gt;U&lt;/code&gt;. Here’s an 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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fetched data&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="err"&gt;​&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FetchedDataType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PromiseType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// FetchedDataType is inferred as 'string'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;PromiseType&lt;/code&gt; is used to infer the type that the &lt;code&gt;fetchData&lt;/code&gt; function's promise resolves to, which is &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;UnboxArray&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;UnboxArray&lt;/code&gt; utility type can be used to extract the type of the elements within an array. Here's the definition of &lt;code&gt;UnboxArray&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;UnboxArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;U&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;U&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we create a temporary type variable &lt;code&gt;U&lt;/code&gt; to represent the type of the elements within the array. If &lt;code&gt;T&lt;/code&gt; is an array, TypeScript infers the element type and assigns it to &lt;code&gt;U&lt;/code&gt;. For instance:&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;MyArray&lt;/span&gt; &lt;span class="o"&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;type&lt;/span&gt; &lt;span class="nx"&gt;ElementType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UnboxArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyArray&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ElementType is inferred as 'number'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;UnboxArray&lt;/code&gt; is used to infer the type of elements within the &lt;code&gt;MyArray&lt;/code&gt; type, which is &lt;code&gt;number&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Limitations
&lt;/h1&gt;

&lt;p&gt;While the &lt;code&gt;infer&lt;/code&gt; keyword is incredibly powerful, it has some limitations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It can only be used within conditional types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s not always possible for TypeScript to infer the correct type, especially when dealing with complex or recursive types. In such cases, developers may need to provide additional type annotations or refactor their types to help TypeScript infer the correct type.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;By understanding and leveraging the power of &lt;code&gt;infer&lt;/code&gt;, you can create more flexible TypeScript projects. Start considering incorporating the infer keyword into your toolkit today.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;em&gt;&lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;&lt;/em&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How Server-Sent Events (SSE) Work</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Fri, 27 Sep 2024 14:47:11 +0000</pubDate>
      <link>https://dev.to/zacharylee/how-server-sent-events-sse-work-450a</link>
      <guid>https://dev.to/zacharylee/how-server-sent-events-sse-work-450a</guid>
      <description>&lt;p&gt;SSE (Server Sent Events) is not widely used in the world of web development, this article will take a deep dive into what SSE is, how it works, and how it can benefit your application.&lt;/p&gt;




&lt;h1&gt;
  
  
  What is SSE?
&lt;/h1&gt;

&lt;p&gt;SSE is a simple and efficient way to send real-time updates from a server to a client over an HTTP connection. It is a part of the HTML5 specification and is supported by all modern web browsers. SSE is based on a unidirectional data flow, where the server sends messages to the client, but the client cannot send messages back to the server.&lt;/p&gt;

&lt;p&gt;SSE uses a text-based format known as “Server-Sent Events” to send data to the client. The data is sent as a series of events, each of which contains a message and an optional event type. The event type is used to distinguish between different types of messages and allows the client to handle them differently.&lt;/p&gt;

&lt;h1&gt;
  
  
  How does SSE work?
&lt;/h1&gt;

&lt;p&gt;The SSE protocol works by establishing a persistent HTTP connection between the server and the client. This connection is kept open for as long as the client wants to receive updates from the server. When the server has new data to send, it sends an HTTP response with a special MIME type “text/event-stream”.&lt;/p&gt;

&lt;p&gt;The response contains a series of events, each of which is separated by a new line character (“\n”). Each event has the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event: [event type]\n
data: [message]\n\n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The “event” field is optional and is used to provide a name for the event. The “data” field contains the actual message being sent. The two newline characters at the end of each event are used to signal the end of the event.&lt;/p&gt;

&lt;p&gt;Here’s an example of a simple SSE response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1 200 OK
Content-Type: text/event-stream

event: message
data: Hello, world!

event: message
data: This is a test message.

event: customEvent
data: {"foo": "bar", "baz": 123}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we’re sending three events to the client. The first two events have the event type “message” and contain simple text messages. The third event has the event type “customEvent” and contains a JSON object as its message.&lt;/p&gt;

&lt;p&gt;When the client receives an SSE response, it uses the data to update its user interface. This can be done using JavaScript to manipulate the DOM, for example.&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementing SSE
&lt;/h1&gt;

&lt;p&gt;Implementing SSE in your application is relatively straightforward. Here’s an example of how to implement SSE using Node.js and the Express framework:&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Set up SSE endpoint&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/events&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="c1"&gt;// Set headers&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&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;text/event-stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cache-Control&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;no-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Connection&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;keep-alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Send initial event&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data: Connected&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Set interval to send periodic events&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;intervalId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data: Hello, world!&lt;/span&gt;&lt;span class="se"&gt;\n\n&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="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Clean up on connection close&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalId&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="c1"&gt;// Start server&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&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="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="s1"&gt;Server started on port 3000&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;In this example, we’re setting up an SSE endpoint at “/events”. We’re setting the necessary headers for SSE and sending an initial event to the client to confirm that the connection has been established.&lt;/p&gt;

&lt;p&gt;We’re then setting up an interval to send periodic events to the client every second. Finally, we’re cleaning up the interval when the connection is closed by the client.&lt;/p&gt;

&lt;p&gt;On the client side, we can use the following JavaScript code to listen for SSE events:&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;source&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;EventSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&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;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="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="nx"&gt;event&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;In this example, we’re creating a new EventSource object and passing in the URL of our SSE endpoint. We’re then listening for the “message” event and logging the data to the console. We’re also listening for the “error” event in case there are any connection issues.&lt;/p&gt;

&lt;p&gt;Note that the &lt;code&gt;EventSource&lt;/code&gt; path on the front end can only be used by &lt;code&gt;GET&lt;/code&gt; requests, if you want to use &lt;code&gt;POST&lt;/code&gt; and other HTTP methods, you need to parse the response data yourself.&lt;/p&gt;

&lt;p&gt;If you want a native Node.js implementation, &lt;a href="https://stackblitz.com/edit/stackblitz-starters-vnmdin?file=index.js&amp;amp;utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=how-server-sent-events-sse-work" rel="noopener noreferrer"&gt;here’s one&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/stackblitz-starters-vnmdin?file=index.js" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Use cases for SSE
&lt;/h1&gt;

&lt;p&gt;SSE can be used in a wide range of applications that require real-time updates. Here are a few examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Social media platforms: SSE can be used to provide real-time updates for social media platforms, such as notifications of new messages, comments, or likes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Financial applications: SSE can be used to provide real-time updates for financial applications, such as stock prices, currency exchange rates, or news.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Online gaming: SSE can be used to provide real-time updates for online gaming applications, such as notifications of game events, scores, or rankings.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Benefits of using SSE
&lt;/h1&gt;

&lt;p&gt;There are several benefits to using SSE over other real-time communication methods such as polling or WebSockets:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Efficiency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;SSE uses a persistent HTTP connection, which means that the overhead of establishing and maintaining the connection is much lower than with other methods. This makes SSE more efficient and less resource-intensive, which is especially important when dealing with large numbers of clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Simplicity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;SSE is a simple protocol that is easy to understand and implement. It does not require any special libraries or frameworks and can be implemented using standard web technologies such as JavaScript and HTTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Reliability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;SSE is a reliable protocol that provides automatic reconnection in case of a network interruption. This ensures that the client will continue to receive updates even if the connection is temporarily lost.&lt;/p&gt;

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

&lt;p&gt;Server-Sent Events (SSE) are a simple and efficient way to send real-time updates from a server to a client over an HTTP connection. It is a part of the HTML5 specification and is supported by all modern web browsers. SSE uses a unidirectional data flow, where the server sends messages to the client, but the client cannot send messages back to the server. This saves you from constantly polling the server for events, which not only improves performance but also reduces complexity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;em&gt;&lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;&lt;/em&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Ditch dotenv: Node.js Now Natively Supports .env File Loading</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Sun, 22 Sep 2024 08:07:16 +0000</pubDate>
      <link>https://dev.to/zacharylee/ditch-dotenv-nodejs-now-natively-supports-env-file-loading-8e6</link>
      <guid>https://dev.to/zacharylee/ditch-dotenv-nodejs-now-natively-supports-env-file-loading-8e6</guid>
      <description>&lt;p&gt;One of the staples of environment management in Node.js has been the use of the &lt;code&gt;dotenv&lt;/code&gt; package, which facilitates the loading of environment variables from a &lt;code&gt;.env&lt;/code&gt; file. However, recent updates in Node.js have introduced built-in capabilities that may reduce or eliminate the need for external packages like &lt;code&gt;dotenv&lt;/code&gt; for managing environment variables.&lt;/p&gt;

&lt;h1&gt;
  
  
  Native &lt;code&gt;.env&lt;/code&gt; File Handling
&lt;/h1&gt;

&lt;p&gt;Starting from version 20.6.0, Node.js allows the use of the &lt;code&gt;--env-file&lt;/code&gt; flag when executing scripts. This flag specifies a path to an &lt;code&gt;.env&lt;/code&gt; file that Node.js will read before running the specified script. This approach streamlines the process of setting environment variables, making it more integrated and less reliant on third-party packages.&lt;/p&gt;

&lt;p&gt;Consider a scenario where you have the following environment configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .env file&lt;/span&gt;
&lt;span class="s"&gt;NODE_OPTIONS='--title="Sample Node App"'&lt;/span&gt;
&lt;span class="s"&gt;USER_NAME='John Doe'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run a Node.js script using this configuration, you would use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--env-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.env your-script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;your-script.js&lt;/code&gt;, accessing these variables can be done as follows:&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: Sample Node App&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;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USER_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;span class="c1"&gt;// Outputs: Hello, John Doe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Simplified Loading with &lt;code&gt;process.loadEnvFile()&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Building upon the initial support, Node.js version 21.7.0 introduced the &lt;code&gt;process.loadEnvFile()&lt;/code&gt; method. This function simplifies the loading of environment variables by incorporating them into the runtime process without the need for command-line flags.&lt;/p&gt;

&lt;p&gt;You can load the environment variables programmatically within your application as shown below:&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadEnvFile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Automatically loads `.env` from the current directory&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
&lt;span class="c1"&gt;// Or specify a path&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadEnvFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config/env_vars.env&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;h1&gt;
  
  
  Parsing Environment Variables
&lt;/h1&gt;

&lt;p&gt;In addition to loading environment variables, Node.js 21.7.0 introduced &lt;code&gt;util.parseEnv()&lt;/code&gt;, a utility function that parses a string containing environment variable definitions into an object.&lt;/p&gt;

&lt;p&gt;Here’s how you might use &lt;code&gt;util.parseEnv()&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;const&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:util&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;envVars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEnv&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_KEY=12345&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;envVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: 12345&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Support for Multi-line Values in &lt;code&gt;.env&lt;/code&gt; Files
&lt;/h2&gt;

&lt;p&gt;Another feature in Node.js 21.7.0 is the support for multi-line values in &lt;code&gt;.env&lt;/code&gt; files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;CERTIFICATE="-----BEGIN CERTIFICATE-----&lt;/span&gt;
&lt;span class="s"&gt;MIIDdTCCAl2gAwIBAgIJAKC1hi9s2wfMM...&lt;/span&gt;
&lt;span class="s"&gt;-----END CERTIFICATE-----"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now include such multi-line strings directly in your &lt;code&gt;.env&lt;/code&gt; files, making management of complex configurations cleaner and more straightforward.&lt;/p&gt;

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

&lt;p&gt;The native .env file support introduced in the latest Node.js allows your project to be set up faster and reduces dependencies on external packages such as dotenv.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;&lt;em&gt;subscribing to my newsletter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>node</category>
    </item>
    <item>
      <title>How to Create a Type to Retrieve All Keys of an Object in TypeScript</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Mon, 16 Sep 2024 04:30:01 +0000</pubDate>
      <link>https://dev.to/zacharylee/how-to-create-a-type-to-retrieve-all-keys-of-an-object-in-typescript-54dn</link>
      <guid>https://dev.to/zacharylee/how-to-create-a-type-to-retrieve-all-keys-of-an-object-in-typescript-54dn</guid>
      <description>&lt;p&gt;Typescript has a feature called &lt;code&gt;keyof&lt;/code&gt; that can be used to obtain the keys of an object. However, the &lt;code&gt;keyof&lt;/code&gt; operator only works for the first level of an object, and when we want to obtain all keys in a deep level, things get a bit more complicated. In this article, we will discuss how to implement a type that can obtain all keys in a deep level.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Overview of the Problem&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;To understand the problem we are trying to solve, let’s start with an example. Consider the following object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;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;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;b&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;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;d&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="na"&gt;e&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;g&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to obtain all the keys of this object, including the keys in the nested objects, we need a type that can recursively traverse the object and return all the keys. This can be a challenging task, especially for complex objects with multiple levels of nesting.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;A Possible Solution&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;One approach to solving this problem is to use a recursive type definition. Typescript allows us to define recursive types using intersection types. An intersection type is a type that represents a value that has all the properties of all the types in the intersection.&lt;/p&gt;

&lt;p&gt;We can define a recursive type that represents an object with a set of keys, where each key is either a primitive value or another object that also has a set of keys. Here’s how we can define this 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;DeepKeys&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&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;K&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;K&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;DeepKeys&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&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="s2"&gt;`&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This type definition may seem a bit complex, so let’s break it down into smaller parts.&lt;/p&gt;

&lt;p&gt;The type &lt;code&gt;DeepKeys&amp;lt;T&amp;gt;&lt;/code&gt; is a conditional type that checks if the input type &lt;code&gt;T&lt;/code&gt; is an object. If &lt;code&gt;T&lt;/code&gt; is an object, we use a mapped type to create a new object with the same keys as &lt;code&gt;T&lt;/code&gt;, but the values are the keys of the nested objects, represented as a string. If &lt;code&gt;T&lt;/code&gt; is not an object, we return an empty string.&lt;/p&gt;

&lt;p&gt;The mapped type uses the &lt;code&gt;keyof&lt;/code&gt; operator to get the keys of the object, and then we use a conditional statement to check if each key is a string or number. If the key is a string or number, we concatenate it with a dot and the keys of the nested object, obtained recursively using &lt;code&gt;DeepKeys&amp;lt;T[K]&amp;gt;&lt;/code&gt;. If the key is not a string or number, we return &lt;code&gt;never&lt;/code&gt;, which means the key is not valid.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Using the Type&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Now that we have defined the &lt;code&gt;DeepKeys&lt;/code&gt; type, we can use it to get the keys of any object with nested objects. Here's an example of how we can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="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="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;b&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;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;d&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="na"&gt;e&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="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;g&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="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;h&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;DeepKeys&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&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;K&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;K&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;DeepKeys&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&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="s2"&gt;`&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&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;getAllKeys&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;object&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;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&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;DeepKeys&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&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;entries&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="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newPrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prefix&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;prefix&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;key&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;newPrefix&lt;/span&gt;&lt;span class="p"&gt;,&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="s1"&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="nf"&gt;getAllKeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newPrefix&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="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;DeepKeys&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getAllKeys&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;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;keys&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ["a" | "f" | "h" | "a.b" | "a.c" | "a.c.d" | "a.c.e" | "f.g"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we define a function called &lt;code&gt;getAllKeys&lt;/code&gt; that takes an object as an argument and returns an array of all the keys in the object. We use the &lt;code&gt;Object.keys&lt;/code&gt; method to get the keys of the object, and then we cast the result to the &lt;code&gt;DeepKeys&lt;/code&gt; type to ensure that we get all the keys, including the keys in the nested objects.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Limitations&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;While the &lt;code&gt;DeepKeys&lt;/code&gt; type can be useful in many situations, it does have some limitations. One limitation is that it only works for objects with a finite depth. If we have an object with an infinite depth, such as an object that contains a reference to itself, the type definition will result in a stack overflow error.&lt;/p&gt;

&lt;p&gt;Another limitation is that the resulting type can be very complex for objects with many levels of nesting, which can make it difficult to work with. In some cases, it may be necessary to use a simpler type definition or a different approach to get the keys of an object.&lt;/p&gt;

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

&lt;p&gt;In this article, we have discussed how to implement a type that can obtain all the keys in an object, including the keys in the nested objects. We have used a recursive type definition to define the &lt;code&gt;DeepKeys&lt;/code&gt; type, which allows us to recursively traverse the object and return all the keys. We have also provided an example of how to use the &lt;code&gt;DeepKeys&lt;/code&gt; type to get the keys of an object.&lt;/p&gt;

&lt;p&gt;While the &lt;code&gt;DeepKeys&lt;/code&gt; type has some limitations, it can be a useful tool for working with objects with nested objects.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;em&gt;&lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;&lt;/em&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>7 Lesser-Known HTML Attributes to Enhance User Experience</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Wed, 11 Sep 2024 04:29:00 +0000</pubDate>
      <link>https://dev.to/zacharylee/7-lesser-known-html-attributes-to-enhance-user-experience-45gm</link>
      <guid>https://dev.to/zacharylee/7-lesser-known-html-attributes-to-enhance-user-experience-45gm</guid>
      <description>&lt;p&gt;HTML is a powerful language for creating web pages, and while most developers are familiar with commonly used HTML attributes, there are several lesser-known attributes that can provide additional functionality and enhance the user experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. The &lt;code&gt;enterkeyhint&lt;/code&gt; Attribute for Virtual Keyboards
&lt;/h1&gt;

&lt;p&gt;When designing web forms for mobile devices, it’s important to consider the virtual keyboards that users interact with. The &lt;code&gt;enterkeyhint&lt;/code&gt; attribute is a global attribute that can be applied to form controls or elements with the &lt;code&gt;contenteditable&lt;/code&gt; attribute set to true. It assists users by providing hints to the virtual keyboard about the intended action associated with the "Enter" key. This attribute accepts values such as &lt;code&gt;enter&lt;/code&gt;, &lt;code&gt;done&lt;/code&gt;, &lt;code&gt;go&lt;/code&gt;, &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;previous&lt;/code&gt;, &lt;code&gt;search&lt;/code&gt;, and &lt;code&gt;send&lt;/code&gt;, allowing you to customize the hint based on the specific context of your application.&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;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;enterkeyhint=&lt;/span&gt;&lt;span class="s"&gt;"done"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  2. Attributes for Custom Ordered Lists
&lt;/h1&gt;

&lt;p&gt;While working with ordered lists &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt;, you can utilize several lesser-known attributes to customize the behavior of the numbering. These attributes include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;reversed&lt;/code&gt; attribute: It allows you to number the list items in reverse order, from high to low instead of the default low to high.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;start&lt;/code&gt; attribute: It defines the number from which the list should start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;type&lt;/code&gt; attribute: It specifies whether to use numbers, letters, or Roman numerals for the list items.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;value&lt;/code&gt; attribute: It enables you to set a custom number for a specific list item.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;ol&lt;/span&gt; &lt;span class="na"&gt;reversed&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;List item...&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;List item...&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;List item...&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;ol&lt;/span&gt; &lt;span class="na"&gt;reversed&lt;/span&gt; &lt;span class="na"&gt;start=&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Typee: A Peep at Polynesian Life (1846)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Omoo: A Narrative of Adventures in the South Seas (1847)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Mardi: and aVoyage Thither (1849)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Redburn: His First Voyage (1849)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;White-Jacket; or, The World in a Man-of-War (1850)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Moby-Dick; or, The Whale (1851)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Pierre; or, The Ambiguities (1852)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Isle of the Cross (1853 unpublished, and now lost)&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  3. The &lt;code&gt;decoding&lt;/code&gt; Attribute for &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; Element
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;decoding&lt;/code&gt; attribute allows you to provide a hint to the browser about how an image should be decoded. This attribute can be added to an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element and accepts three values: &lt;code&gt;sync&lt;/code&gt;, &lt;code&gt;async&lt;/code&gt;, and &lt;code&gt;auto&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;sync&lt;/code&gt;: Decode the image synchronously, which is the default behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;async&lt;/code&gt;: Decode the image asynchronously to avoid delaying the presentation of other content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;auto&lt;/code&gt;: Let the browser use its default decoding method.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/example.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Example"&lt;/span&gt; &lt;span class="na"&gt;decoding=&lt;/span&gt;&lt;span class="s"&gt;"async"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By specifying the appropriate decoding behavior, you can optimize the loading and rendering of images on your web page.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. The &lt;code&gt;loading&lt;/code&gt; Attribute for &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; Element
&lt;/h1&gt;

&lt;p&gt;Similar to lazy loading images, the &lt;code&gt;loading&lt;/code&gt; attribute can be applied to &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; elements to control when the iframe's content should be loaded. By setting the &lt;code&gt;loading&lt;/code&gt; attribute to &lt;code&gt;lazy&lt;/code&gt;, you can defer the loading of the iframe until it's about to enter the viewport. This helps improve performance by reducing the initial page load time.&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;iframe&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/page.html"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"250"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  5. The &lt;code&gt;crossorigin&lt;/code&gt; Attribute for Cross-Origin Resource Sharing (CORS)
&lt;/h1&gt;

&lt;p&gt;When working with elements like &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, you may come across the need for cross-origin resource sharing (CORS). The &lt;code&gt;crossorigin&lt;/code&gt; attribute allows you to specify how the resource should be fetched in terms of CORS.&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;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://example.com/image.jpg"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Example Image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attribute accepts two values: &lt;code&gt;anonymous&lt;/code&gt; and &lt;code&gt;use-credentials&lt;/code&gt;. Setting it to &lt;code&gt;anonymous&lt;/code&gt; indicates that the resource should be fetched without including user credentials, while &lt;code&gt;use-credentials&lt;/code&gt; indicates that the user credentials should be included.&lt;/p&gt;

&lt;h1&gt;
  
  
  6. The &lt;code&gt;disablepictureinpicture&lt;/code&gt; Attribute for &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; Element
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;disablepictureinpicture&lt;/code&gt; attribute can be applied to the &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element to disable the Picture-in-Picture (PiP) feature. PiP allows videos to be displayed in a floating window, but if you want to prevent this behavior, you can simply add the attribute to the video element.&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;video&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"example.mp4"&lt;/span&gt; &lt;span class="na"&gt;disablepictureinpicture&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  7. The &lt;code&gt;integrity&lt;/code&gt; Attribute for Scripts
&lt;/h1&gt;

&lt;p&gt;To ensure that external scripts haven’t been tampered with, you can make use of the &lt;code&gt;integrity&lt;/code&gt; attribute. This attribute allows you to provide a cryptographic hash value that the browser can use to verify the integrity of the script file before executing it.&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;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"script.js"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha256-Kx70Z9jzvYF0Eex8oO7w08="&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By including the &lt;code&gt;integrity&lt;/code&gt; attribute with the appropriate hash value, you can add an extra layer of security to ensure the script's authenticity.&lt;/p&gt;

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

&lt;p&gt;In this article, we have explored a collection of lesser-known HTML attributes that can enhance your web development projects. From improving user interactions to optimizing resource loading, these attributes provide valuable functionalities that may not be widely known or utilized.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you find this helpful, please &lt;strong&gt;&lt;a href="https://webdeveloper.beehiiv.com/?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=7-lesser-known-html-attributes-to-enhance-user-experience" rel="noopener noreferrer"&gt;&lt;em&gt;consider subscribing&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt;_for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>html</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Difference Between new Function() and new function() in JavaScript</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Tue, 10 Sep 2024 13:42:14 +0000</pubDate>
      <link>https://dev.to/zacharylee/difference-between-new-function-and-new-function-in-javascript-254a</link>
      <guid>https://dev.to/zacharylee/difference-between-new-function-and-new-function-in-javascript-254a</guid>
      <description>&lt;p&gt;JavaScript is indeed flexible, but it also brings some confusion. For example, you can use multiple ways to do the same thing, such as creating functions, objects, etc. So what is the difference between the two mentioned in the title?&lt;/p&gt;




&lt;p&gt;&lt;code&gt;new Function&lt;/code&gt; is another way to create a function, its syntax:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const func = new Function ([arg1, arg2, ...argN], functionBody);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A simple 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;sum&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;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&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;b&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;return a + b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, this gives great flexibility. It’s not common, but there are some cases where it can be used. For example, we can use it when we need to dynamically compile a template into a function, which is what Vue.js does as far as I know. Besides that, it can also be used if we need to receive code strings from the server to create functions dynamically.&lt;/p&gt;

&lt;p&gt;Let’s quickly talk about its features. See what the code below will output?&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;globalThis&lt;/span&gt;&lt;span class="p"&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;10&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;createFunction1&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;return a;&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createFunction2&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&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;f&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;a&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;f&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;f1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFunction1&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;f1&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// ?&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFunction2&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;f2&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// ?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer is &lt;code&gt;10&lt;/code&gt; and &lt;code&gt;20&lt;/code&gt;. This is because &lt;code&gt;new Function&lt;/code&gt; always creates functions in the global scope. Only global variables and their own local variables can be accessed when running them.&lt;/p&gt;




&lt;p&gt;Whereas &lt;code&gt;new function()&lt;/code&gt; is intended to create a new object and apply an anonymous function as a constructor. Such as the following 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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new &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="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;name&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="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;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 1 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. Actually, every JavaScript function is a &lt;code&gt;Function&lt;/code&gt; object, in other words, &lt;code&gt;(function () {}).constructor === Function&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An associated knowledge point is how to use &lt;code&gt;new Function()&lt;/code&gt; to create an asynchronous function? &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=difference-between-new-function-and-new-function-in-javascript" rel="noopener noreferrer"&gt;MDN&lt;/a&gt; gave us the answer:&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;// Since `AsyncFunction` is not a global object, we need to get it manually:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AsyncFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&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="kd"&gt;constructor&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;fetchURL&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;AsyncFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&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;return await fetch(url);&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;fetchURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;&lt;em&gt;subscribing to my newsletter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Secrets of the 'delete' Operator in JavaScript</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Sat, 07 Sep 2024 11:26:36 +0000</pubDate>
      <link>https://dev.to/zacharylee/the-secrets-of-the-delete-operator-in-javascript-4e22</link>
      <guid>https://dev.to/zacharylee/the-secrets-of-the-delete-operator-in-javascript-4e22</guid>
      <description>&lt;p&gt;The delete operator is arguably an old language feature of JavaScript. As it literally means, it wants to destroy something, but what exactly can be destroyed? &lt;/p&gt;




&lt;h1&gt;
  
  
  delete 0
&lt;/h1&gt;

&lt;p&gt;When delete 0 is executed, will it be destroyed from the execution system from 0?&lt;/p&gt;

&lt;p&gt;Obviously not, its real purpose is to delete a property reference of an object.&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="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;property&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;Generally, successful deletion will return true and failure will return false, but there are some exceptions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Own properties
&lt;/h1&gt;

&lt;p&gt;The delete operator only works on its own property. If there is a property with the same name on the prototype chain, this property will be skipped.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3c8yo1537sqfilsf2i5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3c8yo1537sqfilsf2i5.png" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Non-existent property
&lt;/h1&gt;

&lt;p&gt;If the deleted property does not exist, delete will have no effect, but will still return true.&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;object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;object&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="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Non-configurable property
&lt;/h1&gt;

&lt;p&gt;Non-configurable properties cannot be removed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabfrevlc9dalesjlzfwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabfrevlc9dalesjlzfwr.png" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In non-strict mode, removing a non-configurable property of itself will return false, but in strict mode, it will throw a TypeError.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvu9f6bqyufs3v2vqabj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvu9f6bqyufs3v2vqabj.png" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Properties declared by var, let, const
&lt;/h1&gt;

&lt;p&gt;In the global scope, neither properties declared with var nor functions declared with function declarations (non-function expressions) can be deleted. This is because both the declared properties are mounted on the window and are non-configurable, so the logic of the previous item will be followed when deleting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F788h67hpkx71bhyrfg1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F788h67hpkx71bhyrfg1k.png" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, properties declared with var, let, const and those functions cannot be deleted, either in the global scope or in the function scope.&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;object&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="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;function&lt;/span&gt; &lt;span class="nf"&gt;getName&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;obj&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="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;delete&lt;/span&gt; &lt;span class="nx"&gt;object&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="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In non-strict mode, false is returned, &lt;strong&gt;but in strict mode, a SyntaxError is thrown instead of a TypeError.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5hziemgy5c98i7flx5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5hziemgy5c98i7flx5u.png" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Array property
&lt;/h1&gt;

&lt;p&gt;First of all, the length property of the array is not configurable, so deleting it in strict mode will throw a &lt;strong&gt;TypeError&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlxun9xqguk2d03y5abm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlxun9xqguk2d03y5abm.png" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, when deleting an array element, the deleted item will be empty.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ahl6oy1es7t5yjh2zj6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ahl6oy1es7t5yjh2zj6.png" width="733" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to modify the original array, you can use &lt;code&gt;Array.prototype.splice()&lt;/code&gt; &lt;/p&gt;

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

&lt;p&gt;The real purpose of the ‘delete operator’ in JavaScript is to delete a property reference of an object. It can behave strangely in some special cases, so it’s best to only use it to remove configurable properties that exist on the object itself.&lt;/p&gt;

&lt;p&gt;Besides that, please note that the ‘delete operator’ has nothing to do with freeing memory directly (compared to &lt;a href="https://docs.microsoft.com/en-us/cpp/cpp/delete-operator-cpp?view=msvc-170&amp;amp;viewFallbackFrom=vs-2019&amp;amp;utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=the-secrets-of-the-delete-operator-in-javascript" rel="noopener noreferrer"&gt;delete in C++&lt;/a&gt;), this is because the runtime environment of the JavaScript manages memory automatically. For more information on programming language memory management check out my &lt;a href="https://webdeveloper.beehiiv.com/p/memory-management-every-programmer-know?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=the-secrets-of-the-delete-operator-in-javascript" rel="noopener noreferrer"&gt;previous article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;&lt;em&gt;subscribing to my newsletter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Creating a React Hook for Rotating Images at Any Angle</title>
      <dc:creator>Zachary Lee</dc:creator>
      <pubDate>Thu, 05 Sep 2024 09:40:17 +0000</pubDate>
      <link>https://dev.to/zacharylee/creating-a-react-hook-for-rotating-images-at-any-angle-4nnb</link>
      <guid>https://dev.to/zacharylee/creating-a-react-hook-for-rotating-images-at-any-angle-4nnb</guid>
      <description>&lt;p&gt;In web development, you may need to rotate an image, which is easy to do in CSS. Simple code like this &lt;code&gt;transform: rotate(90deg);&lt;/code&gt;. But what if we want to do it in JS?&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;TLDR&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Draws the image to the canvas in the browser environment and rotates it. But before that, we need to do some math to keep the original image aspect ratio.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Core&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Assuming that we have loaded the image, calculating the rotated image can be done as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;abs&lt;/span&gt; &lt;span class="p"&gt;}&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;angle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;degree&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;180&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;sinAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&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;cosAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&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;rotatedWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cosAngle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageHeight&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sinAngle&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;rotatedHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sinAngle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageHeight&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cosAngle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And next, we use some of the canvas APIs to do the actual rotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canvasWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&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;canvasCtx2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearRect&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;canvasWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasWidth&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;canvasHeight&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;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;imageWidth&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="nx"&gt;imageHeight&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;imageWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;imageHeight&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;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/png&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;h1&gt;
  
  
  &lt;strong&gt;Wrap up&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;With the core code in place, we can make some optimizations and write dedicated React hooks to use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RotatedImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;src&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="nl"&gt;width&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="nl"&gt;height&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="p"&gt;}&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLCanvasElement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanvasRenderingContext2D&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getRotatedImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLImageElement&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;rotation&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="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;RotatedImage&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;canvas&lt;/span&gt; &lt;span class="o"&gt;??=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt; &lt;span class="o"&gt;??=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&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;image&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentSrc&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;image&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;degree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rotation&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&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;degree&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;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentSrc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageHeight&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;abs&lt;/span&gt; &lt;span class="p"&gt;}&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;angle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;degree&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;180&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;sinAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&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;cosAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cosAngle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageHeight&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sinAngle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sinAngle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageHeight&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cosAngle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// The width and height of the canvas will be automatically rounded.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canvasWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearRect&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;canvasWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasWidth&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;canvasHeight&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;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;canvasCtx2D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;imageWidth&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="nx"&gt;imageHeight&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;imageWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;imageHeight&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;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canvasWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canvasHeight&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;useRotateImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageSrc&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;rotation&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;RotatedImage&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageEle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLImageElement&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rotatedImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setRotatedImage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RotatedImage&lt;/span&gt;&lt;span class="o"&gt;&amp;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="nf"&gt;useEffect&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;rotation&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageEle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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;currImage&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;currentSrc&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;imageSrc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currImage&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;Image&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;imageEle&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="nx"&gt;currImage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;currImage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageSrc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;currImage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setRotatedImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getRotatedImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rotation&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="nf"&gt;setRotatedImage&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="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="nx"&gt;imageSrc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rotation&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;rotatedImage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;useRotateImage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I reuse the same canvas element to reduce repeated creation. Secondly, it should be noted that I set its width and height to &lt;code&gt;0&lt;/code&gt; after each rotation to reduce memory usage. By the way, I also did the operation of clearing the canvas. This is because in the &lt;a href="https://html.spec.whatwg.org/multipage/canvas.html?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=creating-a-react-hook-for-rotating-images-at-any-angle#concept-canvas-set-bitmap-dimensions" rel="noopener noreferrer"&gt;HTML spec&lt;/a&gt; when you modify the width and height of the canvas (whether it is the same as before) will clear the canvas, which is the same as &lt;code&gt;canvasCtx2D.clearRect(0, 0, canvasWidth, canvasHeight)&lt;/code&gt;, which is supported by modern browsers.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;useRotateImage&lt;/code&gt;, I keep a reference to the &lt;code&gt;image&lt;/code&gt; element and set the rotated image state after &lt;code&gt;image.decode()&lt;/code&gt;, which is resolved after the image data is ready.&lt;/p&gt;

&lt;p&gt;Below is a &lt;a href="https://stackblitz.com/edit/vitejs-vite-6iarde?file=src%2FApp.tsx&amp;amp;utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=creating-a-react-hook-for-rotating-images-at-any-angle" rel="noopener noreferrer"&gt;online use case&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/vitejs-vite-6iarde?file=src%2FApp.tsx" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you found this helpful, please consider&lt;/em&gt; &lt;a href="https://webdeveloper.beehiiv.com/subscribe?utm_source=webdeveloper.beehiiv.com&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=under-the-hood-of-react-router-in-40-lines-of-code&amp;amp;_bhlid=2f26f41cf9803691495f3ae68d43e3d616c1c102" rel="noopener noreferrer"&gt;&lt;em&gt;subscribing to my newsletter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for more useful articles and tools about web development. Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
