<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Vladyslav Zubko</title>
    <description>The latest articles on Forem by Vladyslav Zubko (@what1s1ove).</description>
    <link>https://forem.com/what1s1ove</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%2F1192732%2F27039a72-4730-4174-8f03-5f5f6e015675.jpeg</url>
      <title>Forem: Vladyslav Zubko</title>
      <link>https://forem.com/what1s1ove</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/what1s1ove"/>
    <language>en</language>
    <item>
      <title>BEM Modifiers in Pure CSS Nesting</title>
      <dc:creator>Vladyslav Zubko</dc:creator>
      <pubDate>Mon, 17 Jun 2024 08:42:06 +0000</pubDate>
      <link>https://forem.com/what1s1ove/bem-modifiers-in-pure-css-nesting-4j9k</link>
      <guid>https://forem.com/what1s1ove/bem-modifiers-in-pure-css-nesting-4j9k</guid>
      <description>&lt;p&gt;When I was starting to learn web development, pure CSS often remained in the realm of theory. When it came to practice, especially working on real projects, pure CSS was a rarity. The market and the industry itself dictated that styles should be written using preprocessors.&lt;/p&gt;

&lt;p&gt;Fortunately, over time, this trend has almost disappeared. Pure CSS now includes many features that were previously missing, causing people to prefer preprocessors.&lt;/p&gt;

&lt;p&gt;Even though I have not used preprocessors for a long time, at least in my personal projects, there is one thing I missed while working with them: using the &lt;a href="https://sass-lang.com/documentation/style-rules/parent-selector/" rel="noopener noreferrer"&gt;parent selector&lt;/a&gt; to create modifiers when using the &lt;a href="https://en.bem.info/methodology/css/" rel="noopener noreferrer"&gt;BEM methodology&lt;/a&gt;. I thought for a long time that I would never be able to avoid duplicating the full selector when writing modifiers in pure CSS. However, while redesigning my website, I found a convenient way for myself to write BEM modifiers using native CSS nesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Path with BEM &amp;amp; SCSS
&lt;/h2&gt;

&lt;p&gt;I hate preprocessors. Be it &lt;a href="https://sass-lang.com/documentation/syntax/#the-indented-syntax" rel="noopener noreferrer"&gt;SASS&lt;/a&gt;, &lt;a href="https://sass-lang.com/documentation/syntax/#scss" rel="noopener noreferrer"&gt;SCSS&lt;/a&gt;, &lt;a href="https://lesscss.org/" rel="noopener noreferrer"&gt;LESS&lt;/a&gt;, &lt;a href="https://stylus-lang.com/" rel="noopener noreferrer"&gt;Stylus&lt;/a&gt;, or any other. Really, without any exceptions. Though, I think my hatred for preprocessors is not because of the technology itself, but because of how other people use them. Throughout my development career, I have often encountered tickets where a seemingly simple task, like changing the text size, which should take minutes, ended up taking me hours. This is because people often want to use the tool to its full extent. As a result, to find where I needed to change the text size in &lt;em&gt;projects using preprocessors to the max&lt;/em&gt;, I had to go through several mixins, maybe a loop or even nested loops, and several nested selectors using the parent selector. Brr, just thinking about it gives me the shivers.&lt;/p&gt;

&lt;p&gt;Like many who started their careers during the peak popularity of preprocessors, I initially did not spend much time on pure CSS. The industry, including the job market, dictated the need for preprocessor knowledge, and mentions of pure CSS in job listings were rare. I was no exception, and almost from the beginning of my learning journey, I began writing styles using SCSS. I was very fortunate with my mentors, as they instilled in me a great love for pure CSS, despite the use of preprocessors. SCSS was chosen deliberately because it closely resembles pure CSS compared to other preprocessors. Additionally, out of all the features preprocessors offer, we used only two: compiling all &lt;code&gt;.scss&lt;/code&gt; files into one file and nesting with the parent selector, exclusively for pseudo-classes/pseudo-elements and creating &lt;a href="https://en.bem.info/methodology/css/#modifiers" rel="noopener noreferrer"&gt;modifiers&lt;/a&gt; using the BEM methodology. All other preprocessor features, such as loops and mixins, were forbidden, as they were meant to solve specific problems rather than being used &lt;em&gt;just because they exist&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F6xaxe89w2d27mfmefhry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F6xaxe89w2d27mfmefhry.png" alt="An example of my code with BEM and SCSS that I wrote when I started my developer journey."&gt;&lt;/a&gt;&lt;br&gt;For what purpose I used SCSS when I was learning.
  &lt;/p&gt;

&lt;p&gt;Later on, after my training, almost all of my work projects involved some preprocessor. It was during these experiences that I developed my strong dislike for preprocessors. In my personal projects, however, I never used preprocessors and wrote everything in pure CSS, adding precise enhancements through plugins for my &lt;code&gt;.css&lt;/code&gt; bundler. For example, in the past, when I was bundling my &lt;code&gt;.css&lt;/code&gt; files using &lt;a href="https://postcss.org/" rel="noopener noreferrer"&gt;PostCSS&lt;/a&gt;, I used a simple plugin called &lt;a href="https://www.npmjs.com/package/postcss-import" rel="noopener noreferrer"&gt;postcss-import&lt;/a&gt; to bundle all &lt;code&gt;.css&lt;/code&gt; files into one final file (such as in this blog. Here is &lt;a href="https://github.com/what1s1ove/whatislove.dev/commit/15eb16e2de4ddfd9c72fe39503351650bfdc5eab#diff-25789e3ba4c2adf4a68996260eb693a441b4a834c38b76167a120f0b51b969f7R34" rel="noopener noreferrer"&gt;one of the first commits in this repository&lt;/a&gt;). I rarely used any additional plugins for CSS.&lt;/p&gt;

&lt;p&gt;I always tried to avoid nesting in preprocessors wherever possible, but with the introduction of native CSS nesting, I gradually began incorporating it into my personal projects. It seems to me that native CSS nesting works more intuitively and correctly compared to nesting in preprocessors. One key difference with native CSS nesting compared to preprocessor nesting is that it does not have the functionality of a parent selector to create &lt;em&gt;new selectors.&lt;/em&gt; This is what I used during my training for BEM modifiers, and it was perhaps the only thing I started to miss when using native CSS nesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native CSS Nesting Modifiers
&lt;/h2&gt;

&lt;p&gt;Before native CSS nesting became available, I had to describe all class modifiers with separate selectors. During those times, I particularly missed the functionality of creating a new selector using the parent selector in preprocessors. This was because the full selector for a modifier could be duplicated dozens of times.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.tag-list__tag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-red-200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="py"&gt;padding-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;padding-inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.tag-list__tag--html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-green-100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.tag-list__tag--github&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-gray-100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.tag-list__tag--ts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-blue-200&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;But even with the introduction of native CSS nesting, I did not immediately solve this problem because native CSS nesting simply does not have anything functionally similar to creating a new selector through the parent selector functionality found in preprocessors.&lt;/p&gt;

&lt;p&gt;The first thing I started using more actively was various attributes, such as &lt;code&gt;aria-current="page"&lt;/code&gt;, &lt;code&gt;rel="prev"&lt;/code&gt;/&lt;code&gt;rel="next"&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, and others. Just this alone significantly helped reduce the number of class modifiers. However, not all modifiers can be covered with attributes, and in my code, there still remained a sizable number of places where the selector was duplicated entirely to create a BEM modifier.&lt;/p&gt;

&lt;p&gt;I tried googling for solutions because BEM methodology markup is quite popular, but all the code examples and repositories I found were doing the same thing – simply duplicating the entire selector.&lt;/p&gt;

&lt;p&gt;One day, as I was adding new modifiers and duplicating the entire selector, I decided to experiment. Like everyone starting out with CSS, I learned about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors" rel="noopener noreferrer"&gt;attribute selectors&lt;/a&gt;. I was no exception and went through that section, but truthfully, I rarely used these selectors. However, I completely forgot that attribute selectors can be used with any attribute, including &lt;code&gt;class&lt;/code&gt; (because it is odd to use an attribute selector for a &lt;code&gt;class&lt;/code&gt; when you can just use a class selector, right?). Then it struck me – I also remembered about additional operators available in attribute selectors, specifically &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors#substring_matching_selectors" rel="noopener noreferrer"&gt;substring matching selectors&lt;/a&gt;, which work perfectly with native CSS nesting. Here is how it looks:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.tag-list__tag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-red-200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="py"&gt;padding-block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;padding-inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="err"&gt;&amp;amp;[class*='--html']&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-green-100&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;amp;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s2"&gt;'--github'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-gray-100&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;amp;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s2"&gt;'--ts'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-blue-200&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It turned out quite close to the modifiers that I used to write using the parent selector in SCSS at the beginning of my learning, didn't it?&lt;/p&gt;

&lt;p&gt;Perhaps not as concise as using the parent selector to create new selectors in preprocessors, but personally, I prefer the approach with native CSS nesting and attribute selectors paired with substring matching selectors much more. As I mentioned earlier, native CSS nesting is much clearer and more logical to me in understanding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/what1s1ove/whatislove.dev/pull/553/files#diff-ca25b3b88b76bdb99b160aeab08b9a6aaa5428df4fe8ad55834db5c67a74f24e" rel="noopener noreferrer"&gt;Here&lt;/a&gt; you can find the PR where I applied this trick across my entire project.&lt;/p&gt;

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

&lt;p&gt;I love CSS and all its functionality. It is gratifying to see how the foundational aspects of CSS from the very beginning seamlessly complement the new functionalities emerging within it. Moreover, this synergy works in both directions.&lt;/p&gt;

&lt;p&gt;I have never been part of the group of people who say that native CSS should incorporate everything found in tools like SASS or other preprocessors. To me, these are different tools, and this small trick using attribute selectors together with substring matching selectors in native CSS nesting for BEM modifiers &lt;code&gt;&amp;amp;[class*="--modifier"]&lt;/code&gt; has finally fulfilled all my wishes that I had when using SCSS and other preprocessors. However, CSS continues to evolve, and on the horizon, we can already see &lt;a href="https://github.com/w3c/csswg-drafts/issues/9350" rel="noopener noreferrer"&gt;native CSS mixins&lt;/a&gt; (one of the reasons why I always reluctantly talk about SCSS or other preprocessors).&lt;/p&gt;

&lt;p&gt;Once upon a time, when native CSS nesting was just starting to be discussed, I thought, "Nesting? In pure CSS? I will never use that!" But over time, I got used to it, and now I even like it. Will the same happen with native CSS mixins, or, heaven forbid, native CSS loops? I want to say no, but I will not make predictions. At the very least, with experience, I have become acquainted with a wonderful tool like &lt;a href="https://stylelint.io/" rel="noopener noreferrer"&gt;Stylelint&lt;/a&gt; and its life-easing rules such as &lt;a href="https://stylelint.io/user-guide/rules/max-nesting-depth/" rel="noopener noreferrer"&gt;max-nesting-depth&lt;/a&gt; and others. Hopefully, it will prevent me from becoming a hater of pure CSS someday.&lt;/p&gt;

</description>
      <category>css</category>
      <category>html</category>
      <category>bem</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why it is Important to Update Linters and How to Do it Right</title>
      <dc:creator>Vladyslav Zubko</dc:creator>
      <pubDate>Thu, 08 Feb 2024 10:22:05 +0000</pubDate>
      <link>https://forem.com/what1s1ove/why-it-is-important-to-update-linters-and-how-to-do-it-right-28gh</link>
      <guid>https://forem.com/what1s1ove/why-it-is-important-to-update-linters-and-how-to-do-it-right-28gh</guid>
      <description>&lt;p&gt;Many developers approach “&lt;em&gt;old&lt;/em&gt;” projects with great reluctance. An old project can be defined as one in which the majority of its components are written using outdated approaches, obsolete rules of linters, old versions of libraries, or an outdated development platform. There can be various reasons why projects &lt;em&gt;age&lt;/em&gt; – strict release deadlines that only include business features, a lack of understanding on the business side of the project regarding the necessity of investing time &lt;em&gt;just like that&lt;/em&gt;, and simply the indifference towards the technical side of the project. However, when a situation truly starts to heat up, for example, an urgent need to migrate to the Node.js LTS version or promptly update a library version because further development is impossible, the time, motivation, and explanation of why it is necessary to do this will be found.&lt;/p&gt;

&lt;p&gt;When the time for updating the platform version and library versions inevitably comes, many developers mistakenly overlook linters. Often, configuring a linter and its rules is perceived as a one-time task, typically done at the start of the project, and it is assumed that after the initial setup, one can forget about it forever. Linters and their rules evolve, the same as any other libraries. New configurations, rules, and changes to existing rule options emerge. Depending on how and when you configured your linter, it will impact the quality of your code. After all, linters have long been not just about coding style but also about the correctness of code, staying up-to-date with new development approaches, and leveraging the language's new features.&lt;/p&gt;

&lt;p&gt;Consequently, if you adhere to the approach that a linter needs to be configured exactly once at the project's outset, then most likely the quality of your code will remain at the level it was when you initially configured the linter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg58aely2kivzxvg18505.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg58aely2kivzxvg18505.png" width="800" height="264"&gt;&lt;/a&gt;&lt;br&gt;A linter that does not receive enough love.
  &lt;/p&gt;

&lt;p&gt;Many developers are hesitant to update a linter and its rules because they fear that it may lead to various issues. Often, they worry that adding or modifying rules will require editing all the old code in files that may not have been touched for months or even years. This concern is particularly pronounced in large projects. Even if a rule pertains to more stylistic aspects and theoretically should not break anything, a pull request that applies the updated/new linter rule to the entire project can result in potentially several thousands of changed files, depending on the project's size. Reviewing such changes can be quite a task, and there might not even be a review, as such code reviews are rightfully considered unacceptable.&lt;/p&gt;

&lt;p&gt;Quality implementation of updated/new linter rules should follow a different process. First and foremost, the goal is to ensure that only all new files (or preferably new and modified ones) entering the codebase as part of a single code review adhere to the changed/new linter rule. With this approach, the process of modifying or adding rules becomes simple and safe, as there is no need to immediately edit the entire project to comply with the changes in linter. The application of linter updates will occur gradually, with each pull request incorporating more and more files that align with the new changes.&lt;/p&gt;

&lt;p&gt;Indeed, in this article, we will further explore how to approach the implementation of this process effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhanced Config
&lt;/h2&gt;

&lt;p&gt;All modern linters incorporate functionality for extending configurations, although the syntax for this is often implemented differently. Taking &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; as an example, in its latest versions, the primary extension method is through the use of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"&gt;spread operator&lt;/a&gt;. Let's take a look at an 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;// eslint.config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;languageOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;parserOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;ecmaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;latest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;sourceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arrow-parens&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;always&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* other ESLint plugins can be used here */&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;configs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To extend this configuration, you can do the following:&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;// eslint.enhanced.config.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;baseConfigs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./eslint.config.js&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;semi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;never&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;baseConfigs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&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;configs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see from the example, extending the base config using the spread operator is quite simple and clear. The name of this config can be anything, allowing us to pass the desired config name to the linter. Information about this will be provided below.&lt;/p&gt;

&lt;p&gt;Another common way to extend configs in linters is using the &lt;code&gt;extends&lt;/code&gt; key in the configuration file. Let's take &lt;a href="https://stylelint.io/"&gt;StyleLint&lt;/a&gt; as an 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;// stylelint.config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylelint-config-standard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The values in the &lt;code&gt;extends&lt;/code&gt; key array can be absolute or relative paths. Absolute paths are used for configs provided by package managers, for example, &lt;a href="https://www.npmjs.com/"&gt;NPM&lt;/a&gt;, as shown in the example above. On the other hand, relative paths are used to extend local configuration files. The mechanism is similar to using the spread operator for extending ESLint configs.&lt;/p&gt;

&lt;p&gt;Both using the spread operator and the &lt;code&gt;extends&lt;/code&gt; key in the linter's configuration file are popular methods for implementing the config extension mechanism. However, it is worth noting that the spread operator mechanism is becoming increasingly popular among linters in recent times. In earlier versions, ESLint also supported the extension mechanism through the &lt;code&gt;extends&lt;/code&gt; key in the configuration file. Although this mechanism can still be used in ESLint, it is not recommended. Moreover, ESLint's authors plan to deprecate support for the extension mechanism via the &lt;code&gt;extends&lt;/code&gt; key in future releases.&lt;/p&gt;

&lt;p&gt;Another crucial aspect common to all linters is the CLI option &lt;code&gt;--config&lt;/code&gt; (or &lt;code&gt;-c&lt;/code&gt;), which allows us to explicitly specify the configuration to use for linting files. By default, all linters have a set of standard configuration file names they will look for in the project when the linter is run. For example, ESLint searches for the file &lt;code&gt;eslint.config.js&lt;/code&gt;, while StyleLint looks for &lt;code&gt;stylelint.config.js&lt;/code&gt;. Since most projects rarely have more than one linter configuration file, the &lt;code&gt;--config&lt;/code&gt; CLI option is not frequently used, but it is essential not to overlook it.&lt;/p&gt;

&lt;p&gt;Since we want to gradually implement the updated/new rule in the project, we can leverage the config extension mechanism to use the existing linter config and extend it with a newly created config. This new config will include all settings and rules from the base config and will also be extended with updated/new rules. This allows us to use the base linter config to lint all old files as before, and for all new files that should be introduced into the codebase via a pull request, we can lint them using the enhanced linter config and the CLI option &lt;code&gt;--config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We have covered the part about extending the config. Now, let's understand how to apply updated/new rules only to files involved in code reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous Integration Changes
&lt;/h2&gt;

&lt;p&gt;In most projects, before other people start reviewing code in a pull request, it needs to pass machine reviews from various linters and tests. This process is commonly referred to as &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;Continuous Integration&lt;/a&gt; (or CI for short). There are numerous tools available to help set up this process. In this article, we will use &lt;a href="https://docs.github.com/en/actions"&gt;GitHub Actions&lt;/a&gt;, which is also the most popular tool for configuring the CI process on GitHub. However, the principles can be applied with any CI tool.&lt;/p&gt;

&lt;p&gt;The simplest CI GitHub Actions for linting JavaScript files can look like this:&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;# .github/workflows/ci.yml&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Continuous Integration&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Code Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install NodeJS&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.nvmrc&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint JS&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx eslint .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are not familiar with the GitHub Actions syntax, you can refer to it &lt;a href="https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Currently, the main step in the action is the "Lint JS" step, which simply runs ESLint on all JS files in the project. You can learn more about ESLint's CLI capabilities &lt;a href="https://eslint.org/docs/latest/use/command-line-interface"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we need to add additional steps that include checking for updated/new rules. The simplest implementation of this would look like the following:&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;# .github/workflows/ci.yml&lt;/span&gt;

&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="c1"&gt;# CI GitHub Action and its configuration&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get Changed Files&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;changed-files&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tj-actions/changed-files@v42&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint JS with Enhanced Rules&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx eslint --config eslint.enhanced.config.js ${{ steps.changed-files.outputs.added_files }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to add two additional steps. The first one is to retrieve all new files, and the second one is to run the enhanced config only on the new files. In this example the third-party GitHub Action called &lt;a href="https://github.com/tj-actions/changed-files"&gt;changed-files&lt;/a&gt; is used to obtain the new files. In the &lt;a href="https://github.com/marketplace?type=actions"&gt;GitHub Marketplace for Actions&lt;/a&gt;, there is a considerable number of similar actions with similar functionality. You can choose the one that suits you best, as the functionality is more or less the same for all of them.&lt;/p&gt;

&lt;p&gt;It is important to note that in this example, we apply the enhanced config only to new files that will be in the pull request. Depending on the agreements within your team, such as the average size of your pull requests, it is strongly recommended to include not only new files but also modified ones when linting with the enhanced config. This will expedite the process of achieving 100% coverage of the project with updated/new rules.&lt;/p&gt;

&lt;p&gt;Also, due to the simplicity of the example, a straightforward GitHub Actions workflow was used where all steps are performed within a single job. While this works, it is recommended to decompose the tasks performed by a GitHub Action into multiple jobs when it makes sense to divide them. This can enhance readability and maintainability of your workflows.&lt;/p&gt;

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

&lt;p&gt;In modern development, where technologies are constantly evolving, keeping linters up-to-date becomes crucial for maintaining high code quality. Many developers, while focusing on platform and library updates, overlook the importance of updating linters. However, linters play a role not only in maintaining code style but also in ensuring its correctness and adherence to modern development practices.&lt;/p&gt;

&lt;p&gt;The fear of updating linters is often associated with potential issues, such as the need to make changes to extensive old code. However, implementing linter updates can be done more safely by following methods of gradual modification, applying updated/new rules to new or modified files. This process ensures a gradual alignment of the entire project with updated standards, minimizing potential issues and providing a smooth adaptation process.&lt;/p&gt;

&lt;p&gt;An important element of successfully updating a linter is the use of configuration extension functionality. Modern linters, such as ESLint, provide extension mechanisms, allowing updates to be gradually introduced by extending the existing config with updated/new rules. This approach ensures the ease of alignment for both existing code and new changes, contributing to maintaining a high coding standard in the project.&lt;/p&gt;

&lt;p&gt;Additionally, once you achieve 100% coverage of the project with the updated/new rule in the enhanced linter config, do not forget to move this rule to the main config. This ensures that the rule is consistently applied across the entire project and helps maintain a unified code style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F862wbsqr0ugzmraeg4j6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F862wbsqr0ugzmraeg4j6.png" width="800" height="587"&gt;&lt;/a&gt;&lt;br&gt;A linter that receives enough love (but it can always be better!)
  &lt;/p&gt;

&lt;p&gt;Try to incorporate this approach into your daily development routine, as now you know that it is not very complicated to do. I am sure you, your team, and your project will appreciate this change, as it embodies not only technical efficiency but also the flexibility required in the modern dynamic development environment.&lt;/p&gt;

&lt;p&gt;You can find complete examples of using this approach &lt;a href="https://github.com/what1s1ove/enhanced-config"&gt;here in the repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>ci</category>
      <category>automation</category>
    </item>
    <item>
      <title>TypeScript Might Not Be Your God: Case Study of Migration from TS to JSDoc</title>
      <dc:creator>Vladyslav Zubko</dc:creator>
      <pubDate>Tue, 16 Jan 2024 17:20:34 +0000</pubDate>
      <link>https://forem.com/what1s1ove/typescript-might-not-be-your-god-case-study-of-migration-from-ts-to-jsdoc-o99</link>
      <guid>https://forem.com/what1s1ove/typescript-might-not-be-your-god-case-study-of-migration-from-ts-to-jsdoc-o99</guid>
      <description>&lt;p&gt;"We will &lt;em&gt;soon&lt;/em&gt; migrate to TypeScript, and then..." – how often do you hear this phrase? Perhaps, if you mainly work within a single project or mostly just start new projects from scratch, this is a relatively rare expression for you to hear. For me, as someone working in an outsourcing company, who, in addition to my main project, sees dozens of various other projects every month, it is a quite common phrase from the development team or a client who would like to upgrade their project stack for easier team collaboration. Spoiler alert: it is probably not going to be as soon of a transition as you think (most likely, &lt;em&gt;never&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;While it may sound drastic, &lt;em&gt;in most&lt;/em&gt; cases, this will indeed be the case. Most people who have not undergone such a transition may not be aware of the dozens of nuances that can arise during a project migration to TypeScript. For instance, are you prepared for the possibility that your project build, which took &lt;em&gt;tens of seconds&lt;/em&gt; in pure JavaScript, might suddenly start taking &lt;em&gt;tens&lt;/em&gt; &lt;em&gt;of minutes&lt;/em&gt; when using TypeScript? Of course, it depends on your project's size, your pipeline configuration, etc., but these scenarios are not fabricated. You, as a developer, might be prepared for this inevitability, but what will your client think when you tell them that the budget for the server instance needs to be increased because the project build is now failing due to a heap out-of-memory error after adding TypeScript to the project? Yes, TypeScript, like any other tool, is not free.&lt;/p&gt;

&lt;p&gt;On the Internet, you can find a large number of articles about how leading companies successfully migrated their projects from pure JavaScript to TypeScript. While they usually describe a lot of the issues they had during the transition and how they overcame them, there are still many unspoken obstacles that people can encounter which can become critical to your migration.&lt;/p&gt;

&lt;p&gt;Despite the awareness among most teams that adding typing to their projects through migration to TypeScript might not proceed as smoothly as depicted in various articles, they still consider TypeScript as the &lt;em&gt;exclusive and definitive solution&lt;/em&gt; to address typing issues in their projects. This mindset can result in projects remaining in pure JavaScript for extended periods, and the eagerly anticipated typing remains confined to the realm of dreams. While alternative tools for introducing typing to JavaScript code do exist, TypeScript's overwhelming popularity often casts them into the shadows. This widespread acclaim, justified by the TypeScript team's active development, may, however, prove disadvantageous to developers. Developers tend to lean towards the perception that TypeScript is the &lt;em&gt;only&lt;/em&gt; solution to typing challenges in a project, neglecting other options.&lt;/p&gt;

&lt;p&gt;Next, we will consider JSDoc as a tool that, when used correctly and understood in conjunction with other tools (like TypeScript), can help address the typing issue in a project &lt;em&gt;virtually for free&lt;/em&gt;. Many might think that the functionality of JSDoc pales in comparison to TypeScript, and comparing them is unfair. To some extent, that is true, but on the other hand, it depends on the perspective. Each technology has its pros and cons, counterbalancing the other.&lt;/p&gt;

&lt;p&gt;Code examples will illustrate a kind of &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Graceful_degradation" rel="noopener noreferrer"&gt;graceful degradation&lt;/a&gt; from TypeScript to JavaScript while maintaining typing functionality. While for some, this might appear as a form of &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement" rel="noopener noreferrer"&gt;progressive enhancement&lt;/a&gt;. Again, it all depends on how you look at it…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbr5pmlqy0h2qs5o6hnd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbr5pmlqy0h2qs5o6hnd4.png"&gt;&lt;/a&gt;&lt;br&gt;TypeScript to JSDoc. My vanilla JavaScript enums.
  &lt;/p&gt;

&lt;h2&gt;
  
  
  JSDoc and Its Extensions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://jsdoc.app/" rel="noopener noreferrer"&gt;JSDoc&lt;/a&gt; is a specification for the comment format in JavaScript. This specification allows developers to describe the structure of their code, data types, function parameters, and much more using special comments. These comments can then be transformed into documentation using appropriate tools.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * Adds two numbers.
 * @param {number} a - The first number.
 * @param {number} b - The second number.
 * @returns {number} The sum of the two numbers.
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getSum&lt;/span&gt; &lt;span class="o"&gt;=&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="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Initially, JSDoc was created with the goal of generating documentation based on comments, and this functionality remains a significant part of the tool. However, it is not the only aspect. The second substantial aspect of the tool is the description of various types within the program: variable types, object types, function parameters, and many other structures. Since the fate of &lt;a href="https://evertpot.com/ecmascript-4-the-missing-version/" rel="noopener noreferrer"&gt;ECMAScript 4&lt;/a&gt; was uncertain, and many developers lacked (and still lack to this day) proper typing, JSDoc started adding this much-needed typing to JavaScript. This contributed to its popularity, and as a result, many other tools began to rely on the JSDoc syntax.&lt;/p&gt;

&lt;p&gt;An interesting fact is that while the JSDoc documentation provides a list of basic tags, the specification itself allows developers to expand the list based on their needs. Tools built on top of JSDoc leverage this flexibility to the maximum by adding their own custom tags. Therefore, encountering a &lt;em&gt;pure&lt;/em&gt; JSDoc setup is a relatively rare occurrence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgzwc0tr4238f2f0u3499.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgzwc0tr4238f2f0u3499.png"&gt;&lt;/a&gt;&lt;br&gt;TypeScript to JSDoc. Function typing.
  &lt;/p&gt;

&lt;p&gt;The most well-known tools that rely on JSDoc are &lt;a href="https://github.com/google/closure-compiler" rel="noopener noreferrer"&gt;Closure Compiler&lt;/a&gt; (not to be confused with the Closure programming language) and &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;. Both of these tools can help make your JavaScript &lt;em&gt;typed&lt;/em&gt;, but they approach it differently. Closure Compiler primarily focuses on &lt;em&gt;enhancing&lt;/em&gt; your &lt;code&gt;.js&lt;/code&gt; files by adding typing through JSDoc annotations (after all, they are just &lt;em&gt;comments&lt;/em&gt;), while TypeScript is designed for &lt;code&gt;.ts&lt;/code&gt; files, introducing its own well-known TypeScript constructs such as &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;interface&lt;/code&gt;, &lt;code&gt;enum&lt;/code&gt;, &lt;code&gt;namespace&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;Not from its inception, but starting from &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#errors-in-js-files-with---checkjs" rel="noopener noreferrer"&gt;version 2.3&lt;/a&gt;, TypeScript began allowing something similar to Closure Compiler – checking type annotations in &lt;code&gt;.js&lt;/code&gt; files based on the use of JSDoc syntax. With this version, and with each subsequent version, TypeScript not only added support for JSDoc but also incorporated &lt;a href="https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler" rel="noopener noreferrer"&gt;many of the core tags and constructs&lt;/a&gt; present in Closure Compiler. This made migration to TypeScript more straightforward. While Closure Compiler is still being updated, used by some teams, and &lt;em&gt;remains the most effective tool for code compression&lt;/em&gt; in JavaScript (if its rules are followed), due to support for checking &lt;code&gt;.js&lt;/code&gt; files and various other updates brought by the TypeScript team, &lt;a href="https://effectivetypescript.com/2023/09/27/closure-compiler/" rel="noopener noreferrer"&gt;Closure Compiler eventually lost to TypeScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From the implementation perspective, incorporating an understanding of JSDoc notation into TypeScript is not a fundamental change. Whether it is TypeScript types or JSDoc types, ultimately, they both become part of the AST (Abstract Syntax Tree) of the executed program. This is convenient for us as developers because all our everyday tools, such as ESLint (including all its plugins), Prettier, and others, primarily rely on the AST. Therefore, regardless of the file extensions we use, our favorite plugins can continue to work in both &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.ts&lt;/code&gt; files (with some exceptions, of course).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbpeh9reqo79qw0uc1wy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbpeh9reqo79qw0uc1wy1.png"&gt;&lt;/a&gt;&lt;br&gt;TypeScript to JSDoc. Type Declaration.
  &lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Experience
&lt;/h2&gt;

&lt;p&gt;When adding typing to JavaScript code using JSDoc, it is advisable to use additional tools that enhance the development experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/eslint-plugin-jsdoc" rel="noopener noreferrer"&gt;eslint-plugin-jsdoc&lt;/a&gt; is a JSDoc plugin for ESLint. This plugin reports errors in case of invalid JSDoc syntax usage and helps standardize the written JSDoc. An important setting for this plugin is the &lt;a href="https://github.com/gajus/eslint-plugin-jsdoc/blob/HEAD/docs/settings.md#mode" rel="noopener noreferrer"&gt;mode&lt;/a&gt; option, which offers one of the following values: &lt;code&gt;typescript&lt;/code&gt;, &lt;code&gt;closure&lt;/code&gt; (referring to Closure Compiler), or &lt;code&gt;jsdoc&lt;/code&gt;. As mentioned earlier, JSDoc can vary, and this option allows you to specify which JSDoc tags and syntax to use. The default value is &lt;code&gt;typescript&lt;/code&gt; (though this has not always been the case), which, given TypeScript's dominance over other tools that work with JSDoc, seems like a sensible choice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhv9mm3xc2kp44uyfj3ya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhv9mm3xc2kp44uyfj3ya.png"&gt;&lt;/a&gt;&lt;br&gt;TypeScript to JSDoc. Type casting.
  &lt;/p&gt;

&lt;p&gt;It is also important to choose a tool for analyzing the type annotations written in JSDoc, and in this case, it will be &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;. This might sound strange because, in this article, it seems like we are discussing its replacement. However, we are not using TypeScript for its &lt;em&gt;primary&lt;/em&gt; purpose – our files still have the &lt;code&gt;.js&lt;/code&gt; extension. We will only use TypeScript as a type checking linter. In most projects where TypeScript is used &lt;em&gt;fully&lt;/em&gt;, there is typically a &lt;code&gt;build&lt;/code&gt; script responsible for compiling &lt;code&gt;.ts&lt;/code&gt; files into &lt;code&gt;.js&lt;/code&gt;. In the case of using TypeScript as a linting tool, instead of a &lt;code&gt;build&lt;/code&gt; command handling compilation, you will have a command for linting your types.&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;// package.json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lint: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="s2"&gt;tsc --noEmit&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;If, in the future, a tool emerges that &lt;em&gt;surpasses&lt;/em&gt; TypeScript as a linting tool for project typing, we can always replace it in this script.&lt;/p&gt;

&lt;p&gt;To make this script work correctly, you need to create a &lt;a href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html" rel="noopener noreferrer"&gt;tsconfig.json&lt;/a&gt; file in your project or add additional parameters to this script. These parameters include &lt;a href="https://www.typescriptlang.org/tsconfig#allowJs" rel="noopener noreferrer"&gt;allowJs&lt;/a&gt; and &lt;a href="https://www.typescriptlang.org/tsconfig#checkJs" rel="noopener noreferrer"&gt;checkJs&lt;/a&gt;, which allow TypeScript to check code written in &lt;code&gt;.js&lt;/code&gt; files. In addition to these parameters, you can enable many others. For example, to make type checking stricter, you can use &lt;a href="https://www.typescriptlang.org/tsconfig#strict" rel="noopener noreferrer"&gt;strict&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess" rel="noopener noreferrer"&gt;noUncheckedIndexedAccess&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes" rel="noopener noreferrer"&gt;exactOptionalPropertyTypes&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#noPropertyAccessFromIndexSignature" rel="noopener noreferrer"&gt;noPropertyAccessFromIndexSignature&lt;/a&gt;, and more. TypeScript will rigorously check your code even if you are using &lt;code&gt;.js&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;The TypeScript team consistently enhances the functionality of TypeScript when working with JSDoc. With almost every release, they introduce both fixes and new features. The same applies to code editors. Syntax highlighting and other DX features provided by TypeScript when working with &lt;code&gt;.ts&lt;/code&gt; files also work when dealing with &lt;code&gt;.js&lt;/code&gt; files using JSDoc. Although there are occasional instances where support for certain JSDoc features may come later, many GitHub issues labeled with JSDoc in the TypeScript backlog indicate that the TypeScript team continues to work on improving JSDoc support.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhgb3ki94wctmaqrluy06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhgb3ki94wctmaqrluy06.png"&gt;&lt;/a&gt;&lt;br&gt;TypeScript to JSDoc. Generics.
  &lt;/p&gt;

&lt;p&gt;Many might mention the nuance that when using TypeScript solely for &lt;code&gt;.js&lt;/code&gt; files, you are deprived of the ability to use additional constructs provided by TypeScript. For example: &lt;a href="https://www.typescriptlang.org/docs/handbook/enums.html" rel="noopener noreferrer"&gt;Enums&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/docs/handbook/namespaces.html" rel="noopener noreferrer"&gt;Namespaces&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties" rel="noopener noreferrer"&gt;Class Parameter Properties&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/docs/handbook/2/classes.html#abstract-classes-and-members" rel="noopener noreferrer"&gt;Abstract Classes and Members&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/docs/handbook/decorators.html" rel="noopener noreferrer"&gt;Experimental (!) Decorators&lt;/a&gt;, and others, as their syntax is only available in files with the &lt;code&gt;.ts&lt;/code&gt; extension.&lt;/p&gt;

&lt;p&gt;Again, for some, this may seem like a drawback, but for others, it could be considered a benefit, as most of these constructs have their drawbacks. Primarily, during TypeScript compilation to JavaScript, anything related to types &lt;em&gt;simply disappears&lt;/em&gt;. In the case of using the aforementioned constructs, all of them are &lt;em&gt;translated&lt;/em&gt; into less-than-optimal JavaScript code. If this does not sound compelling enough for you to refrain from using them, you can explore the downsides of each of these constructs on your own, as there are plenty of articles on the Internet discussing these issues.&lt;/p&gt;

&lt;p&gt;Overall, the use of these constructs is generally considered an anti-pattern. On most of my projects where I use TypeScript to its full extent (with all my code residing in &lt;code&gt;.ts&lt;/code&gt; files), I always use a custom ESLint rule:&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;// eslint.config.js&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('eslint').Linter.FlatConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&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-restricted-syntax&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="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="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TSEnumDeclaration,TSModuleDeclaration,TSParameterProperty,ClassDeclaration[abstract=true],Decorator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TypeScript shit is forbidden.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This rule prohibits the use of TypeScript constructs that raise concerns.&lt;/p&gt;

&lt;p&gt;When considering what remains of TypeScript when applying this ESLint rule, essentially, only the &lt;em&gt;typing&lt;/em&gt; aspect remains. In this context, when using this rule, leveraging &lt;a href="https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html" rel="noopener noreferrer"&gt;JSDoc tags and syntax provided by TypeScript&lt;/a&gt; for adding typing to &lt;code&gt;.js&lt;/code&gt; files is almost indistinguishable from using TypeScript with &lt;code&gt;.ts&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F94bzt4j78lfryevo2maj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F94bzt4j78lfryevo2maj.png"&gt;&lt;/a&gt;&lt;br&gt;TypeScript to JSDoc. Class and its members.
  &lt;/p&gt;

&lt;p&gt;As mentioned earlier, most tools rely on AST for their operations, including TypeScript. TypeScript does not care whether you define types using TypeScript's keywords and syntax or JSDoc tags supported by TypeScript. This principle also applies to ESLint and its plugins, including the &lt;a href="https://typescript-eslint.io/getting-started/" rel="noopener noreferrer"&gt;typescript-eslint&lt;/a&gt; plugin. This means that we can use this plugin and its powerful rules to check typing even if the entire code is written in &lt;code&gt;.js&lt;/code&gt; files (provided you enabled the &lt;a href="https://typescript-eslint.io/packages/parser" rel="noopener noreferrer"&gt;appropriate parser&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Unfortunately, a significant drawback when using these tools with &lt;code&gt;.js&lt;/code&gt; files is that some parts of these tools, such as specific rules in typescript-eslint, rely on the use of specific TypeScript keywords. Examples of such rules include &lt;a href="https://typescript-eslint.io/rules/explicit-function-return-type/" rel="noopener noreferrer"&gt;explicit-function-return-type&lt;/a&gt;, &lt;a href="https://typescript-eslint.io/rules/explicit-member-accessibility/" rel="noopener noreferrer"&gt;explicit-member-accessibility&lt;/a&gt;, &lt;a href="https://typescript-eslint.io/rules/explicit-member-accessibility/" rel="noopener noreferrer"&gt;no-unsafe-return&lt;/a&gt;, and others that are tied explicitly to TypeScript keywords. Fortunately, there are not many such rules. Despite the fact that these rules could be rewritten to use AST, the development teams behind these rules are currently reluctant to do so due to the increased complexity of support when transitioning from using keywords to AST.&lt;/p&gt;

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

&lt;p&gt;JSDoc, when used alongside TypeScript as a linting tool, provides developers with a powerful means of typing &lt;code&gt;.js&lt;/code&gt; files. Its functionality does not lag significantly behind TypeScript when used to its &lt;em&gt;full potential&lt;/em&gt;, keeping all the code in &lt;code&gt;.ts&lt;/code&gt; files. Utilizing JSDoc allows developers to introduce typing into a pure JavaScript project right now, without delaying it as a distant dream of a full migration to TypeScript (which most likely will never happen).&lt;/p&gt;

&lt;p&gt;Many mistakenly spend too much time critiquing the JSDoc syntax, deeming it ugly, especially when compared to TypeScript. It is hard to argue otherwise, TypeScript's syntax does indeed look much more concise. However, what is truly a mistake is engaging in empty discussions about syntax instead of taking any action. In the end, you will probably want to achieve a similar result, as shown in the screenshot below. Performing such a migration is significantly easier and more feasible when transitioning from code that already has typing written in JSDoc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F9zofrpuv5oypfho5hngk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9zofrpuv5oypfho5hngk.png"&gt;&lt;/a&gt;&lt;br&gt;JSDoc to TypeScript. Possibly a long-awaited migration. React Component.
  &lt;/p&gt;

&lt;p&gt;By the way, many who label the JSDoc syntax as ugly, while using TypeScript as their sole primary tool, after such remarks, nonchalantly return to their &lt;code&gt;.ts&lt;/code&gt; files, fully embracing TS Enums, TS Parameter Properties, TS Experimental (!) Decorators, and other TS constructs that might raise questions. Do they truly believe they are on the right side?&lt;/p&gt;

&lt;p&gt;Most of the screenshots were taken from the migration of &lt;code&gt;.ts&lt;/code&gt; files to &lt;code&gt;.js&lt;/code&gt; while preserving type functionality in my library &lt;a href="https://github.com/what1s1ove/form-payload" rel="noopener noreferrer"&gt;form-payload&lt;/a&gt; (here is the &lt;a href="https://github.com/what1s1ove/form-payload/pull/70" rel="noopener noreferrer"&gt;PR&lt;/a&gt;). Why did I decide to make this migration? Because I wanted to. Although this is far from my only experience with such migrations. Interestingly, the sides of migrations often change (migrations from &lt;code&gt;.js&lt;/code&gt; to &lt;code&gt;.ts&lt;/code&gt; undoubtedly occur more frequently). Despite my affection for TypeScript and its concise syntax, after several dozen files written/rewritten using JSDoc, I stopped feeling any particular aversion to the JSDoc syntax, as it is &lt;em&gt;just syntax&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Summing up: JSDoc provides developers with real opportunities for gradually improving the codebase without requiring a complete transition to TypeScript from the start of migration. It is essential to remember that the key is not to pray to the TypeScript-God but to start taking action. The ultimate transition to using TypeScript fully is possible, but you might also realize that JSDoc is more than sufficient for successful development, as it has its advantages. For example, here is what a "JSDoc-compiler" might look like:&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;// bundler.js&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;esbuild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;jsMainEntryPoint&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;minify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 👌&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Give it a try! Do not stand still, continually develop your project, and I am sure you will find many other benefits!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>jsdoc</category>
    </item>
    <item>
      <title>The Strictest TypeScript Config</title>
      <dc:creator>Vladyslav Zubko</dc:creator>
      <pubDate>Wed, 13 Dec 2023 09:24:47 +0000</pubDate>
      <link>https://forem.com/what1s1ove/the-strictest-typescript-config-mad</link>
      <guid>https://forem.com/what1s1ove/the-strictest-typescript-config-mad</guid>
      <description>&lt;p&gt;Most people know that to make projects using TypeScript "strict" in terms of typing, you need to enable the &lt;code&gt;"strict": true&lt;/code&gt; option in the &lt;code&gt;tsconfig&lt;/code&gt;. What this option does is enable a multitude of other options, such as &lt;a href="https://www.typescriptlang.org/tsconfig#alwaysStrict"&gt;alwaysStrict&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#strictNullChecks"&gt;strictNullChecks&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#strictBindCallApply"&gt;strictBindCallApply&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#strictFunctionTypes"&gt;strictFunctionTypes&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#strictPropertyInitialization"&gt;strictPropertyInitialization&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#noImplicitAny"&gt;noImplicitAny&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#noImplicitThis"&gt;noImplicitThis&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables"&gt;useUnknownInCatchVariables&lt;/a&gt;. Indeed, all these options will undoubtedly make your TypeScript project stricter.&lt;/p&gt;

&lt;p&gt;However, not everyone knows that in the TypeScript config, there are other options that can more reliably protect your project from type-related errors, which are &lt;em&gt;not yet&lt;/em&gt; automatically included by the &lt;code&gt;strict&lt;/code&gt; option. Let's take a look at these options together to make our projects using TypeScript more robust.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The first option we will explore is called &lt;a href="https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess"&gt;noUncheckedIndexedAccess&lt;/a&gt;. Historically, TypeScript automatically &lt;em&gt;infers&lt;/em&gt; a type if it has grounds to do so. For example, if we manually specify the type of an array while leaving it empty or use an &lt;a href="https://www.typescriptlang.org/glossary#index-signatures"&gt;index signature&lt;/a&gt; for objects. It might seem like TypeScript is doing us a favor, but very often, this can lead to unintended consequences.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess"&gt;noUncheckedIndexedAccess&lt;/a&gt; comes to the rescue. It adds &lt;code&gt;undefined&lt;/code&gt; to any undeclared key of an object or index of an array, prompting additional checks to ensure that you are fully aware of what you are doing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// noUncheckedIndexedAccess: false (default behavior)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&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="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&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;id0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;

&lt;span class="nx"&gt;id0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ✅ but 💥&lt;/span&gt;
&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ✅ but 💥&lt;/span&gt;

&lt;span class="c1"&gt;// noUncheckedIndexedAccess: true&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// number | undefined&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="c1"&gt;// string | undefined&lt;/span&gt;

&lt;span class="nx"&gt;id0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error: 'id0' is possibly 'undefined'.&lt;/span&gt;
&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error: 'username' is possibly 'undefined'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;exactOptionalPropertyTypes&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Next, we have the option &lt;a href="https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes"&gt;exactOptionalPropertyTypes&lt;/a&gt;, which also addresses a long-standing pain point in TypeScript. Specifically, the issue that the &lt;code&gt;?&lt;/code&gt; prefix in object keys serves two purposes – indicating that a field can be &lt;code&gt;undefined&lt;/code&gt; and also signifying that the field might not exist in the object at all (yes, these are two different things).&lt;/p&gt;

&lt;p&gt;With this option enabled, TypeScript retains only one behavior with the &lt;code&gt;?&lt;/code&gt; prefix. Now, it signifies only the absence of a key, not that it could be &lt;code&gt;undefined&lt;/code&gt;. If you need to allow the value to be &lt;code&gt;undefined&lt;/code&gt;, you must specify it explicitly (e.g., &lt;code&gt;hasFriends: string | undefined&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// exactOptionalPropertyTypes: false (default behavior)&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&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="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;hasFriends&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasFriends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasFriends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;

&lt;span class="c1"&gt;// exactOptionalPropertyTypes: true&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasFriends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasFriends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;noPropertyAccessFromIndexSignature&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Concluding the trio of significant options, which are not part of the &lt;code&gt;strict&lt;/code&gt; option but play a crucial role in enforcing stricter typing in TypeScript projects, is the &lt;a href="https://www.typescriptlang.org/tsconfig#noPropertyAccessFromIndexSignature"&gt;noPropertyAccessFromIndexSignature&lt;/a&gt; option.&lt;/p&gt;

&lt;p&gt;There is often a temptation to either write your own &lt;a href="https://www.typescriptlang.org/glossary#index-signatures"&gt;index signature&lt;/a&gt; for an object, even when it seems like there is nothing preventing you from explicitly describing all the keys of the object, or to use index signatures from libraries, as library authors often indulge in them. &lt;code&gt;noPropertyAccessFromIndexSignature&lt;/code&gt; requires the use of bracket notation when accessing keys of objects described through index signatures.&lt;/p&gt;

&lt;p&gt;The goal of this option is to make sure you are absolutely certain about what you are doing. Since nobody likes bracket notation where it can be avoided, this option &lt;em&gt;forces&lt;/em&gt; you to avoid index signatures as much as possible. Indeed, many problems arise from them, and this option aims to mitigate those issues.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// noPropertyAccessFromIndexSignature: false (default behavior)&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&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="na"&gt;key&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MFA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google&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;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wat&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;

&lt;span class="c1"&gt;// noPropertyAccessFromIndexSignature: true&lt;/span&gt;

&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="c1"&gt;// ❌&lt;/span&gt;
&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wat&lt;/span&gt; &lt;span class="c1"&gt;// ❌&lt;/span&gt;
&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kind&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// ✅, but it's better to avoid index signatures and describe all type keys explicitly&lt;/span&gt;
&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wat&lt;/span&gt;&lt;span class="dl"&gt;'&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;By the way, the TypeScript ESLint plugin developers have thoughtfully provided the ability to use this and many other options from the TypeScript config, along with their rules. The &lt;a href="https://typescript-eslint.io/rules/dot-notation/"&gt;@typescript-eslint/dot-notation&lt;/a&gt; rule syncs seamlessly with this option, once again emphasizing that using index signatures is not a good practice.&lt;/p&gt;

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

&lt;p&gt;There are also &lt;a href="https://www.typescriptlang.org/tsconfig#Type_Checking_6248"&gt;other options improving typing&lt;/a&gt; in the TypeScript config that are not automatically enabled with the &lt;code&gt;strict&lt;/code&gt; option, but they are not as crucial as the three mentioned above.&lt;/p&gt;

&lt;p&gt;For all new projects where you will be using TypeScript, I recommend starting with a TypeScript config where the &lt;code&gt;strict&lt;/code&gt; option is enabled along with the additional three options we discussed earlier: &lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt;, &lt;code&gt;exactOptionalPropertyTypes&lt;/code&gt;, and &lt;code&gt;noPropertyAccessFromIndexSignature&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noUncheckedIndexedAccess"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exactOptionalPropertyTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noPropertyAccessFromIndexSignature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or try enabling them in an existing project, but be prepared to uncover many areas where you might have taken shortcuts 😉&lt;/p&gt;

&lt;p&gt;All these options, by imposing additional constraints and promoting more correct coding practices, will help make your project more reliable. This simplifies both its maintenance in the long run and the quicker detection of incorrect behavior in your code.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How We Started Managing BSA Delivery Processes on GitHub</title>
      <dc:creator>Vladyslav Zubko</dc:creator>
      <pubDate>Sat, 25 Nov 2023 22:00:00 +0000</pubDate>
      <link>https://forem.com/what1s1ove/how-we-started-managing-bsa-delivery-processes-on-github-3jc</link>
      <guid>https://forem.com/what1s1ove/how-we-started-managing-bsa-delivery-processes-on-github-3jc</guid>
      <description>&lt;p&gt;Hello everyone! I am Vladyslav. At the beginning of 2022, I was offered the role of Delivery Head of BSA (Binary Studio Academy). &lt;a href="https://academy.binary-studio.com/"&gt;Binary Studio Academy&lt;/a&gt; is a free, international course that transforms people with basic programming language knowledge into &lt;em&gt;true&lt;/em&gt; beginner engineers.&lt;/p&gt;

&lt;p&gt;From a delivery perspective, each Academy consists of several specific stages, each of which comprises a varying number of checklists that need to be completed for the stage to be considered successfully completed. Additionally, the Academy involves a substantial amount of documentation for various roles within it, as well as a wealth of content ranging from concise lecture summaries to automated tests that assess homework completion of these lectures.&lt;/p&gt;

&lt;p&gt;Despite having two years of experience within the Academy at the time I received this role, I still felt the need for more examples and checklists for all the actions I needed to take at each stage of the Academy. Documentation was not always helpful because we all know that documentation has a tendency to become outdated or get lost when stored in different places. Establishing a process where everyone understands what they need to do, having a single source of truth, and maintaining a history of past Academies became my top priority for change.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Was
&lt;/h2&gt;

&lt;p&gt;Before diving into the current process we use, I would like to start with what we had before. We had a significant number of tools at our disposal. Here are the key ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://trello.com/"&gt;&lt;strong&gt;Trello&lt;/strong&gt;&lt;/a&gt;. Was our tool for managing task boards. Depending on who held the position of Delivery Head of BSA, boards were created by different individuals, sometimes not even within the organization but on personal accounts. This led to the problem that there was no real history of the boards. As a result, for almost every Academy, we had to recall the number of tasks that needed to be completed at each stage. While everyone usually understood what needed to be done, without a clear list of tasks, things were occasionally forgotten.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd27eou4mvhuwii2hrtqs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd27eou4mvhuwii2hrtqs.png" alt="BSA Trello" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.google.com/docs/about/"&gt;&lt;strong&gt;Google Docs&lt;/strong&gt;&lt;/a&gt;. This tool was used both for storing general information, such as documentation and lecture content, and for collecting information required for each Academy. Despite using &lt;a href="https://www.google.com/drive/"&gt;Google Drive&lt;/a&gt; and keeping most of the information in one place, there was still a situation where some documents in each Academy were created on the fly to test something or provide a rough draft, and eventually, those documents could become quite valuable. Sometimes, these documents were created not in the BSA Google Drive but in someone's personal account which led to the occasional loss of such documents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetnkyaubaqr7etrp6yqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetnkyaubaqr7etrp6yqc.png" alt="BSA Google Docs" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.google.com/sheets/about/"&gt;&lt;strong&gt;Google Sheets&lt;/strong&gt;&lt;/a&gt;. They were mainly used for collecting statistics but created similar issues as Google Docs, with documents sometimes being scattered across different accounts and losing some degree of organization and accessibility.&lt;/p&gt;

&lt;p&gt;While Google Docs/Sheets in combination with Google Drive are decent tools for storing information in one place, their functionality sometimes fell short of providing convenient management. For example, the process of reviewing changes, especially when it involves multiple people, could become increasingly challenging. The more individuals were involved in working on a single document, the harder it was to control the process.&lt;/p&gt;

&lt;p&gt;Another significant problem was related to document version history. Sometimes it was easier to create a new document than to maintain it for each Academy. As a result, the appearance of certain stages or lectures as they were in the past often got lost. Occasionally, it was crucial to view how certain documents looked in their previous states.&lt;/p&gt;

&lt;p&gt;Another challenge for us was that while all the content was stored in Google Docs, it was often written using &lt;a href="https://www.markdownguide.org/"&gt;Markdown&lt;/a&gt;. Although Google Docs has &lt;a href="https://support.google.com/docs/answer/12014036"&gt;partial support for Markdown&lt;/a&gt;, it was insufficient for our needs, and we had to store raw Markdown in Google Docs. This experience was not the most pleasant because things often broke or did not display as intended due to a lack of full Markdown support.&lt;/p&gt;

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

&lt;p&gt;We also had other tools in use, such as &lt;a href="https://miro.com/"&gt;Miro&lt;/a&gt;. This tool was primarily used for visualizing certain process flows, like document change approval processes. Or at some point, we considered using boards in &lt;a href="//asana.com"&gt;Asana&lt;/a&gt; because non-delivery processes were managed in that tool. However, when we contemplated the move to Asana, I decided to explore other potential tools. After reading many articles and conducting some research, especially on emerging tools, my attention turned to something unusual.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Is Now
&lt;/h2&gt;

&lt;p&gt;I did not have the goal of using just one tool, although that is usually the most convenient option. Providing access to a single tool is much easier than granting access to multiple tools, especially given the volume of people involved in each Academy. Reflecting on what tool we could use to cover all our needs and after reading many articles about the experiences of other products, I chose &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;. It seemed ideal to me in terms of what it could offer us – version history, boards, and a clear process for accepting changes.&lt;/p&gt;

&lt;p&gt;A significant factor in my decision was observing GitHub's development over the past six months. I was confident that while not all the features GitHub offered looked perfect at the time, the GitHub team would continue to refine and improve them. Roadmaps of GitHub features, such as the &lt;a href="https://github.com/orgs/github/projects/4247"&gt;GitHub Actions Roadmap&lt;/a&gt;, were helpful to me. I am a fan of &lt;a href="https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions"&gt;GitHub Actions&lt;/a&gt; and enjoy keeping an eye on what is coming soon. Some other GitHub features, like &lt;a href="https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects"&gt;GitHub Projects&lt;/a&gt;, also have &lt;a href="https://github.com/orgs/github/projects/4247"&gt;open roadmaps&lt;/a&gt; that provide insights into upcoming updates in those features.&lt;/p&gt;

&lt;p&gt;Now, let's discuss the core functionality of GitHub that we use for managing delivery processes in the Academy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.github.com/en/get-started/using-git/about-git"&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/a&gt;. Since GitHub is primarily about version control, we immediately resolved the issue of any file getting lost. Additionally, we now have a clear version history for every file, easily accessible through the familiar to all GitHub interface.&lt;/p&gt;

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

&lt;p&gt;Certainly, version history is not the only advantage of Git. In general, it provides a robust toolkit that we make use of. For instance, the ability to quickly revert to a specific version or the conflict resolution functionality when someone starts editing the same file are valuable features. GitHub, in combination with Git, has proven to be a highly convenient tool for managing textual content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.markdownguide.org/"&gt;&lt;strong&gt;Markdown&lt;/strong&gt;&lt;/a&gt;. Since a substantial portion of the content we use in the Academy is written with Markdown syntax, we no longer needed to come up with various workarounds as we did when using Google Docs. Finally, we were able to use &lt;code&gt;.md&lt;/code&gt; files, which are the standard format for Markdown syntax. We no longer had to worry about the output of information for students being different from what we could see in Google Docs because all the content was stored in files with the appropriate extension.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.github.com/en/issues/tracking-your-work-with-issues/about-issues"&gt;&lt;strong&gt;Issues&lt;/strong&gt;&lt;/a&gt; &amp;amp; &lt;a href="https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects"&gt;&lt;strong&gt;Projects&lt;/strong&gt;&lt;/a&gt;. We started using GitHub Projects as our primary board for each Academy. GitHub Projects are closely tied to GitHub Issues, which serve as tasks on the board. In addition, GitHub Projects itself offers a lot of useful functionality, such as various views and filters that allow you to easily and conveniently display information based on your specific criteria.&lt;/p&gt;

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

&lt;p&gt;To be honest, when we first started using GitHub Projects as our main board, not everyone, including myself, was initially thrilled about it. At the outset, we missed some convenient features that Trello offered, such as due dates or easy Slack notification setup for board actions. This was during our first Academy where we began using GitHub as our primary tool for managing delivery processes in the Academy. Since then, GitHub has created a lot of useful documentation, such as how to add automation with GitHub Actions, and they have also introduced many new features, like &lt;a href="https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields"&gt;custom fields&lt;/a&gt; for Issues, which can be used in various ways. For instance, we started using them to store due dates. By the time we got to the second Academy where we used GitHub as our primary tool, it covered everything we needed and even more.&lt;/p&gt;

&lt;p&gt;Once again, because GitHub is fundamentally about version control, GitHub Projects had a simple but crucial feature for us – project archiving. It might seem like a small detail, but the issue of losing boards, which we experienced when using Trello, could be critically important at times. Storing everything within a single GitHub repository, from boards to content, minimized the risk of losing anything.&lt;/p&gt;

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

&lt;p&gt;All our checklists migrated into Issues. With all the statistical highlights, including how much is left to complete an issue and quick navigation to the relevant lectures and &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request"&gt;pull requests&lt;/a&gt;, Issues seemed much more convenient than what tickets in Trello offered. Primarily, this was because we used two separate tools, Trello for tickets and Google Docs/Sheets for content. These two tools did not integrate seamlessly, and each time, we had to set up convenient interactions between them for every ticket.&lt;/p&gt;

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

&lt;p&gt;Since Issues are also about clear communication, we agreed with the team that a significant portion of Academy-related communication would take place within Issues. This was primarily for historical purposes, but also because using Issues for this purpose proved to be very convenient. Any internal references, such as to pull requests, were transformed by GitHub into concise text. Additionally, it linked Issues and Pull Requests, making the history of changes and decision-making clearer and more aesthetically pleasing than ever before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhb13hkugn9f1dqftl9hn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhb13hkugn9f1dqftl9hn.png" alt="BSA Issue Comments" width="800" height="784"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates"&gt;&lt;strong&gt;Issues Templates&lt;/strong&gt;&lt;/a&gt;. To standardize all the issues and never forget the checklists that needed to be completed in them, we made use of the Issues Templates feature. One significant advantage is that an issues template is just a text file, like all other files in the repository. This means it benefits from all the powerful functionality of Git, has its own version history, and in case of any issues, you can easily revert it to a specific version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4chcpg8m43nwgnp1ne4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4chcpg8m43nwgnp1ne4.png" alt="BSA Issue Templates" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request"&gt;&lt;strong&gt;Pull Requests&lt;/strong&gt;&lt;/a&gt;. With Google Docs/Sheets, the process of accepting changes to existing lecture content and documentation, as well as creating new documents, was not particularly convenient. The main inconvenience was assigning permissions to users. Since lecture and content owners changed quite frequently in our Academy, keeping track of it all was challenging. It was especially tricky when the change process depended on multiple people. Unfortunately, Google Docs/Sheets did not offer a convenient way to implement a change approval workflow for such cases.&lt;/p&gt;

&lt;p&gt;The familiar process of proposing changes through pull requests was well-received by the entire team. No one needed extensive explanations about how it works because everyone had experience with it. Configuring content ownership through &lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners"&gt;code owners&lt;/a&gt; resolved the issue of content authorship and whose approvals were needed to get changes into the Academy.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6of0co0g28enatvbucr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6of0co0g28enatvbucr3.png" alt="BSA PRs" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.github.com/en/actions"&gt;&lt;strong&gt;GitHub Actions&lt;/strong&gt;&lt;/a&gt;. At some point, we realized the importance of automation. We started with linters that run on every pull request. Our linters help us maintain a consistent style throughout all our content and serve as the first line of defense that everyone must pass through when they want to introduce changes to the Academy.&lt;/p&gt;

&lt;p&gt;Here is a list of our main linters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://remark.js.org/"&gt;&lt;strong&gt;remark&lt;/strong&gt;&lt;/a&gt;. Primarily, this is a linter for Markdown. Additionally, thanks to its numerous plugins, it allows us to perform additional checks for grammatical mistakes within the content itself. Before using this linter, our content was not scrutinized to this extent.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://prettier.io/"&gt;&lt;strong&gt;prettier&lt;/strong&gt;&lt;/a&gt;. A code formatter and linter for code formatting. It ensures that all our files have a consistent appearance.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ls-lint.org/"&gt;&lt;strong&gt;ls-lint&lt;/strong&gt;&lt;/a&gt;. A linter for file and folder names. Again, we aim for uniformity in this aspect as well.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/editorconfig-checker/editorconfig-checker.javascript"&gt;&lt;strong&gt;editorconfigchecker&lt;/strong&gt;&lt;/a&gt;. A linter that checks files for compliance with &lt;a href="https://editorconfig.org/"&gt;editorconfig&lt;/a&gt; rules. Another linter that helps maintain consistency in the format of all files.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://commitlint.js.org/"&gt;&lt;strong&gt;commitlint&lt;/strong&gt;&lt;/a&gt; &amp;amp; &lt;a href="https://danger.systems/js/"&gt;&lt;strong&gt;dangerjs&lt;/strong&gt;&lt;/a&gt;. Linters that help maintain consistency in all user-provided information related to Git and GitHub (commits, branch names, PR titles, etc.).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Since we aimed to reduce our reliance on Google Docs/Sheets wherever possible, especially in cases where we could extract information from existing data instead of conducting manual audits of lectures in Google Sheets for each Academy, we decided to write a script that automatically compiles statistics based on the information already present in the repository. This script was connected to an GitHub Actions that triggers and updates the statistics every time new changes are pushed to the main branch.&lt;/p&gt;

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

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


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

&lt;p&gt;&lt;a href="https://docs.github.com/en/organizations/organizing-members-into-teams/about-teams"&gt;&lt;strong&gt;Teams&lt;/strong&gt;&lt;/a&gt;. GitHub has an excellent system of teams and permissions that continues to evolve. The most convenient thing is that by adding an Academy participant to one of the teams, the participant automatically gained access to all the necessary repositories and Projects, of which we have quite a few, while only having the permissions they needed.&lt;/p&gt;

&lt;p&gt;Since some of our content, such as starters for lecture homework or lecture auto-checks, was already in GitHub repositories, setting up teams and permissions took minimal time because we essentially had everything ready prior to the creation of the Academy delivery process management repository.&lt;/p&gt;

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


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list above only enumerates the main features we use to manage our delivery processes at the Academy. I may have missed some aspects because some of these features have become so familiar that it is sometimes hard to remember how we managed processes without them in the past.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Gets Better
&lt;/h2&gt;

&lt;p&gt;To be honest, I wanted to write this article after the first Academy when we started actively using GitHub as the primary tool for managing the delivery processes of the Academy. However, I kept delaying it for various reasons. One of the reasons was that I was not entirely satisfied with how we worked around some limitations that existed at the time. For example, as mentioned earlier, we now use &lt;a href="https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields"&gt;custom fields&lt;/a&gt; for setting due dates in issues. Before this feature, we had to set due dates directly in the issue body. While this approach worked, it did not look as elegant as due dates in Trello. Nevertheless, even with these workarounds for limitations at the time, we still liked GitHub better. Moreover, we knew that these limitations would soon be addressed, and GitHub with all its features, would become even better. Currently, we do not feel like we are missing anything from the old set of tools we used.&lt;/p&gt;

&lt;p&gt;GitHub is constantly evolving, and one of the recent innovations we want to try in the next Academy is called "&lt;a href="https://docs.github.com/en/issues/planning-and-tracking-with-projects/managing-your-project/managing-project-templates-in-your-organization"&gt;Project Templates&lt;/a&gt;". I think the name itself makes it clear what this feature entails. Currently, for each Academy, we need to create a specific set of issues that always repeats. While we never lose the content of these issues because we use &lt;a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates"&gt;issue templates&lt;/a&gt;, it is still repetitive work that needs to be done for every Academy. No one likes to do the same thing over and over again, and project templates were created precisely to automate this task.&lt;/p&gt;

&lt;p&gt;The project templates feature is just one example. As mentioned earlier, because GitHub develops features using an open-source development approach, anyone interested can keep track of upcoming feature updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;GitHub has long ceased to be a tool exclusively for developers. All the toolsets that appear in GitHub allow it to be used for more than just storing code history. Different companies find various uses for it. From managing an open-source blog to hosting a podcast website (by the way, they store all their recordings in repositories).&lt;/p&gt;

&lt;p&gt;Some readers might suggest that similar behavior could be achieved by continuing to use Trello and Google Docs/Sheets while adding stricter requirements and constraints. I partly agree with that, but that approach did not work for us. It is precisely because everything in GitHub is integrated, interconnected, and complements each other seamlessly that there's no desire to create anything on a personal account, as was the case with our old tools. Not to mention the additional automation, from grammar mistakes linting to automatic statistics generation, that GitHub provides.&lt;/p&gt;

&lt;p&gt;Undoubtedly, we are pleased with the fact that we now manage our delivery processes in GitHub, and the statistics we collect from people participating in the Academy are a testament to its effectiveness.&lt;/p&gt;

&lt;p&gt;Before GitHub became our main tool:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyc7rlfgqb20z536gfc2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyc7rlfgqb20z536gfc2p.png" alt="Internal Statistic Before" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After GitHub became our main tool:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypuwuns6kw5ojsp1b12e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypuwuns6kw5ojsp1b12e.png" alt="Internal Statistic After" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While we have not completely eliminated Google Docs/Sheets (although we now use &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt; more for this purpose. Yes-yes, one more tool…), it's often easier to quickly create a new MVP for statistics in Google Sheets than to immediately start implementing some logic in GitHub. However, we aim to keep all the essential functionality within GitHub, which serves as the primary tool for controlling all of the Academy's delivery processes.&lt;/p&gt;

&lt;p&gt;Coming into the role of Delivery Head of BSA, I was not tasked with establishing a process where every participant understood what they needed to do. While I did not have an exact checklist at that time outlining what each participant should do at each stage, I believe that after 1-2 Academies, I would have formed a similar checklist for myself, and I would have felt confident. The problem is that most likely, I would have been the only one that felt confident with this process. Perhaps for the next people who will support the Academy afterward, it would still not be entirely clear, just as it was for me in the beginning.&lt;/p&gt;

&lt;p&gt;Quoting the words of Jimmy Carter, the 39th president of the USA, from my favorite movie "&lt;a href="https://en.wikipedia.org/wiki/Miracle_(2004_film)"&gt;Miracle&lt;/a&gt;": "&lt;em&gt;We've always had a faith that the days of our children would be better than our own&lt;/em&gt;", by introducing tools like GitHub and all the other innovations into the Academy, which I have implemented and continue to implement, I wanted to facilitate the experience of participating in the Academy for both the current generation and all those who come after us.&lt;/p&gt;

&lt;p&gt;What the ideal end of the Academy looks like to me:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqh6ur84bupupcs993j8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqh6ur84bupupcs993j8.png" alt="BSA Mailstouns" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>management</category>
      <category>projectmanagement</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>JavaScript Naming Conventions are Important</title>
      <dc:creator>Vladyslav Zubko</dc:creator>
      <pubDate>Mon, 13 Nov 2023 22:00:00 +0000</pubDate>
      <link>https://forem.com/what1s1ove/javascript-naming-conventions-are-important-45n</link>
      <guid>https://forem.com/what1s1ove/javascript-naming-conventions-are-important-45n</guid>
      <description>&lt;p&gt;&lt;strong&gt;IMPORTANT NOTE: The latest updates to the article and changelog can be found by following the link to the &lt;a href="https://whatislove.dev/articles/javascript-naming-conventions-are-important/"&gt;original article publication&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is no secret that developers have to ponder over numerous everyday tasks. Part of their thoughts is always dedicated to various routine matters, such as "In which module should I place this function?", "&lt;em&gt;How should I name this variable?&lt;/em&gt;", or "What should this variable do?". Despite these questions appearing simple and trivial, they consistently consume mental resources. However, if there are ways to simplify this process by automating some routine tasks, thereby focusing attention on more critical matters, it undoubtedly makes sense to take advantage of them.&lt;/p&gt;

&lt;p&gt;In this context, naming conventions play a crucial role. Acquiring knowledge and employing these conventions judiciously contribute to enhanced code readability, simplifying comprehension, and reducing the developer's cognitive load. However, not all developers are aware of, and sometimes forget, how to correctly apply these conventions, mindlessly diverting their attention to seemingly more critical matters. This, in turn, complicates the readability and understanding of their code, making ostensibly "more critical" tasks more intricate than they could actually be.&lt;/p&gt;

&lt;p&gt;Below is a screenshot from a real project I had the opportunity to work on. Take note of each import. Try to &lt;em&gt;guess&lt;/em&gt;, based on the names, what item we can obtain from each of the imports.&lt;/p&gt;

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

&lt;p&gt;In this article, we will explore most of them, learning or reminding ourselves which principles are best to follow when choosing names for the constructs you write. This will help both you and anyone who works with your code in the future – whether it is your team or &lt;em&gt;yourself&lt;/em&gt; after some time – avoid &lt;em&gt;guesswork&lt;/em&gt; and enhance the readability of your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;JavaScript Naming Conventions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This article will consist of a set of naming recommendations. I would not want you to perceive them as the sole truth. Firstly, it is not entirely the case, as most recommendations come with a disclaimer that there are numerous exceptions, hinting that the conventions themselves do not cover all cases. Secondly, while most recommendations are accepted in the JavaScript community, not everyone follows them for various reasons, and some recommendations are either partially or significantly modified to suit specific teams.&lt;/p&gt;

&lt;p&gt;The main message of the article is that each project should establish its naming conventions, whether they align with widely adopted ones or are unique to your team. The crucial aspect is to have conventions and adhere to them.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;General Rules&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;On the internet, there is a considerable number of articles written about best naming practices. Well-known conventions emphasize that a name should be short and, more importantly, &lt;strong&gt;understandable&lt;/strong&gt;. The name should be specific, correspond to the context in which it is used, and convey the meaning of the code at a glance. In reality, these conventions can and should be applied not only when working with JavaScript but also with any programming language. In these general rules, I would like to focus on some specific details in conventions that are widely known but often forgotten or not fully adhered to.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Uniformity.&lt;/strong&gt; In JavaScript projects, there are numerous conventions, but the most valuable one to adhere to is maintaining a consistent coding style within a single project. Individuals involved in different projects know better than anyone that writing styles can vary significantly between projects.&lt;/p&gt;

&lt;p&gt;Situations often arise where different parts of an application are developed by different teams or use different technologies in their development. Naming conventions may differ based on the chosen programming language or the preferences of the development team. Despite these differences, different parts of the application need to interact with each other, such as data exchange between the frontend and backend. For example, the naming style for data requested from the backend might differ from the style used in the frontend code.&lt;/p&gt;

&lt;p&gt;Despite the convention in the JavaScript language to write in &lt;code&gt;camelCase&lt;/code&gt;, it is worth noting that nothing is preventing the use of, for instance, &lt;code&gt;snake_case&lt;/code&gt;. As already mentioned, this notation might be more familiar to many other programming languages and some teams. There might be situations where a naming case different from the style of your application starts creeping into your code.&lt;/p&gt;

&lt;p&gt;It is not our place to judge whether using different naming cases is good or bad, as various reasons may drive such choices. However, explicit mixing of two or more naming cases can pose challenges. For new developers joining the project, understanding what is happening and deciding which naming case to use can become quite challenging.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasAccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkHasUserAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;checkIsPageVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasAccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkHasUserAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;checkIsPageVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Also good, if such a naming case is preferred&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;has_access&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check_has_user_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;check_is_page_visible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current_page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;There are several ways to address this issue, ranging from using renaming with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment"&gt;destructuring&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import"&gt;import renaming&lt;/a&gt;, using mapping functions (e.g., &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"&gt;Array.prototype.map()&lt;/a&gt;), and more advanced approaches like utilizing the &lt;a href="https://refactoring.guru/design-patterns/adapter"&gt;Adapter&lt;/a&gt; design pattern.&lt;/p&gt;

&lt;p&gt;The key is to adopt a consistent approach, not only in naming conventions but also in how tasks are accomplished. Whenever possible, prefer a single method for a particular action. Avoid forcing yourself and other developers to spend time and extra mental resources deciding which approach to use. Consider delegating such tasks, especially those related to coding style, to tools like &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;English only&lt;/strong&gt;. Despite the fact that you can use non-Latin letters when writing in JavaScript, it is not recommended to do so. While there will not be any programming errors, it is strongly discouraged to use any languages other than English. Even if you are writing something for yourself, every piece of code has the ability to "live long", and there may come a time when you need to share this code with other developers. For other developers, especially from different countries, it will be difficult to understand what is happening in the code.&lt;/p&gt;

&lt;p&gt;When emphasizing the use of only English, people often think only about keyboard layout. However, one should not forget about abbreviations and the general use of short forms for names. They should only be used with commonly accepted words, such as &lt;code&gt;idx&lt;/code&gt;, &lt;code&gt;err&lt;/code&gt;, &lt;code&gt;evt&lt;/code&gt;, &lt;code&gt;xhr&lt;/code&gt;, &lt;code&gt;src&lt;/code&gt;, and other historically accepted words in the community. In other cases, the use of abbreviations and short forms of words is strongly discouraged, as they often lead to confusion, and deciphering them can take a lot of time.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;新規ユーザーのウェルカムメッセージ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;こんにちは&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usrInf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&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;isAdult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newUserWelcomeMessage&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&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;isAdult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userAge&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;It is also recommended to enable a spell checker in your code editor, which will highlight grammatical errors in words. In many editors it is enabled by default, and for some you may need to install an extension, such as &lt;a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker"&gt;Code Spell Checker&lt;/a&gt; for VS Code. Today's spell checkers are smart enough, and most commonly accepted abbreviations and short forms of words will not be flagged as errors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Not only &lt;code&gt;camelCase&lt;/code&gt;&lt;/strong&gt;. Many resources emphasize using &lt;code&gt;camelCase&lt;/code&gt; notation &lt;em&gt;exclusively&lt;/em&gt; when writing in JavaScript. However, this is not entirely accurate. The recommendation is more about &lt;strong&gt;adhering to the notation used by the language itself&lt;/strong&gt;. While a &lt;em&gt;significant&lt;/em&gt; portion of the JavaScript language is written in &lt;code&gt;camelCase&lt;/code&gt;, it is not universally so. Here are a few examples:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;18&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// camelCase&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&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-Z]&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;i&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// PascalCase&lt;/span&gt;

&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_SAFE_INTEGER&lt;/span&gt; &lt;span class="c1"&gt;// PascalCase + UPPER_SNAKE_CASE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;As we can see, JavaScript incorporates not only &lt;code&gt;camelCase&lt;/code&gt; notation but also some others. All classes and constructor functions in JavaScript are written using &lt;code&gt;PascalCase&lt;/code&gt; notation. When declaring custom classes and constructor functions, it is customary to follow the same naming convention as the language itself. The same applies to constants, representing fixed values. Both built-in JavaScript constants and those created by developers are conventionally named in &lt;code&gt;UPPER_SNAKE_CASE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In contrast to some programming languages where the API is written using various cases without clear distribution, JavaScript's API does not suffer from this issue. Therefore, it is customary to adhere to the conventions present in the language itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Follow &lt;code&gt;readme.md&lt;/code&gt;&lt;/strong&gt;. Suppose you are working with a network request library like &lt;a href="https://www.npmjs.com/package/axios"&gt;axios&lt;/a&gt;, and the library's README recommends using the standard name &lt;code&gt;axios&lt;/code&gt; for imports.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;httpRequester&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;npm:axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Somewhere very far at the bottom of the file&lt;/span&gt;

&lt;span class="nf"&gt;httpRequester&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&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;p&gt;Changing the name from &lt;code&gt;axios&lt;/code&gt; to &lt;code&gt;httpRequester&lt;/code&gt; can cause confusion and errors, as other developers working on the project and expecting the standard name &lt;code&gt;axios&lt;/code&gt; may encounter issues. Therefore, it is important to adhere to the recommendations set in the library's README to ensure compatibility and code understanding.&lt;/p&gt;

&lt;p&gt;At first glance, the example with the &lt;code&gt;axios&lt;/code&gt; library may seem harmless, but similar renaming scenarios can arise with the use of more complex libraries and frameworks deeply integrated into a project. Teams that adopt &lt;em&gt;meaningful&lt;/em&gt; renaming practices will need to create their own documentation because new team members will not find sufficient information in the official documentation to understand the changes in the technology's usage style.&lt;/p&gt;

&lt;p&gt;Typically, &lt;em&gt;meaningful&lt;/em&gt; renaming into something more abstract, is used in conjunction with the &lt;a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle"&gt;dependency inversion principle&lt;/a&gt;. However, it is important to understand the fine line here. You and your team must have a clear understanding of what you are doing and why, as there needs to be a balance in adopting such practices.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No data types&lt;/strong&gt;. It can be tempting to include data types in variable names, but succumbing to this temptation often adds unnecessary semantic load to the name. For instance, using the name &lt;code&gt;arr&lt;/code&gt; for a variable containing an array can lead to conflicts if a variable with the same name is used elsewhere. Moreover, the name &lt;code&gt;arr&lt;/code&gt; does not convey meaningful information. Making the name more specific, like &lt;code&gt;userArr&lt;/code&gt;, is an improvement, but it does not address all the issues.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userNameMinLengthConst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getUser&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;getUniqueUserNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USER_NAME_MIN_LENGTH_COUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getUser&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;getUniqueUserNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;For each language construct, whether built-in or custom data structures, there exists a conventional way to indicate the intended data type of the value. This is reflected in the name of the construct, which should align with both the established community conventions and those within your team. It is advisable to prioritize community conventions, as explaining something widely accepted is generally easier than introducing something entirely unique. In the case of community conventions, you can refer someone to an internet article, while for team-specific conventions, you might need to write that article yourself.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Specific Rules&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this section, we will discuss specific naming conventions for data types and data structures. While JavaScript may appear limited in its built-in data types and structures, it offers extensive capabilities. These encompass a variety of methods, which in other programming languages are often segregated into distinct built-in types or data structures.&lt;/p&gt;

&lt;p&gt;For instance, in JavaScript, an object can serve as an &lt;code&gt;enum&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt; (&lt;code&gt;dictionary&lt;/code&gt;), &lt;code&gt;graph&lt;/code&gt;, and more. The &lt;code&gt;number&lt;/code&gt; data type in JavaScript includes handling both integers and floating-point numbers. Depending on specific requirements, JavaScript data types and structures can be flexibly adapted for use, providing JavaScript with versatility and power.&lt;/p&gt;

&lt;p&gt;It is in this context that the importance of naming conventions becomes clear. They not only enhance code readability but also prevent confusion and errors when interacting with other parts of the codebase. Good naming conventions ensure clarity within the code and facilitate understanding of data structures and their purposes for other developers, contributing to more effective collaboration within a team.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Booleans&lt;/strong&gt;. Names of boolean values should start with an affirmative prefix, meaning the prefix should answer the question "yes." Although there are several affirmative words (should, can, will, etc.) that answer "yes," it is advisable to prefer the two most common ones – &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;has&lt;/code&gt;. While using other affirmative words will not be considered an error, their use should be treated as an exception, and if possible, it is better to avoid using them.&lt;/p&gt;

&lt;p&gt;An important addition to this convention, often overlooked, is that the affirmative prefix should not include a negation. The reason behind this is that the negation operator (&lt;code&gt;!&lt;/code&gt;) is most commonly used with boolean values. Therefore, a value named something like &lt;code&gt;isNotAllowed&lt;/code&gt; with the negation applied to it &lt;code&gt;!isNotAllowed&lt;/code&gt; can be quite misleading. Do not believe so? Then try quickly figuring out what &lt;code&gt;!!isNotAllowed&lt;/code&gt; (double negation) equals. Even if you manage to do it quickly, imagine working with real code where all these negation inversions are scattered throughout the file. Keeping track of such logic, especially when there is a lot of it, can be quite challenging. In such cases, it is better to alter the logic of evaluating the boolean variable using a positive affirmative in its name.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userLogin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;friend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isNotUserRemoved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userActionState&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;ActionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REMOVED&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;isNotUserRemoved&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* some logic */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isUserAuthorized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;hasFriend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isUserRemoved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userActionState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;ActionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REMOVED&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;isUserRemoved&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* some logic */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Along with the convention to use affirmative prefixes for boolean names, we diverge from the &lt;a href="https://w3ctag.github.io/design-principles/#naming-booleans"&gt;W3C specification recommendations&lt;/a&gt;, as it advises against using these prefixes for boolean names. This contradicts the idea mentioned earlier to prefer conventions used by the language itself. However, there are always exceptions, and this is one of them. It is normal since the way specification authors think may differ from the community's perspective.&lt;/p&gt;

&lt;p&gt;JavaScript was created a long time ago, and at the time of its inception, the authors decided not to use affirmative prefixes for boolean names. Now, they do their best by &lt;a href="https://github.com/tc39/proposal-decorators/issues/417"&gt;continuing to follow&lt;/a&gt; their convention, even if it goes against the community's opinion. Even if the authors wanted to introduce new naming conventions in the specification, they could not do it, at least not coherently. Old code cannot be renamed because JavaScript must remain backward-compatible. And starting to write new code using new approaches is not a great idea either, as there would be two ways to do the same thing, which is also undesirable.&lt;/p&gt;

&lt;p&gt;Exceptions are normal. Nothing in this world is perfect. Even the specification itself has exceptions – &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/isContentEditable"&gt;&lt;code&gt;node.isContentEditable&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted"&gt;&lt;code&gt;evt.isTrusted&lt;/code&gt;&lt;/a&gt;. The key is to try to minimize them while adhering to previously established conventions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Functions &amp;amp; Methods&lt;/strong&gt;. The name of a function/method should be a verb and correspond to the action it performs.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userNaming&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charAt&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="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hey&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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;permissionRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getCapitalizedUserName&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charAt&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="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hey&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUserPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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;permissionRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Although the naming convention for functions/methods may seem simple at first glance, their naming is the one that has the most exceptions and other conventions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Following the JavaScript writing style (&lt;code&gt;Number.isNaN()&lt;/code&gt;, &lt;code&gt;Array.isArray()&lt;/code&gt;, &lt;code&gt;salary.toFixed()&lt;/code&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new"&gt;constructor functions&lt;/a&gt;, etc.).&lt;/li&gt;
&lt;li&gt;Naming conventions for event handler functions (&lt;code&gt;onBtnClick&lt;/code&gt;, &lt;code&gt;onImgMouseOver&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;Library functions, for example, a reducer function in the &lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; library (&lt;code&gt;const users = (state, action) =&amp;gt; { /* some logic */ }&lt;/code&gt;), functional components in &lt;a href="https://react.dev/"&gt;React&lt;/a&gt; (&lt;code&gt;const UserDashboard = () =&amp;gt; { /* component */ }&lt;/code&gt;), and many other exceptions and conventions proposed by libraries and frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can learn about all of them by working directly with them. However, for most functions and methods, the main convention that the name should be a verb and correspond to the action they perform remains unchanged.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Collections &amp;amp; Iterators&lt;/strong&gt;. The naming convention is as follows – if &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator"&gt;Iterator&lt;/a&gt; or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections"&gt;indexed collections&lt;/a&gt; (e.g., &lt;code&gt;Array&lt;/code&gt;, &lt;code&gt;NodeList&lt;/code&gt;, &lt;code&gt;FileList&lt;/code&gt;, etc.) are used, the name should be a plural noun. Otherwise, if &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections"&gt;keyed collections&lt;/a&gt; (&lt;code&gt;Set&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;) are used, and we are only interested in &lt;em&gt;values&lt;/em&gt; that we can obtain by keys (usually using &lt;code&gt;Array.from()&lt;/code&gt; or &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"&gt;spread syntax&lt;/a&gt;), the naming convention remains the same – the name should be a plural noun. However, if the keys are also important to us in keyed collections, then such collections should be named using a singular noun, and at the end of the name, add one of the prefixes that signifies a set of something. For example, &lt;code&gt;Collection&lt;/code&gt;, &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Group&lt;/code&gt;, and others.&lt;/p&gt;

&lt;p&gt;An important addition is that this convention should also be applied to user-created indexed or keyed collections using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols"&gt;Iteration protocols&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRoleArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserRole&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;usersAccordionList&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;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.users-accordion__list-item&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;groupPermissions&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;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permission&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;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRoles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserRole&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;usersAccordionItemNodes&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;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.users-accordion__list-item&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;permissionsByGroupList&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;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permission&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;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




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

&lt;p&gt;&lt;strong&gt;Classes&lt;/strong&gt;. When working with classes, it is important to follow several conventions. Here is the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;PascalCase&lt;/code&gt; for the class name, following the same case style that JavaScript uses for classes and constructor functions.&lt;/li&gt;
&lt;li&gt;The class name should be a singular noun.&lt;/li&gt;
&lt;li&gt;Names of all class members should not include the class name.
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;userService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* class members */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Permissions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* class members */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserAuthPopup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;isPopupOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="nf"&gt;openPopup&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;isPopupOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* class members */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PermissionService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* class mmebers */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserAuthPopup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;isOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="nf"&gt;open&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;isOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;If there is a temptation to use the class name in the names of its members, it is likely that the class is overloaded with logic or is responsible for more things than it should be. In such cases, a violation of the &lt;a href="https://en.wikipedia.org/wiki/Single-responsibility_principle"&gt;Single Responsibility Principle&lt;/a&gt; can often be observed. To avoid such situations, it is recommended to create additional classes and use inheritance or dependency injection to limit the responsibility of each class.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Constants&lt;/strong&gt;. Used to describe values which are known &lt;em&gt;before the program's execution&lt;/em&gt; and that &lt;em&gt;should not change&lt;/em&gt; during its execution.&lt;/p&gt;

&lt;p&gt;Constants are a crucial and widely adopted approach to organizing a program's code. Regarding naming conventions, there is an important agreement among developers: the name of a constant should be written using the &lt;code&gt;UPPER_SNAKE_CASE&lt;/code&gt; notation.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userFailingLoginAttempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; 

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USER_ROLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateUserRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userDefaultAuthMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;USER_FAILING_LOGIN_ATTEMPTS_COUNT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateUserRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;USER_DEFAULT_AUTH_METHOD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mfa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Although there are several ways to declare a variable in JavaScript, and for constants, it might seem logical to use &lt;em&gt;only&lt;/em&gt; the &lt;code&gt;const&lt;/code&gt; keyword, which &lt;em&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const#description"&gt;prevents it from being changed&lt;/a&gt;&lt;/em&gt; during program execution, as some teams prefer not to worry about choosing the keyword for variable declarations. They may use automation tools like &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; to enforce the use of only the &lt;code&gt;let&lt;/code&gt; keyword for variable declarations in the program code.&lt;/p&gt;

&lt;p&gt;Again, every team is different, and each may have its own conventions. However, even the prohibition of using seemingly more appropriate constructs and keywords is not an indicator of how something should be done or named. Naming always carries more meaning than the use of any keywords. This is why naming is such a crucial aspect of code writing.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Enums&lt;/strong&gt;. Also known as enumerations. In JavaScript, this &lt;em&gt;data structure&lt;/em&gt; is used to enumerate a set of fixed values.&lt;/p&gt;

&lt;p&gt;Unlike many other programming languages that have a separate data type for enumerations, JavaScript does not have such a data type (at least, as of now). Instead, to simulate an enumeration in JavaScript, a plain object can be used, but with specific naming conventions. Here is a list of these naming conventions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The name of the enumeration should start with a capital letter.&lt;/li&gt;
&lt;li&gt;The name of the enumeration should be in the singular noun.&lt;/li&gt;
&lt;li&gt;The keys of the enumeration should be in uppercase.
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;guest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest&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;const&lt;/span&gt; &lt;span class="nx"&gt;USER_API_PATHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;root&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="nx"&gt;users&lt;/span&gt;&lt;span class="na"&gt;$Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/:id&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;const&lt;/span&gt; &lt;span class="nx"&gt;userValidationRules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;MIN_PASSWORD_LENGTH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;MAX_NAME_LENGTH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;VALID_REFERRER_DOMAINS&lt;/span&gt;&lt;span class="p"&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;google.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;GUEST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest&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;const&lt;/span&gt; &lt;span class="nx"&gt;UserApiPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ROOT&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="nx"&gt;USERS_&lt;/span&gt;&lt;span class="na"&gt;$ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/:id&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;const&lt;/span&gt; &lt;span class="nx"&gt;UserValidationRule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;MIN_PASSWORD_LENGTH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;MAX_NAME_LENGTH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;VALID_REFERRER_DOMAINS&lt;/span&gt;&lt;span class="p"&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;google.com&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;p&gt;Since TypeScript is now a significant part of JavaScript development, it is worth mentioning that TypeScript has the &lt;code&gt;enum&lt;/code&gt; keyword for enumerations. If you decide to use TypeScript's enumerations with your team, it is customary to follow the same naming conventions.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Maps&lt;/strong&gt;. Also known as a &lt;code&gt;dictionary&lt;/code&gt; data structure. This data structure is used for &lt;em&gt;mapping&lt;/em&gt; one value to another.&lt;/p&gt;

&lt;p&gt;A map is a very useful and frequently used data structure in any programming language. For maps in the JavaScript world, there is a specific naming convention. The name should follow the pattern &lt;code&gt;aToB&lt;/code&gt;, where &lt;code&gt;a&lt;/code&gt; serves as the key for retrieving values from the map, followed by the preposition &lt;code&gt;To&lt;/code&gt;, implying the mapping of two things, and then &lt;code&gt;B&lt;/code&gt;, which is the mapped value for &lt;code&gt;a&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRolesReadable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Administrator&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;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GUEST&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Guest&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;const&lt;/span&gt; &lt;span class="nx"&gt;REDIRECTING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/groups&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;/admin-login&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;/profile&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;/login&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;const&lt;/span&gt; &lt;span class="nx"&gt;UserPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MANAGE_USERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MANAGE_GROUPS&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GUEST&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EDIT_PROFILE&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRoleToReadable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Administrator&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;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GUEST&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Guest&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;const&lt;/span&gt; &lt;span class="nx"&gt;pagePathToRedirectPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/groups&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;/admin-login&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;/profile&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;/login&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;const&lt;/span&gt; &lt;span class="nx"&gt;userRoleToPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MANAGE_USERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MANAGE_GROUPS&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GUEST&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EDIT_PROFILE&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;p&gt;There is a built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/a&gt; class in JavaScript. The main difference from a regular object is the ability to use any data type (even an object) as a key. Usually, using the native &lt;code&gt;Map&lt;/code&gt; class is redundant for creating a map as a data structure. However, if you need the functionality provided by the native &lt;code&gt;Map&lt;/code&gt;, you can use it to create a map data structure. In most cases, a regular object will suffice.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Types &amp;amp; Interfaces&lt;/strong&gt;. As mentioned earlier, TypeScript has become an integral part of JavaScript development today. In general, &lt;em&gt;in most cases&lt;/em&gt;, types and interfaces are interchangeable. However, since there are already enough discussions about which one to choose, in this article, we will focus specifically on naming. For types and interfaces, the following naming conventions exist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Names of types and interfaces should be written in &lt;code&gt;PascalCase&lt;/code&gt; notation.&lt;/li&gt;
&lt;li&gt;The name should describe what the type or interface will be used for, often as straightforwardly as possible: &lt;code&gt;const user: User = getUserById(id)&lt;/code&gt; / &lt;code&gt;const users: User[] = getUsers()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If a development team has decided to &lt;em&gt;actively&lt;/em&gt; use both types and interfaces in one codebase, it is recommended to add a prefix to interfaces to distinguish them. The most popular prefixes are &lt;code&gt;I&lt;/code&gt; and &lt;code&gt;Contract&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;userServiceInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserServiceContract&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IUserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important to realize that despite the extensive overview of JavaScript naming conventions in this article, it cannot cover all possible scenarios. Even within the presented points, numerous exceptions should be considered. The naming process, although fundamental, implies flexibility in application, taking into account the unique features and requirements of each project.&lt;/p&gt;

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

&lt;p&gt;During development, we often delve into complex technical details, forgetting that the power often lies in the details. Years of development experience only affirm the truth that attention to details, such as naming, plays a crucial role in creating efficient and readable code. Simplicity and the absence of the need to ponder over how to name a value and how quickly to understand what it contains bring incredible relief in the daily work of a developer.&lt;/p&gt;

&lt;p&gt;Can a developer consider themselves strong if their variables are not clearly named? Clear naming not only makes the code more understandable for other developers but also for the programmer themselves, making the development process more efficient and less error-prone.&lt;/p&gt;

&lt;p&gt;It often happens that searching for poor naming leads to the discovery of bad code. This only underscores how naming conventions serve as an indicator of code quality. Proper naming reflects care for details, which, in turn, speaks to an attentive approach to development.&lt;/p&gt;

&lt;p&gt;Here is how the import of values from the introductory part looks when applying the conventions discussed in this article. Now it looks much clearer, doesn't it? I am sure it will take you much less effort now to understand the meaning of each import.&lt;/p&gt;

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

&lt;p&gt;In conclusion, it is essential to remember that while naming standards are important, they are not absolute. Every project has its peculiarities, and it is crucial to define your conventions. The main thing is that they should exist, and you adhere to them to ensure consistency in the code and improve collective productivity. Also, if possible, try to delegate code style issues to tools like &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; to simplify and enhance the development process.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>ECMAScript Decorators. The Ones That are Real</title>
      <dc:creator>Vladyslav Zubko</dc:creator>
      <pubDate>Tue, 24 Oct 2023 10:31:26 +0000</pubDate>
      <link>https://forem.com/what1s1ove/ecmascript-decorators-the-ones-that-are-real-g96</link>
      <guid>https://forem.com/what1s1ove/ecmascript-decorators-the-ones-that-are-real-g96</guid>
      <description>&lt;p&gt;&lt;strong&gt;IMPORTANT NOTE: The latest updates to the article and changelog can be found by following the link to the &lt;a href="https://whatislove.dev/articles/ecmascript-decorators-the-ones-that-are-real/"&gt;original article publication&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In 2015, ECMAScript 6 was introduced – a significant release of the JavaScript language. This release introduced many new features, such as &lt;code&gt;const&lt;/code&gt;/&lt;code&gt;let&lt;/code&gt;, arrow functions, classes, etc. Most of these features were aimed at eliminating JavaScript's quirks. For this reason, all these features were labeled as "Harmony." Some sources say that the entire ECMAScript 6 is called "ECMAScript Harmony." In addition to these features, the "Harmony" label highlights other features expected to become part of the specification soon. Decorators are one of such anticipated features.&lt;/p&gt;

&lt;p&gt;Nearly 10 years have passed since the first mentions of decorators. The decorators’ specification has been rewritten several times almost from scratch but they have not become part of the specification yet. As JavaScript has long extended beyond just browser-based applications, authors of specifications must consider a wide range of platforms where JavaScript can be executed. This is precisely why progressing to &lt;a href="https://exploringjs.com/impatient-js/ch_history.html#tc39-process"&gt;stage 3&lt;/a&gt; for this proposal has taken so much time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Something Completely New?
&lt;/h2&gt;

&lt;p&gt;First of all, let's clarify what decorators are in the programming world.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“&lt;em&gt;Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.&lt;/em&gt;”&lt;br&gt;
© &lt;a href="https://refactoring.guru/design-patterns/decorator"&gt;https://refactoring.guru/design-patterns/decorator&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The key point here is that a decorator is a design pattern. This means that &lt;em&gt;typically&lt;/em&gt; it can be implemented in any programming language. If you have even a basic familiarity with JavaScript, chances are you have already used this pattern without even realizing it.&lt;/p&gt;

&lt;p&gt;Sound interesting? Then try to guess what the most popular decorator in the world is... Meet the most famous decorator in the world, the higher-order function – &lt;code&gt;debounce&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debounce
&lt;/h3&gt;

&lt;p&gt;Before we delve into the details of the &lt;code&gt;debounce&lt;/code&gt; function, let's remind ourselves what higher-order functions are. Higher-order functions are functions that take one or more functions as arguments or return a function as their result. The &lt;code&gt;debounce&lt;/code&gt; function is a prominent example of a higher-order function and at the same time the most popular decorator for JS developers.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;higher-order function&lt;/em&gt; &lt;code&gt;debounce&lt;/code&gt; delays the invocation of another function until a certain amount of time has passed since the last invocation, without changing its behavior. The most common use case is to prevent sending multiple requests to the server when a user is inputting values into a search bar, such as loading autocomplete suggestions. Instead, it waits until the user has finished or paused input and only then sends the request to the server.&lt;/p&gt;

&lt;p&gt;On most resources for learning JavaScript language in the section about timeouts, you will find exercises that involve writing this function. The simplest implementation looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;debounce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;args&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;lastTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;lastTimeout&lt;/span&gt; &lt;span class="o"&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="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&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="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this function may look like the following:&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;class&lt;/span&gt; &lt;span class="nc"&gt;SearchForm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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;handleUserInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&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;handleUserInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;handleUserInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&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;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using a special syntax for decorators which we will discuss in the next section, the implementation of the same behavior will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SearchForm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;handleUserInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&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;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the boilerplate code is gone, leaving only the essentials. Looks nice and clean, doesn't it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Higher-Order Component (HOC)
&lt;/h3&gt;

&lt;p&gt;The next example will come from the &lt;a href="https://react.dev/"&gt;React&lt;/a&gt;-world. Although the use of Higher-Order Components (HOC) is becoming less common in applications built with this library, HOCs still serve as a good and well-known example of decorator usage.&lt;/p&gt;

&lt;p&gt;Let's take a look at an example of the &lt;code&gt;withModal&lt;/code&gt; HOC:&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;withModal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsOpen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleModalVisibilityToggle&lt;/span&gt; &lt;span class="o"&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;setIsOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isOpen&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;
        &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onModalVisibilityToggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleModalVisibilityToggle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, let's see how it can be used:&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;AuthPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onModalVisibilityToggle&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;// Component&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;WrappedAuthPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;withModal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthPopup&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;WrappedAuthPopup&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AuthPopup&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is what using the HOC with the special decorator syntax would look like:&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;withModal&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;AuthPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onModalVisibilityToggle&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;// Component&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;AuthPopup&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important Note:&lt;/strong&gt; &lt;em&gt;Function decorators are not a part of the current proposal. However, they are on the list of things that could be considered for the future development of the decorators specification.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once again, all the boilerplate code is gone, leaving only what truly matters. &lt;/p&gt;

&lt;p&gt;Perhaps some of the readers did not see anything special in this. In the example above, only one decorator was used. Let's take a look at such 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AuthPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onFocusTrapInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onModalVisibilityToggle&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="c1"&gt;// Component&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;WrappedAuthPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;withForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;withFocusTrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;withModal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthPopup&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;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WrappedAuthPopup&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AuthPopup&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See that hard-to-read nesting? How much time did it take you to understand what is happening in the code? Now, let's take a look at the same example but with the use of decorator syntax:&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;withForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&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="nd"&gt;withFocusTrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;withModal&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;AuthPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onFocusTrapInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onModalVisibilityToggle&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="c1"&gt;// Component&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;AuthPopup&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Would you not agree that the code that goes from top to bottom is much more readable than the previous example with nested function calls?&lt;/p&gt;

&lt;p&gt;The higher-order function &lt;code&gt;debounce&lt;/code&gt; and the higher-order component &lt;code&gt;withModal&lt;/code&gt; are just a few examples of how the decorator pattern is applied in everyday life. This pattern can be found in many frameworks and libraries that we use regularly, although many of us may often not pay attention to it. Try analyzing the project you are working on and look for places where the decorator pattern is applied. You will likely discover more than one such example.  &lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Implementations
&lt;/h2&gt;

&lt;p&gt;Before we delve into the decorators proposal itself and its implementation, I would like us to take a look at this image:&lt;/p&gt;

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

&lt;p&gt;With this image, I would like to remind you of the primary purpose for which JavaScript language was originally created. I am not one of those people who like to complain, saying, "Oh, JavaScript is only good for highlighting form fields." Typically, I refer to such individuals as “dinosaurs”.&lt;/p&gt;

&lt;p&gt;JavaScript primarily focuses on the end user for whom we write code. This is a crucial point to understand because every time new things are introduced in JavaScript language such as classes with implementations differing from what is found in other programming languages, the same complainers come and start lamenting that things are not done in a user-friendly manner. Quite the opposite, in JavaScript everything is designed with end users in mind, which is something that no other programming language can boast about.&lt;/p&gt;

&lt;p&gt;Today, JavaScript is not just a browser language. It can be run in various environments, including on the server. The &lt;a href="https://exploringjs.com/impatient-js/ch_history.html#tc39-process"&gt;TC39&lt;/a&gt; committee responsible for introducing new features to the language, faces the challenging task of meeting the needs of all platforms, frameworks, and libraries. However, the primary focus remains on end users in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  History of Decorators
&lt;/h3&gt;

&lt;p&gt;To delve deeper into the history of this proposal, let's review a list of key events.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/tc39/notes/blob/main/meetings/2014-04/apr-10.md#decorators-for-es7"&gt;2014-04 – Stage 0&lt;/a&gt;&lt;/strong&gt;. Decorators were proposed by Yehuda Katz and they were initially intended to become a part of the ECMAScript 7.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Decorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DecoratedClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;propertyKey&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;descriptor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropertyDescriptor&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;PropertyDescriptor&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delay&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;PropertyDescriptor&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;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;propertyKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;descriptor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;lastTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;descriptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;

    &lt;span class="nx"&gt;descriptor&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="p"&gt;(...&lt;/span&gt;&lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="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;lastTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="nx"&gt;lastTimeout&lt;/span&gt; &lt;span class="o"&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="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&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="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;delay&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;descriptor&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;p&gt;Already at this stage, you can see one of the reasons why the decorators API underwent such significant changes later on. The first argument of the decorator was an entire class, even if you were decorating only one of its members. Moreover, it was assumed that developers could mutate this class. JavaScript engines always strive to optimize as much as possible, and in this case, the developer's call to mutate the entire class undermined a significant number of optimizations provided by the engine. Later, we will see that this was indeed a major reason why the decorators API was rewritten multiple times, almost from scratch.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/tc39/notes/blob/main/meetings/2015-03/mar-24.md#62-decorators"&gt;&lt;strong&gt;2015-03 – Stage 1&lt;/strong&gt;&lt;/a&gt;. Without significant changes, the proposal advanced to stage 2. However, an event occurred that significantly influenced the further development of this proposal: &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-1-5/"&gt;TypeScript 1.5 was released&lt;/a&gt;, which supported decorators. Despite decorators being marked as experimental (&lt;code&gt;--experimentalDecorators&lt;/code&gt;), projects like Angular and MobX actively started using them. Furthermore, the overall workflow for these projects assumed the use of decorators exclusively. Due to the popularity of these projects, many developers mistakenly believed that decorators were already a part of the official JS standard.&lt;/p&gt;

&lt;p&gt;This created additional challenges for the TC39 committee because they had to consider the expectations and requirements of the developer community as well as optimization issues in language engines.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/tc39/notes/blob/main/meetings/2016-07/jul-28.md#9iiic-decorators"&gt;2016-07 – Stage 2&lt;/a&gt;&lt;/strong&gt;. After the decorators proposal reached stage 2, its API began to undergo significant changes. Furthermore, at one point the proposal was referred to as "ESnext class features for JavaScript." During its development, there were numerous ideas about how decorators could be structured. To get a comprehensive view of the entire history of changes, I recommend &lt;a href="https://github.com/tc39/proposal-decorators"&gt;reviewing the commits&lt;/a&gt; in the proposal's repository. Here is an example of what the decorators API used to look like:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Decorator&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;property&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&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="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isStatic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;descriptor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropertyDescriptor&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="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;property&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;key&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="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isStatic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;descriptor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropertyDescriptor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;extras&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;By the end of stage 2, the decorator API looked as follows:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Decorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DecoratedValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;method&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accessor&lt;/span&gt;&lt;span class="dl"&gt;'&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="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;access&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;get&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="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;addInitializer&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initializer&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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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="nx"&gt;UpdatedDecoratedValue&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delay&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;UpdatedDecoratedValue&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;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;args&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;lastTimeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="nx"&gt;lastTimeout&lt;/span&gt; &lt;span class="o"&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&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="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The entire stage 2 took 6 years, during which the decorator API underwent significant changes. However, as we can see from the code above, mutations were excluded. This made the proposal more acceptable for JS engines as well as for various platforms, frameworks, and libraries. But the development history of decorators is not over yet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://michel.codes/blogs/mobx6"&gt;2020-09 – Announcing MobX 6. Bye-bye Decorators&lt;/a&gt;&lt;/strong&gt;. Some libraries that relied exclusively on decorators started to move away from their old implementation because they understood that the way they were working with decorators would no longer be standardized.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;”&lt;em&gt;Using decorators is no longer the norm in MobX. This is good news to some of you, but others will hate it. Rightfully so, because I concur that the declarative syntax of decorators is still the best that can be offered. When MobX started, it was a TypeScript only project, so decorators were available. Still experimental, but obviously they were going to be standardized soon. That was my expectation at least (I did mostly Java and C# before). However, that moment still hasn't come yet, and two decorators proposals have been cancelled in the mean time. Although they still can be transpiled.&lt;/em&gt;”&lt;br&gt;
© Michel Weststrate, author of MobX&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/tc39/notes/blob/main/meetings/2022-03/mar-28.md#decorators-for-stage-3"&gt;&lt;strong&gt;2022-03 – Stage 3&lt;/strong&gt;&lt;/a&gt;. After years of changes and refinements, decorators finally reached stage 3. Thanks to the extensive adjustments and refinements during the second stage, the third stage began without significant changes. A particular highlight is the creation of a new proposal called &lt;strong&gt;&lt;a href="https://github.com/tc39/proposal-decorator-metadata"&gt;Decorator Metadata&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://spidermonkey.dev/blog/2022/08/29/newsletter-firefox-104-105.html"&gt;&lt;strong&gt;2022-08 – SpiderMonkey Newsletter&lt;/strong&gt;&lt;/a&gt;. SpiderMonkey, the browser engine used by Firefox, became the first engine to begin working on the implementation of decorators. Implementations like this indicate that the proposal is generally ready to become a full-fledged part of the specification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://babeljs.io/blog/2022/09/05/7.19.0"&gt;2022-09 – Babel 7.19.0. Stage 3 decorators&lt;/a&gt;&lt;/strong&gt;. Adding support in a compiler is a very significant update for any proposal. Most proposals have a similar item in their standardization plan and the decorators proposal &lt;a href="https://github.com/tc39/proposal-decorators#standardization-plan"&gt;was no exception&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-9/"&gt;2022-11 – Announcing TypeScript 4.9&lt;/a&gt;&lt;/strong&gt;. ECMAScript decorators were listed in &lt;a href="https://github.com/microsoft/TypeScript/issues/50457"&gt;TS 4.9 Iteration Plan&lt;/a&gt;. However, after some time, the TS team decided to move decorators to the 5.0 release. Here is the &lt;a href="https://github.com/microsoft/TypeScript/issues/50457#issuecomment-1253100246"&gt;authors' comment&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“&lt;em&gt;While decorators have reached stage 3, we saw some behavior in the spec that needed to be discussed with the champions. Between addressing that and reviewing the changes, we expect decorators will be implemented in the next version.&lt;/em&gt;”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In general, this decision makes sense, as they did not want to risk incorporating a feature into TS prematurely, especially if it did not become part of the standard. There is always a chance of such situations happening. Although in this case, it might not be as significant as the first implementation.&lt;/p&gt;

&lt;p&gt;In TS 4.9, only a small part of decorators specification was included – &lt;a href="https://github.com/tc39/proposal-decorators#class-auto-accessors"&gt;Class Auto-Accessors&lt;/a&gt;. This addition to the decorators specification served as a correction for the mutations that were prevalent in the first stages of implementation. The reason behind this is that often there is a desire to make properties reactive, meaning that some effects should occur when the property changes, such as UI re-rendering, for example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dashboard&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;reactive&lt;/span&gt;
  &lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DashboardTab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USERS&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In the old implementation, with the &lt;code&gt;reactive&lt;/code&gt; decorator, you had to mutate the &lt;code&gt;target&lt;/code&gt; class by adding additional &lt;code&gt;set&lt;/code&gt; and &lt;code&gt;get&lt;/code&gt; accessors to achieve the desired behavior. With the use of auto-accessors, this behavior now occurs more explicitly, which in turn allows engines to optimize it better.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dashboard&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;reactive&lt;/span&gt;
  &lt;span class="nx"&gt;accessor&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DashboardTab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USERS&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Another interesting thing is how decorators were supposed to work. Since the TS team could not remove the old implementation that worked under the &lt;code&gt;--experimentalDecorators&lt;/code&gt; flag, they decided on the following approach: if the &lt;code&gt;--experimentalDecorators&lt;/code&gt; flag is present in the configuration, the old implementation will be used. If this flag is not present, then the new implementation will be used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/"&gt;2023-03 – Announcing TypeScript 5.0&lt;/a&gt;&lt;/strong&gt;. As promised, the TS team released the full version of decorators specification in TS 5.0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://deno.com/blog/v1.32"&gt;2023-03 – Deno 1.32&lt;/a&gt;.&lt;/strong&gt; Although in version 1.32 Deno supported TS 5.0, they decided to postpone the functionality related to decorators.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“&lt;em&gt;Take note that ES decorators are not yet supported, but we will be working towards enabling them by default in a future version.&lt;/em&gt;”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://blog.angular.io/angular-v16-is-here-4d7a28ec680d"&gt;2023-05 – Angular v16 is here.&lt;/a&gt;&lt;/strong&gt; Angular 16 also added support for ECMAScript decorators. However, some other frameworks built around decorators (and which were inspired by Angular?) have stated that they will not make changes toward ECMAScript decorators for now. For many of them, &lt;a href="https://github.com/nestjs/nest/issues/11414"&gt;two important aspects&lt;/a&gt; are Metadata and Parameter decorators.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;”&lt;em&gt;I don't think we'll support JS decorators till the metadata support &amp;amp; parameter decorators are implemented.&lt;/em&gt;”&lt;br&gt;
© Kamil Mysliwiec, creator of NextJS&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-2/"&gt;2023-08 – Announcing TypeScript 5.2&lt;/a&gt;.&lt;/strong&gt; In TS 5.2, another standard was added that complements the decorators specification – &lt;a href="https://github.com/tc39/proposal-decorator-metadata"&gt;Decorator Metadata&lt;/a&gt;. The primary idea behind this proposal is to simplify decorators' access to class metadata in which they are used. Another reason there were so many debates regarding syntax and usage was that the authors had to create a whole separate proposal for this purpose.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Just Syntactic Sugar or Not?
&lt;/h2&gt;

&lt;p&gt;After all the explanations and examples, you might have a question: "So, are decorators in JavaScript just higher-order functions with special syntax, and that is it?”.&lt;/p&gt;

&lt;p&gt;It is not all that simple. In addition to what was mentioned earlier regarding how JavaScript primarily focuses on end-users, it is also worth adding that JS-engines always try to use the new syntax as a reference point to at least &lt;em&gt;attempt&lt;/em&gt; to make your JavaScript faster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;groupBy&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;npm:lodash@4.17.21&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getGroupedOffersByCity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;it&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;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&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="c1"&gt;// OR ?&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getGroupedOffersByCity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;it&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;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may seem like there is no difference, but there are distinctions for the engine. Only in the second case, when native functions are used,  can the engine &lt;em&gt;attempt&lt;/em&gt; optimization.&lt;/p&gt;

&lt;p&gt;Describing how optimizations work in JavaScript engines would require a separate article. Do not hesitate to explore browser source code or search for articles to gain a better understanding of this topic.&lt;/p&gt;

&lt;p&gt;It is also important to remember that there are many JavaScript engines, and they all perform optimizations differently. However, if you assist the engine by using native syntax, your &lt;em&gt;application&lt;/em&gt; code will generally run faster in most cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Possible Extensions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The new syntax in the specification also opens the door for additional features in the future. As an analogy, consider constructor functions and classes. When private fields were introduced in the specification, they were introduced as a feature for classes. For those who staunchly denied the usefulness of classes and claimed that constructor functions were equivalent, private fields became another reason to move away from constructor functions in favor of classes. Such features are likely to continue evolving.&lt;/p&gt;

&lt;p&gt;While we can currently achieve many of the same effects as decorators using higher-order functions in many cases, they still do not cover all the potential functionality that will be added to the decorators specification in the future.&lt;/p&gt;

&lt;p&gt;The "&lt;a href="https://github.com/tc39/proposal-decorators/blob/master/EXTENSIONS.md"&gt;possible extensions&lt;/a&gt;" file in the decorators specification repository provides insights into how the decorators specification may evolve in the future. Some of the points were listed in the first stages but are not present in the current standard, such as parameter decorators. However, there are also entirely new concepts mentioned, like &lt;code&gt;const&lt;/code&gt;/&lt;code&gt;let&lt;/code&gt; decorators or block decorators. These potential extensions illustrate the ongoing development and expansion of the decorator functionality in JavaScript.&lt;/p&gt;

&lt;p&gt;Indeed, numerous proposals and extensions are being considered to enhance the decorators specification further. Some of these proposals like the &lt;a href="https://github.com/tc39/proposal-decorator-metadata"&gt;Decorator Metadata&lt;/a&gt;, are already under consideration even though the core decorator specification has not yet been standardized. This underscores the idea that decorators have a promising future in the specification and we can hope to see them become a part of the standard in the near future.&lt;/p&gt;

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

&lt;p&gt;The lengthy consideration of the decorators proposal over 10 years may indeed seem like an extended period. It is true that the early adoption of decorators by leading frameworks and libraries played a role in uncovering the shortcomings of the initial implementation. However, this early adoption also served as an invaluable learning experience, highlighting the importance of harmonizing with web platforms and developing a solution that aligns with both platforms and the developer community, while preserving the essence of decorators. The time spent refining the proposal has ultimately contributed to making it a more robust and well-considered addition to the JavaScript language.&lt;/p&gt;

&lt;p&gt;Indeed, decorators will bring significant changes to how we write applications today. Perhaps not immediately, as the current specification primarily focuses on classes, but with all the &lt;a href="https://github.com/tc39/proposal-class-method-parameter-decorators"&gt;additions and ongoing work&lt;/a&gt; JavaScript code in many applications will soon look different. We are now closer than ever to the moment when we can finally see those &lt;em&gt;ones that are real&lt;/em&gt; decorators in the specification. It is an exciting development that promises to enhance the expressiveness and functionality of JavaScript applications.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tc39</category>
      <category>decorators</category>
    </item>
  </channel>
</rss>
