<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cyrille Tuzi</title>
    <description>The latest articles on DEV Community by Cyrille Tuzi (@cyrilletuzi).</description>
    <link>https://dev.to/cyrilletuzi</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%2F610306%2F6c239df3-c526-4301-b6a2-75c26c1465ac.jpeg</url>
      <title>DEV Community: Cyrille Tuzi</title>
      <link>https://dev.to/cyrilletuzi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cyrilletuzi"/>
    <language>en</language>
    <item>
      <title>TypeScript strictly typed - Part 4: full static types</title>
      <dc:creator>Cyrille Tuzi</dc:creator>
      <pubDate>Wed, 31 Jul 2024 12:36:50 +0000</pubDate>
      <link>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-4-full-static-types-8bc</link>
      <guid>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-4-full-static-types-8bc</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-3-safe-nullability-38mf"&gt;previous part&lt;/a&gt; of this &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;posts series&lt;/a&gt;, we discussed about safe nullability.&lt;/p&gt;

&lt;p&gt;Now we will explain and solve the third and last problem of TypeScript default behavior: &lt;strong&gt;remains of dynamic typing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remains of dynamic typing&lt;/li&gt;
&lt;li&gt;Actual equality checks&lt;/li&gt;
&lt;li&gt;No implicit conversions in conditions&lt;/li&gt;
&lt;li&gt;Conditions shorthand notation&lt;/li&gt;
&lt;li&gt;No strings and numbers mix&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Remains of dynamic typing
&lt;/h2&gt;

&lt;p&gt;TypeScript is supposed to be a "&lt;a href="https://www.typescriptlang.org/docs/handbook/2/basic-types.html#static-type-checking" rel="noopener noreferrer"&gt;static type checker&lt;/a&gt;", as opposed to JavaScript in which typing is deeply dynamic.&lt;/p&gt;

&lt;p&gt;But in a &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-2-full-coverage-typing-4cg1"&gt;previous part&lt;/a&gt; of this post series, we also explained that TypeScript is built as a superset of JavaScript.&lt;/p&gt;

&lt;p&gt;So the problem is: &lt;strong&gt;some parts of JavaScript dynamic typing system remain in TypeScript&lt;/strong&gt;. We are thus going to explain &lt;strong&gt;how to suppress these remaining behaviors to achieve full static typing&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Actual equality checks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://eslint.org/docs/latest/rules/eqeqeq" rel="noopener noreferrer"&gt;&lt;code&gt;eqeqeq&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/eslint/eqeqeq" rel="noopener noreferrer"&gt;&lt;code&gt;eqeqeq&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best example of the problem is equality checks. In JavaScript, &lt;strong&gt;&lt;code&gt;==&lt;/code&gt; is not exactly an equality check&lt;/strong&gt;, but an equivalence check:&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Despite the types being different, some conversion rules come into action so JavaScript is able to compare the values. It can lead to a lot of errors, because the rules details are difficult to remember, are sometimes quite weird, and are not exactly the same in all dynamic languages (like PHP for example).&lt;/p&gt;

&lt;p&gt;These equivalence checks only makes sense in a dynamically typed language like JavaScript. From the moment we decide to work in TypeScript, only actual equality checks (type and value) should be used.&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;eqeqeq&lt;/code&gt; lint rule enforces it.&lt;/p&gt;

&lt;p&gt;People coming from languages like Java, C# or Rust should be particularly careful with this problem, as &lt;code&gt;==&lt;/code&gt; in JavaScript or TypeScript does not mean the same as in these languages. In JavaScript and TypeScript, a third &lt;code&gt;=&lt;/code&gt; is required to achieve the same behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  No implicit conversions in conditions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/strict-boolean-expressions/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/strict-boolean-expressions&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/strict-boolean-expressions" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/strict-boolean-expressions&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think conditions are now safe? Unfortunately not, because conversions can be implicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Process payment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&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;The above example is equivalent to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tax&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Process payment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tax&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, there were implicit &lt;code&gt;==&lt;/code&gt;, so conversions still happen: &lt;code&gt;0&lt;/code&gt; is not equivalent to &lt;code&gt;true&lt;/code&gt;, it is equivalent to &lt;code&gt;false&lt;/code&gt;. So it will error despite &lt;code&gt;tax&lt;/code&gt; being a valid value.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;strict-boolean-expressions&lt;/code&gt; lint rule disallows such implicit conditions, and enforces actual checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tax&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Process payment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tax&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&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 be one of the most tedious rule to follow for people used to quick conditions in JavaScript, but to put it into perspective, it is just the normal way to do things in other languages like Java, C# or Rust.&lt;/p&gt;

&lt;p&gt;As shown in the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-1-configuring-a-project-9ca"&gt;configuration part&lt;/a&gt;, disabling &lt;code&gt;allowNumber&lt;/code&gt; and &lt;code&gt;allowString&lt;/code&gt; sub-options is important to avoid all errors.&lt;/p&gt;

&lt;p&gt;The only exception allowed is for objects and arrays: these cases are safe because contrary to strings and numbers, they do not have falsy values. So the following is still OK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;movie&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;Note: &lt;code&gt;switch&lt;/code&gt; statements are already safe as they use &lt;code&gt;===&lt;/code&gt; internally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conditions shorthand notation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/prefer-nullish-coalescing/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/prefer-nullish-coalescing&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;stylistic-type-checked&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-nullish-coalescing" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/prefer-nullish-coalescing&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;strict-boolean-expressions&lt;/code&gt; lint rule takes care that conditions checks are type safe, but there are other conditions syntaxes than &lt;code&gt;if&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movieRating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userRating&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Which is a shorter version of:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movieRating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userRating&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="nx"&gt;userRating&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user rated &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt; is equivalent to &lt;code&gt;false&lt;/code&gt;, so rating will be &lt;code&gt;5&lt;/code&gt; instead of &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It can be avoided with modern JavaScript:&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;movieRating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userRating&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Which is a shorter version of:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movieRating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userRating&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;userRating&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;userRating&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can be enforced by the &lt;code&gt;prefer-nullish-coalescing&lt;/code&gt; lint rule.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;??&lt;/code&gt; should not be used everywhere: &lt;code&gt;||&lt;/code&gt; is still relevant when working with booleans.&lt;/p&gt;

&lt;h2&gt;
  
  
  No strings and numbers mix
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://eslint.org/docs/latest/rules/prefer-template" rel="noopener noreferrer"&gt;&lt;code&gt;prefer-template&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://typescript-eslint.io/rules/restrict-plus-operands/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/restrict-plus-operands&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;recommended-type-checked&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://typescript-eslint.io/rules/restrict-template-expressions/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/restrict-template-expressions&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;recommended-type-checked&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Oxlint:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/eslint/prefer-template" rel="noopener noreferrer"&gt;&lt;code&gt;prefer-template&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/restrict-plus-operands" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/restrict-plus-operands&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/restrict-template-expressions" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/restrict-template-expressions&lt;/code&gt;&lt;/a&gt; (enabled by default)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In JavaScript, the &lt;code&gt;+&lt;/code&gt; operator can be used both for mathematical addition of numbers, or strings concatenation. It leads to error.&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;There is &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Matrix movies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 31&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;There is &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Matrix movies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;+&lt;/code&gt; operator should be reserved for mathematical addition. Or at least, it should be used only with data of the same type, which the &lt;code&gt;restrict-plus-operands&lt;/code&gt; lint rule enforces.&lt;/p&gt;

&lt;p&gt;Template strings from modern JavaScript should be used for string concatenation, which the &lt;code&gt;prefer-template&lt;/code&gt; lint rule enforces:&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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Everything everywhere all at once`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is the best movie!`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conversely, only strings should be used in template strings, which the &lt;code&gt;restrict-template-expressions&lt;/code&gt; lint rule enforces.&lt;/p&gt;

&lt;p&gt;If mixing types is what is actually wanted, conversions should be explicit:&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="s2"&gt;`There is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;total&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="s2"&gt; Matrix movies`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that template strings can be nested:&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="s2"&gt;`There is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;total&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="s2"&gt; Matrix movie&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&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="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This is the end of this posts series. You can follow my account (button  on top right of this page) to know when other posts about TypeScript or other topics like Angular are published.&lt;/p&gt;

&lt;p&gt;You want to &lt;strong&gt;contact me&lt;/strong&gt;? Instructions are available in the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;summary&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>TypeScript strictly typed - Part 3: safe nullability</title>
      <dc:creator>Cyrille Tuzi</dc:creator>
      <pubDate>Wed, 17 Jul 2024 12:39:35 +0000</pubDate>
      <link>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-3-safe-nullability-38mf</link>
      <guid>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-3-safe-nullability-38mf</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-2-full-coverage-typing-4cg1"&gt;previous part&lt;/a&gt; of this &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;posts series&lt;/a&gt;, we discussed about full coverage typing.&lt;/p&gt;

&lt;p&gt;Now we will explain and solve the second problem of TypeScript default behavior: unsafe nullability.&lt;/p&gt;

&lt;p&gt;We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Required nullability checks&lt;/li&gt;
&lt;li&gt;Required properties initialization&lt;/li&gt;
&lt;li&gt;Objects vs records&lt;/li&gt;
&lt;li&gt;Required indexes checks&lt;/li&gt;
&lt;li&gt;Exact properties types&lt;/li&gt;
&lt;li&gt;Handling inexact libraries&lt;/li&gt;
&lt;li&gt;Evil !&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Required nullability checks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#strictNullChecks" rel="noopener noreferrer"&gt;&lt;code&gt;strictNullChecks&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;strict&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/prefer-optional-chain/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/prefer-optional-chain&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;stylistic-type-checked&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-optional-chain" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/prefer-optional-chain&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In JavaScript, no matter what is the type of a variable, it can always contain &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. It leads to errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Without strict mode */&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Matrix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="nx"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Runtime error&lt;/span&gt;
&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Runtime error if the id does not exist&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#wrong-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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;strictNullChecks&lt;/code&gt;, the second most important TypeScript compiler option, a type cannot be &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; unless it is explicitly authorized, and TypeScript will enforce checks for values which can be nullish.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* With strict mode */&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Matrix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Compilation error&lt;/span&gt;
&lt;span class="nx"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nullableMovie&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="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Matrix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="nx"&gt;nullableMovie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Compilation error&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#wrong-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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="c1"&gt;// OK&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#wrong-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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As in the above example, modern JavaScript, with the optional chaining operator, will help a lot to handle nullability without introducing more conditions and complexity. It can be enforced by the &lt;code&gt;prefer-optional-chain&lt;/code&gt; lint rule.&lt;/p&gt;

&lt;p&gt;It also happens a lot with objects, for which some properties can be optional and/or &lt;code&gt;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="cm"&gt;/* With strict mode */&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Required property&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Optional property&lt;/span&gt;
  &lt;span class="nl"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Required property which can be undefined&lt;/span&gt;
  &lt;span class="nl"&gt;summary&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Optional property which can be undefined&lt;/span&gt;
  &lt;span class="nl"&gt;summary&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="kc"&gt;undefined&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;We will discuss the difference between the last 3 forms below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Required properties initialization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#strictPropertyInitialization" rel="noopener noreferrer"&gt;&lt;code&gt;strictPropertyInitialization&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;strict&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;strictPropertyInitialization&lt;/code&gt; is just a variant of &lt;code&gt;strictNullChecks&lt;/code&gt; for class properties. Let us look at this 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="cm"&gt;/* Without strict mode */&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&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="nf"&gt;getUpperCasedTitle&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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;movie&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;Movie&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Runtime error because `title` is undefined&lt;/span&gt;
&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUpperCasedTitle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a class property is not initialized (either in its declaration or in the constructor), then it can be &lt;code&gt;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="cm"&gt;/* With strict mode */&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Compilation error&lt;/span&gt;
  &lt;span class="nl"&gt;titleNotInitialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// OK&lt;/span&gt;
  &lt;span class="nx"&gt;titleInitializedDirectly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Matrix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;titleInitializedInConstructor&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;titleOptional&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;titleInitializedInConstructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;title&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;It can get complicated if initialization involves some asynchronous actions, as a class constructor cannot be asynchronous. This pattern 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;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Do not allow direct instantiation&lt;/span&gt;
  &lt;span class="c1"&gt;// to enforce the use of `getInstance()`&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Movie&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchTitle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Objects vs records
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#noPropertyAccessFromIndexSignature" rel="noopener noreferrer"&gt;&lt;code&gt;noPropertyAccessFromIndexSignature&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically &lt;code&gt;noPropertyAccessFromIndexSignature&lt;/code&gt; does not impact type correctness, but it is closely related to the next option, &lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt;, so we will explain it first.&lt;/p&gt;

&lt;p&gt;Most objects have a defined interface with known properties. But sometimes an object with dynamic properties is needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// It means the object can have any property&lt;/span&gt;
  &lt;span class="c1"&gt;// with a string index and a string value&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="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;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1px solid red&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;Note that the code above is a legacy syntax. TypeScript introduced a proper concept for this case called &lt;code&gt;Record&lt;/code&gt;, with a simpler and recommended 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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1px solid red&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;As it is indeed a different concept, &lt;code&gt;noPropertyAccessFromIndexSignature&lt;/code&gt; enforces a special syntax to access such dynamic properties:&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;// Compilation error with `noPropertyAccessFromIndexSignature`&lt;/span&gt;
&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why a specific syntax? To be sure to take into account that &lt;code&gt;color&lt;/code&gt; may not exist, as dynamic properties allow any property.&lt;/p&gt;

&lt;p&gt;Note that in most cases, records would be better expressed as maps, which is a real proper concept in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Map&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CssValue&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="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border&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;1px solid red&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;css&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// string | undefined!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Required indexes checks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess" rel="noopener noreferrer"&gt;&lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/prefer-for-of/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/prefer-for-of&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;stylistic&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/prefer-for-of" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/prefer-for-of&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let us continue to talk about records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* In default mode */&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spotted the issue? The last line is obviously erroneous.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt; will do the job correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* With `noUncheckedIndexedAccess` */&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// string | undefined&lt;/span&gt;
&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// string | undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the last line is correct.&lt;/p&gt;

&lt;p&gt;But notice that &lt;code&gt;color&lt;/code&gt; is now considered to potentially be undefined too, which will require additional checks.&lt;/p&gt;

&lt;p&gt;Why? Because the &lt;code&gt;css&lt;/code&gt; variable is typed as &lt;code&gt;Record&amp;lt;string, string&amp;gt;&lt;/code&gt;, which does not ensure the existence of any specific property. The explicit generic record type somewhat overrides the more specific type which TypeScript could infer from the concrete value.&lt;/p&gt;

&lt;p&gt;One cannot just delete the explicit type: it would mean that the object is not checked at all and could contain errors (for example, having boolean values).&lt;/p&gt;

&lt;p&gt;But there is a solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt; &lt;span class="o"&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;CssValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;border&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Compilation error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And notice that as TypeScript is now sure there is a &lt;code&gt;color&lt;/code&gt; property, it also allows us to come back to the classic dot syntax!&lt;/p&gt;

&lt;p&gt;As a reminder, all of this would have been avoided with a &lt;code&gt;Map&lt;/code&gt; instead of a record.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt; also applies to array indexes:&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;movies&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;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`The Matrix`&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="cm"&gt;/* In default mode */&lt;/span&gt;
&lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="cm"&gt;/* With `noUncheckedIndexedAccess` */&lt;/span&gt;
&lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// string | undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can causes issues in some places where TypeScript cannot infer information at compilation time, because it depends on concrete values at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* With `noUncheckedIndexedAccess` */&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// string | undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it is easily avoided by writing modern JavaScript, which can be enforced by the &lt;code&gt;prefer-for-of&lt;/code&gt; lint rule:&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;movies&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;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`The Matrix`&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need the index?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movies&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;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`The Matrix`&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;movies&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exact properties types
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#exactOptionalPropertyTypes" rel="noopener noreferrer"&gt;&lt;code&gt;exactOptionalPropertyTypes&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most people think the below 2 ways to define a property are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&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;title&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In TypeScript default mode, they are equivalent. But in reality, at JavaScript runtime, they are not.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;title?: string;&lt;/code&gt; means that the property &lt;code&gt;title&lt;/code&gt; may not exist in the object. But if it exists, it will always be a string.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;title: string | undefined;&lt;/code&gt; means that the property &lt;code&gt;title&lt;/code&gt; will always exist in the object. But its value may be a string or &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In some scenarios, it gives different results:&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;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;optionalStringTitle&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;requiredStringOrUndefinedTitle&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;requiredStringOrUndefinedTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;optionalStringTitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="c1"&gt;// true, but the value is `undefined`&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;requiredStringOrUndefinedTitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;exactOptionalPropertyTypes&lt;/code&gt; enforces to manage these differences correctly, so it reflects the actual runtime behavior.&lt;/p&gt;

&lt;p&gt;When enabled, it also means a third scenario is possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&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;title&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&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="kc"&gt;undefined&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;Question is: which one to choose?&lt;/p&gt;

&lt;p&gt;Whenever the data is a parameter of something (functions mainly), the third form should be chosen to allow both possibilities.&lt;/p&gt;

&lt;p&gt;Why? Because the function consumer may be forced to use one form, and they should be able to use the function without additional transformations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MovieOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&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="nl"&gt;subtitles&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;watchMovie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieOptions&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="cm"&gt;/* All the code below should be OK */&lt;/span&gt;

&lt;span class="nf"&gt;watchMovie&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// No `speed` property&lt;/span&gt;
  &lt;span class="na"&gt;subtitles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// May be `undefined`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subtitles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configFromPreviousCode&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;subtitles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;watchMovie&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;subtitles&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;Otherwise, it will be more complicated to manage some scenarios. Let us imagine a common scenario: library code which does not allow &lt;code&gt;undefined&lt;/code&gt; values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Some library */&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MovieOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;speed&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;subtitles&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;function&lt;/span&gt; &lt;span class="nf"&gt;watchMovie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieOptions&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="cm"&gt;/* User code */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subtitles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;configFromPreviousCode&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;subtitles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;watchMovie&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Compilation error with `exactOptionalPropertyTypes`&lt;/span&gt;
  &lt;span class="nx"&gt;subtitles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// OK&lt;/span&gt;
  &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;subtitles&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;subtitles&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;So it is particularly important from frameworks and libraries author to be aware of this issue.&lt;/p&gt;

&lt;p&gt;Conversely, when owned data is described, it should be described as exactly as possible. For example, when getting JSON data from a HTTP request, some properties will be optional, but it is unlikely that an object contains a property with &lt;code&gt;undefined&lt;/code&gt; as a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MovieFromJSON&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;speed&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;subtitles&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling inexact libraries
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#skipLibCheck" rel="noopener noreferrer"&gt;&lt;code&gt;skipLibCheck&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;exactOptionalPropertyTypes&lt;/code&gt; and &lt;code&gt;noUncheckedIndexedAccess&lt;/code&gt; seem to fix some TypeScript incorrectness. So one could ask why it is not included in &lt;code&gt;strict&lt;/code&gt; mode or in &lt;code&gt;strictNullChecks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From what I know, it is mostly for backward compatibility with existing libraries. Indeed, one will probably meet some library code causing issues here and there, especially with &lt;code&gt;exactOptionalPropertyTypes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So should a project sacrifice some strict options and thus correctness because it includes a non-strict-enough library?&lt;/p&gt;

&lt;p&gt;Hopefully not. Apart from creating an issue and a Pull Request to fix it in the library repository, the &lt;code&gt;skipLibCheck&lt;/code&gt; compiler option can also be enabled.&lt;/p&gt;

&lt;p&gt;It will skip type checks inside library code (meaning code in &lt;code&gt;node_modules&lt;/code&gt;) and just type check the project own code. &lt;/p&gt;

&lt;p&gt;Most frameworks already enable this option by default for performance (less checks = faster compilation), and it is a recommended option in the official TypeScript documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evil !
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/no-non-null-assertion/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-non-null-assertion&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;strict&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-non-null-assertion" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-non-null-assertion&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In TypeScript, the &lt;code&gt;!&lt;/code&gt; operator tells the compiler to trust us about the fact that a data is not &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;, without any checks.&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;// Runtime error if undefined&lt;/span&gt;
&lt;span class="nx"&gt;unsureMovie&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is basically destroying all the nullability safety we talked above. So, of course, it should be prohibited by the &lt;code&gt;no-non-null-assertion&lt;/code&gt; lint rule.&lt;/p&gt;

&lt;p&gt;In most cases, undefined values must be checked with the &lt;code&gt;?&lt;/code&gt; operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;unsureMovie&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Next part
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-4-full-static-types-8bc"&gt;next part&lt;/a&gt; of this posts series, we will explain and solve the third and last problem of TypeScript default behavior: remains of dynamic typing.&lt;/p&gt;

&lt;p&gt;You want to &lt;strong&gt;contact me&lt;/strong&gt;? Instructions are available in the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;summary&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>TypeScript strictly typed - Part 2: full coverage typing</title>
      <dc:creator>Cyrille Tuzi</dc:creator>
      <pubDate>Wed, 12 Jun 2024 16:53:10 +0000</pubDate>
      <link>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-2-full-coverage-typing-4cg1</link>
      <guid>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-2-full-coverage-typing-4cg1</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-1-configuring-a-project-9ca"&gt;previous part&lt;/a&gt; of this &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;posts series&lt;/a&gt;, we discussed about how and when to configure a TypeScript project. Now we will explain and solve the first problem of TypeScript default behavior: from partial to full coverage typing.&lt;/p&gt;

&lt;p&gt;We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is really TypeScript?&lt;/li&gt;
&lt;li&gt;How typing works in TypeScript?&lt;/li&gt;
&lt;li&gt;Required missing types&lt;/li&gt;
&lt;li&gt;Ban any &lt;code&gt;any&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The unknown &lt;code&gt;unknown&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;Required errors checks&lt;/li&gt;
&lt;li&gt;Who is &lt;code&gt;this&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Should we add explicit types everywhere?&lt;/li&gt;
&lt;li&gt;Required objects and arrays types&lt;/li&gt;
&lt;li&gt;Required return types&lt;/li&gt;
&lt;li&gt;Dangerous assertions&lt;/li&gt;
&lt;li&gt;Do not use &lt;em&gt;any&lt;/em&gt; library&lt;/li&gt;
&lt;li&gt;A better TypeScript lib&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is really TypeScript?
&lt;/h2&gt;

&lt;p&gt;This topic requires to understand TypeScript correctly.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.typescriptlang.org" rel="noopener noreferrer"&gt;official TypeScript home page&lt;/a&gt; defines it as &lt;strong&gt;"a strongly typed programming language that builds on JavaScript"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Everyone knows about the first part of the definition. Fewer are fully aware of the second part, "that builds on JavaScript", and what it means exactly.&lt;/p&gt;

&lt;p&gt;It means that TypeScript is a superset of JavaScript. Told differently: &lt;strong&gt;valid JavaScript should be valid TypeScript&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Just change &lt;code&gt;example.js&lt;/code&gt; to &lt;code&gt;example.ts&lt;/code&gt; and it should be OK! (If by doing so, one gets errors, it would only be because they were doing bad things which were undetected in JavaScript, but never because of a TypeScript syntax problem.)&lt;/p&gt;

&lt;p&gt;It was an important decision in TypeScript design, because it is one of the main reasons of its success.&lt;/p&gt;

&lt;p&gt;Indeed, &lt;strong&gt;if one already knows how to program with JavaScript, they already know how to program with TypeScript&lt;/strong&gt;. Sure it will be basic TypeScript, but one does not have to learn a whole new language.&lt;/p&gt;

&lt;h2&gt;
  
  
  How typing works in TypeScript?
&lt;/h2&gt;

&lt;p&gt;But this has a drawback: &lt;strong&gt;TypeScript is only partially typed by default&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let us take a really basic example, which is valid JavaScript (and thus valid TypeScript):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;organic&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;/div&gt;



&lt;p&gt;Given that &lt;code&gt;organic&lt;/code&gt; parameter has a default value, TypeScript is able to automatically infer that its type is &lt;code&gt;boolean&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But TypeScript is not a seer: it cannot infer the type of &lt;code&gt;quantity&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;So with explicit types and without strict mode, the above example is equivalent to 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;function&lt;/span&gt; &lt;span class="nf"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;organic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means that &lt;strong&gt;without strict mode, only a portion of the code is really typed&lt;/strong&gt;. Correctness of what is done with &lt;code&gt;organic&lt;/code&gt; variable will be checked, but not what is done with &lt;code&gt;quantity&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;organic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Compilation OK, but runtime error if `quantity` is a number&lt;/span&gt;
  &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// Compilation error&lt;/span&gt;
  &lt;span class="nx"&gt;organic&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Required missing types
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#noImplicitAny" rel="noopener noreferrer"&gt;&lt;code&gt;noImplicitAny&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;strict&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To fix this behavior, &lt;code&gt;noImplicitAny&lt;/code&gt; is the most important TypeScript compiler option. It is included in &lt;code&gt;strict&lt;/code&gt; mode.&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;// Compilation error in strict mode&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;organic&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;/div&gt;



&lt;p&gt;It enforces explicit types when TypeScript cannot infer automatically:&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;// OK&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quantity&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;organic&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;/div&gt;



&lt;p&gt;Note that &lt;code&gt;noImplicitAny&lt;/code&gt; enforces explicit types only when inference is not possible. So it is not required to add explicit types everywhere. But should we? We will discuss that below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ban any &lt;code&gt;any&lt;/code&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/no-explicit-any/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-explicit-any&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;recommended&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-explicit-any" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-explicit-any&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;noImplicitAny&lt;/code&gt; is not strict enough yet. TypeScript still allows this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Runtime error if `movie` is not a string&lt;/span&gt;
  &lt;span class="nx"&gt;movie&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;any&lt;/code&gt; means it can be anything, so TypeScript will let us do anything from that point. One could consider that &lt;code&gt;movie.toUpperCase()&lt;/code&gt; is not really TypeScript anymore, but just totally unchecked JavaScript.&lt;/p&gt;

&lt;p&gt;So explicit &lt;code&gt;any&lt;/code&gt; must be disallowed completely via the linter &lt;code&gt;no-explicit-any&lt;/code&gt; rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unknown &lt;code&gt;unknown&lt;/code&gt; type
&lt;/h2&gt;

&lt;p&gt;But what to do when one really does not know a data type? The right type to use is &lt;code&gt;unknown&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;movie&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="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Compilation error&lt;/span&gt;
  &lt;span class="nx"&gt;movie&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// OK&lt;/span&gt;
    &lt;span class="nx"&gt;movie&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="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;The difference here is that &lt;code&gt;unknown&lt;/code&gt; means what it means: the data type is unknown, so TypeScript will not let us do anything, except if we check the type by ourself.&lt;/p&gt;

&lt;p&gt;But note that except for very few special cases, data types are usually known. What happens more frequently is that the type can be variable: it is called &lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" rel="noopener noreferrer"&gt;generics&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ApiData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;error&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;ApiData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Movie&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TVSeries&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another reason one could be tempted to use &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;unknown&lt;/code&gt; is when the data structure is too complicated to describe.&lt;/p&gt;

&lt;p&gt;Types can serve here as a design warning: if a structure is too complicated to describe as a type, it should probably be simplified, or maybe the wrong concept is used (an object instead of a &lt;code&gt;Map&lt;/code&gt; for example).&lt;/p&gt;

&lt;h2&gt;
  
  
  Required errors checks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#useUnknownInCatchVariables" rel="noopener noreferrer"&gt;&lt;code&gt;useUnknownInCatchVariables&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;strict&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/use-unknown-in-catch-callback-variable" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/use-unknown-in-catch-callback-variable&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;strict-type-checked&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://typescript-eslint.io/rules/use-unknown-in-catch-callback-variable" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/use-unknown-in-catch-callback-variable&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;useUnknownInCatchVariables&lt;/code&gt; exists because TypeScript cannot be sure at compilation time what will be the type of errors in &lt;code&gt;catch&lt;/code&gt; blocks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Without strict mode */&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;someAction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// `any` type&lt;/span&gt;
  &lt;span class="c1"&gt;// Runtime error if not an `Error`&lt;/span&gt;
  &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* With strict mode */&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;someAction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// `unknown` type&lt;/span&gt;
  &lt;span class="c1"&gt;// Compilation error&lt;/span&gt;
  &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// OK&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;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="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;The same issue happens in the asynchronous version in Promises, but is not handled by the former option.&lt;/p&gt;

&lt;p&gt;The linter &lt;code&gt;use-unknown-in-catch-callback-variable&lt;/code&gt; rule enforces to do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that it is an exceptional case. In normal situations, typing callback functions parameters should not be done like this: it is the responsibility of the outer function to type the callback function, including its parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is &lt;code&gt;this&lt;/code&gt;?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript: &lt;a href="https://www.typescriptlang.org/tsconfig/#noImplicitThis" rel="noopener noreferrer"&gt;&lt;code&gt;noImplicitThis&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;strict&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;ESLint: &lt;a href="https://eslint.org/docs/latest/rules/prefer-arrow-callback" rel="noopener noreferrer"&gt;&lt;code&gt;prefer-arrow-callback&lt;/code&gt;&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Oxlint: missing rule (progress tracked &lt;a href="https://github.com/oxc-project/oxc/issues/479" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;noImplicitThis&lt;/code&gt; is also about avoiding &lt;code&gt;any&lt;/code&gt;, for &lt;code&gt;this&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Matrix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;displayTitle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Runtime error without strict mode,&lt;/span&gt;
      &lt;span class="c1"&gt;// because `this` has changed and is no more the class instance&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;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But note that it happens because the code above is not using correct and modern JavaScript. Arrow functions should be used to keep the &lt;code&gt;this&lt;/code&gt; context.&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;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Matrix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;displayTitle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// OK, `this` is still the class instance&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;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arrow syntax can be enforced by the linter &lt;code&gt;prefer-arrow-callback&lt;/code&gt; rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should we add explicit types everywhere?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/no-inferrable-types/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-inferrable-types&lt;/code&gt;&lt;/a&gt; (in &lt;code&gt;stylistic&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-inferrable-types" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-inferrable-types&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For variables assigned to primitive static values, like strings, numbers and booleans, it is superfluous and just a preference. The preset of TypeScript ESLint enable the &lt;code&gt;no-inferrable-types&lt;/code&gt; rule, which disallows explicit types in this case, to keep the code concise.&lt;/p&gt;

&lt;p&gt;But developers from Java, C# or Rust, who are accustomed to explicit types nearly everywhere, can make the choice to do the same in TypeScript and to disable this rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Required objects and arrays types
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: missing rule&lt;/li&gt;
&lt;li&gt;Oxlint: missing rule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;when it is a more complex structure, like arrays and objects, it is better to use explicit types&lt;/strong&gt;. TypeScript can always infer a type when there is a value, but the inference happens based on what the code does. So we presuppose the code is doing things right.&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;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// Good: classic array, not mixing types&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;explicitArray&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;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// Good: tuple (although rarely the best solution)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;explicitTuple&lt;/span&gt;&lt;span class="p"&gt;:&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;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Bad&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movieWithATypo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;totle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Everything everywhere all at once&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&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;checkedMovie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Everything everywhere all at once&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Required return types
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/explicit-function-return-type" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/explicit-function-return-type&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/explicit-function-return-type" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/explicit-function-return-type&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same goes with functions: TypeScript is always able to infer the return type, but it does so based on what the function does. If the function is modified, the return type will continue to be inferred, but the modifications may have change this type by error.&lt;/p&gt;

&lt;p&gt;The linter &lt;code&gt;explicit-function-return-type&lt;/code&gt; rule enforces to explicitly type the functions returns.&lt;/p&gt;

&lt;p&gt;It is also considered a good practice because &lt;strong&gt;the return type is part of the core and minimal documentation one should include for every function&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dangerous assertions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint: &lt;a href="https://typescript-eslint.io/rules/no-unsafe-type-assertion/" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-unsafe-type-assertion&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Oxlint: &lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-type-assertion" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-unsafe-type-assertion&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Casting with &lt;code&gt;as&lt;/code&gt; tells the compiler to trust us about a type, without any check. It should be prohibited. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#some-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Runtime error if it is not really an input&lt;/span&gt;
&lt;span class="c1"&gt;// or if it does not exist&lt;/span&gt;
&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// OK&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;input&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The worst thing which can be done is 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="nx"&gt;movie&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TVSeries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript sometimes suggests to do that in some scenarios, and it is  a terrible suggestion. Like &lt;code&gt;any&lt;/code&gt;, it is basically bypassing all type checks and going back to blind JavaScript.&lt;/p&gt;

&lt;p&gt;There are justified exceptions. One is when implementing a HTTP client: TypeScript cannot know the type of the JSON sent by the server, so we have to tell it. Still, we are responsible that the client forced type matches the server model.&lt;/p&gt;

&lt;p&gt;Another one is when fixing an "any" coming from a library: casting can serve here to retype correctly.&lt;/p&gt;

&lt;p&gt;Type predicates is just a variant of type assertions for functions returns. The most common case is when filtering an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* With TypeScript &amp;lt;= 5.4 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;:&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;movies&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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;movie&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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;// string | undefined&lt;/span&gt;
    &lt;span class="c1"&gt;// because TypeScript is not capable to narrow the type&lt;/span&gt;
    &lt;span class="c1"&gt;// based on what the code do in `filter`&lt;/span&gt;
    &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;movies&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt; &lt;span class="k"&gt;is&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="nx"&gt;movie&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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;// string&lt;/span&gt;
    &lt;span class="nx"&gt;movie&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;Nice, but the compiler trusts us. If the check does not match the type predicate, errors may happen.&lt;/p&gt;

&lt;p&gt;While this feature can be useful and relevant in some cases, it should be double checked when used.&lt;/p&gt;

&lt;p&gt;Note that I took the &lt;code&gt;filter&lt;/code&gt; example because it is the most frequent one. But now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* With TypeScript &amp;gt;= 5.5 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;:&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;movies&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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;movie&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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;// string&lt;/span&gt;
    &lt;span class="nx"&gt;movie&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;Be sure when updating to TypeScript 5.5 to delete &lt;code&gt;movie is string&lt;/code&gt;, because the behavior is not exactly the same. Explicit &lt;code&gt;movie is string&lt;/code&gt; still means the compiler blindly trusts us. But the new implicit behavior is inferred from the actual code in &lt;code&gt;filter&lt;/code&gt;, so now the type predicate is really checked!&lt;/p&gt;

&lt;p&gt;It also means it becomes an exception of the linter &lt;code&gt;explicit-function-return-type&lt;/code&gt; rule: in such scenarios, the return type should not be explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not use &lt;em&gt;any&lt;/em&gt; library
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ESLint (in &lt;code&gt;recommended-type-checked&lt;/code&gt;):

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://typescript-eslint.io/rules/no-unsafe-argument" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-unsafe-argument&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://typescript-eslint.io/rules/no-unsafe-assignment" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-unsafe-assignment&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://typescript-eslint.io/rules/no-unsafe-call" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-unsafe-call&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://typescript-eslint.io/rules/no-unsafe-member-access" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-unsafe-member-access&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://typescript-eslint.io/rules/no-unsafe-return" rel="noopener noreferrer"&gt;&lt;code&gt;@typescript-eslint/no-unsafe-return&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Oxlint:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-argument" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-unsafe-argument&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-assignment" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-unsafe-assignment&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-call" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-unsafe-call&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-member-access" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-unsafe-member-access&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-unsafe-return" rel="noopener noreferrer"&gt;&lt;code&gt;typescript/no-unsafe-return&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now our code has full coverage typing. But in a real world project, frameworks and libraries are also included. What if they introduced some &lt;code&gt;any&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Some other linter &lt;code&gt;no-unsafe-xxx&lt;/code&gt; rules catch when something typed as &lt;code&gt;any&lt;/code&gt; is used.&lt;/p&gt;

&lt;p&gt;But as a prior step, one should &lt;strong&gt;audit libraries carefully before adding them in a project&lt;/strong&gt;. Accumulating not reliable enough libraries is another major recurring problems in JavaScript projects.&lt;/p&gt;

&lt;p&gt;It can be made into &lt;strong&gt;a criterion of choice: one can go see the &lt;code&gt;tsconfig.json&lt;/code&gt; and the lint configuration in the library GitHub repository to check if it is typed in a strict way&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One should not be too demanding though: currently there are probably no libraries following all the recommendations from this posts series. At the current state of the TypeScript ecosystem, having the &lt;code&gt;strict&lt;/code&gt; mode and the &lt;code&gt;no-explicit-any&lt;/code&gt; rule is already a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better TypeScript lib
&lt;/h2&gt;

&lt;p&gt;There is one hole left in our typing coverage: what about the types of native JavaScript functions and classes?&lt;/p&gt;

&lt;p&gt;Few knows it, but if our code editor knows what is the type expected by &lt;code&gt;JSON.parse()&lt;/code&gt; for example, it is because TypeScript includes definitions for every JavaScript native API, in what is called "libs".&lt;/p&gt;

&lt;p&gt;In Visual Studio Code, if we cmd/ctrl click on &lt;code&gt;parse()&lt;/code&gt;, we arrive in a file called &lt;code&gt;lib.es5.d.ts&lt;/code&gt;, with definitions for a lot of JavaScript functions. And in this example, we see &lt;code&gt;any&lt;/code&gt; as the return type.&lt;/p&gt;

&lt;p&gt;Those &lt;code&gt;any&lt;/code&gt; have a historical reason (for example, &lt;code&gt;unknown&lt;/code&gt; did not exist in the very first versions of TypeScript). And correcting that now would break a lot of existing projects, so it is unlikely to happen.&lt;/p&gt;

&lt;p&gt;But even fewer knows these definitions can be overridden. It is what does the amazing &lt;a href="https://github.com/uhyo/better-typescript-lib" rel="noopener noreferrer"&gt;&lt;code&gt;better-typescript-lib&lt;/code&gt;&lt;/a&gt; by &lt;a href="https://github.com/sponsors/uhyo" rel="noopener noreferrer"&gt;uhyo&lt;/a&gt;. And what is really magical is that one just needs to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;better-typescript-lib &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we are done! &lt;strong&gt;Now JavaScript native APIs will be typed correctly with no more &lt;code&gt;any&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To be transparent: I discovered this wonder very recently. My first usages of it were successful, but I have little perspective on it yet. But it is not a big risk: in worst case scenario, just uninstall the library and that is it.&lt;/p&gt;

&lt;p&gt;Note that the &lt;code&gt;use-unknown-in-catch-callback-variable&lt;/code&gt; lint rule becomes useless with this tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next part
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed the meta jokes.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-3-safe-nullability-38mf"&gt;next part&lt;/a&gt; of this posts series, we will explain and solve the second problem of TypeScript default behavior: nullability.&lt;/p&gt;

&lt;p&gt;You want to &lt;strong&gt;contact me&lt;/strong&gt;? Instructions are available in the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;summary&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>TypeScript strictly typed - Part 1: configuring a project</title>
      <dc:creator>Cyrille Tuzi</dc:creator>
      <pubDate>Wed, 12 Jun 2024 16:50:22 +0000</pubDate>
      <link>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-1-configuring-a-project-9ca</link>
      <guid>https://dev.to/cyrilletuzi/typescript-strictly-typed-part-1-configuring-a-project-9ca</guid>
      <description>&lt;p&gt;After the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-intro-reliability-and-productivity-32aj"&gt;introduction&lt;/a&gt; of this &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;posts series&lt;/a&gt;, we are going to the topic's technical core. First, we will talk about configuration, and why &lt;strong&gt;it is very important to do it at the very beginning of a project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When to enable strict options?&lt;/li&gt;
&lt;li&gt;Frameworks status&lt;/li&gt;
&lt;li&gt;Full configuration (the hard way)&lt;/li&gt;
&lt;li&gt;Automatic configuration (the easy way)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to enable strict options?
&lt;/h2&gt;

&lt;p&gt;I cannot insist more on the fact that &lt;strong&gt;strict options must be enabled at the very beginning of any project&lt;/strong&gt;. Doing so is an easy and straightforward process: one just has to gradually type correctly when coding.&lt;/p&gt;

&lt;p&gt;But enabling strict options in an on-going project is a completely different matter: even if TypeScript default mode is capable of inferring types in the majority of cases, the remaining untyped places are a proportion of the codebase. So the more code, the more places to fix, and it requires a clear understanding of what each code is doing.&lt;/p&gt;

&lt;p&gt;It is one of the main recurring big errors I have seen in all the companies I have helped over the last decade as a TypeScript expert. Recovering from it is good but really time consuming and painful.&lt;/p&gt;

&lt;p&gt;So &lt;strong&gt;be sure to always check a new project is in strict mode before to start coding&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks status
&lt;/h2&gt;

&lt;p&gt;TypeScript strict mode is enabled automatically when generating a project with the last versions of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;: &lt;code&gt;tsc --init&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.dev" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;: &lt;code&gt;npm init @angular@latest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://create-react-app.dev" rel="noopener noreferrer"&gt;React App&lt;/a&gt;: &lt;code&gt;npx create-react-app --template typescript&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;: &lt;code&gt;npx create-next-app@latest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org" rel="noopener noreferrer"&gt;Vue&lt;/a&gt;: &lt;code&gt;npm create vue@latest&lt;/code&gt;, then choosing TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://deno.com" rel="noopener noreferrer"&gt;Deno&lt;/a&gt;: by default&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note &lt;strong&gt;it has not always been the case with older versions of these frameworks&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full configuration (the hard way)
&lt;/h2&gt;

&lt;p&gt;We will see in the next parts that the "strict" mode is not enough. Other TypeScript compiler options must be enabled, as well as some lint rules.&lt;/p&gt;

&lt;p&gt;A complete configuration would look like this:&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript compiler options
&lt;/h3&gt;

&lt;p&gt;For TypeScript, in &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;compilerOptions:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;strict:&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="err"&gt;exactOptionalPropertyTypes:&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="err"&gt;noPropertyAccessFromIndexSignature:&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="err"&gt;noUncheckedIndexedAccess:&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;Note that &lt;code&gt;strict&lt;/code&gt; is now enabled by default in TypeScript &amp;gt;= 6.&lt;/p&gt;

&lt;h3&gt;
  
  
  ESLint
&lt;/h3&gt;

&lt;p&gt;For &lt;a href="https://eslint.org" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; + &lt;a href="https://typescript-eslint.io/" rel="noopener noreferrer"&gt;TypeScript ESLint&lt;/a&gt;, with the new flat config &lt;code&gt;eslint.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;eslint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recommended&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;tseslint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strictTypeChecked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;tseslint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stylisticTypeChecked&lt;/span&gt;&lt;span class="p"&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;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="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;eqeqeq&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;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;prefer-arrow-callback&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;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;prefer-template&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;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;@typescript-eslint/explicit-function-return-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;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;@typescript-eslint/no-explicit-any&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;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;@typescript-eslint/no-non-null-assertion&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;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;@typescript-eslint/no-unsafe-argument&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;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;@typescript-eslint/no-unsafe-assignment&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;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;@typescript-eslint/no-unsafe-call&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;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;@typescript-eslint/no-unsafe-member-access&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;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;@typescript-eslint/no-unsafe-return&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;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;@typescript-eslint/no-unsafe-type-assertion&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;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;@typescript-eslint/prefer-for-of&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;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;@typescript-eslint/prefer-nullish-coalescing&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;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;@typescript-eslint/prefer-optional-chain&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;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;@typescript-eslint/restrict-plus-operands&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="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allowAny&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allowBoolean&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allowNullish&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allowNumberAndString&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allowRegExp&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@typescript-eslint/restrict-template-expressions&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;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;@typescript-eslint/strict-boolean-expressions&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="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allowNumber&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allowString&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@typescript-eslint/use-unknown-in-catch-callback-variable&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;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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important: many of these rules require &lt;a href="https://typescript-eslint.io/getting-started/typed-linting" rel="noopener noreferrer"&gt;typed linting&lt;/a&gt;, which is configured above with &lt;code&gt;project: true&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Oxlint
&lt;/h3&gt;

&lt;p&gt;For &lt;a href="https://eslint.org" rel="noopener noreferrer"&gt;Oxlint&lt;/a&gt;, in &lt;code&gt;.oxlintrc.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./node_modules/oxlint/configuration_schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"options"&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;"typeAware"&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="nl"&gt;"rules"&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;"eqeqeq"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prefer-template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/explicit-function-return-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-explicit-any"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-non-null-assertion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-unsafe-argument"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-unsafe-assignment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-unsafe-call"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-unsafe-member-access"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-unsafe-return"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/no-unsafe-type-assertion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/prefer-for-of"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/prefer-nullish-coalescing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/prefer-optional-chain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/restrict-plus-operands"&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="s2"&gt;"deny"&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;"allowAny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowBoolean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowNullish"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowNumberAndString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowRegExp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/restrict-template-expressions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/strict-boolean-expressions"&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="s2"&gt;"deny"&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;"allowNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"allowString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript/use-unknown-in-catch-callback-variable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&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;Important: many of these rules require &lt;a href="https://oxc.rs/docs/guide/usage/linter/type-aware.html" rel="noopener noreferrer"&gt;type-aware linting&lt;/a&gt;, which require additional setup.&lt;/p&gt;

&lt;p&gt;Also, while Oxlint puts forward as an advantage the fact that no configuration is required by default, be careful that nearly none of the rules presented in these posts are enabled by default in Oxlint, so you &lt;em&gt;do&lt;/em&gt; need a configuration file to achieve proper strict typing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Biome
&lt;/h3&gt;

&lt;p&gt;Biome initially planned feature parity with ESLint. Unfortunately, this goal has been &lt;a href="https://github.com/biomejs/biome/discussions/3" rel="noopener noreferrer"&gt;abandoned&lt;/a&gt;. It means that a lot of the lint rules required to enforce strong, static and complete typing are missing in Biome.&lt;/p&gt;

&lt;p&gt;As a consequence, for a project where strict typing is a goal, Biome is probably not the adequate choice. If one is looking for an alternative to ESLint and an equivalent of Biome, &lt;a href="https://oxc.rs/docs/guide/usage/linter.html" rel="noopener noreferrer"&gt;Oxlint&lt;/a&gt; mentioned above seems the new way to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deno
&lt;/h3&gt;

&lt;p&gt;For &lt;a href="https://lint.deno.land" rel="noopener noreferrer"&gt;Deno&lt;/a&gt;, in &lt;code&gt;deno.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="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;"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="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;"useUnknownInCatchVariables"&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="nl"&gt;"lint"&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;"rules"&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;"tags"&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="s2"&gt;"recommended"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"eqeqeq"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"explicit-function-return-type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"no-non-null-assertion"&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;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;h3&gt;
  
  
  Notes
&lt;/h3&gt;

&lt;p&gt;Note that these configuration examples only include options and rules related to this posts series topic. Other options and rules may be added to enforce other TypeScript good practices not related to strict typing.&lt;/p&gt;

&lt;p&gt;For all tools, &lt;strong&gt;be careful if a configuration extends another one&lt;/strong&gt;. It could mean that even if a preset like &lt;code&gt;strict&lt;/code&gt; is enabled, one of the individual option included in the preset is disabled in the parent configuration. So in this case, all options should be enabled individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatic configuration (the easy way)
&lt;/h2&gt;

&lt;p&gt;Totally optional, but if one does not want to lose time to remember and configure all these options manually, one can run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx typescript-strictly-typed@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is &lt;a href="https://github.com/cyrilletuzi/typescript-strictly-typed" rel="noopener noreferrer"&gt;a tool I published&lt;/a&gt; to automatically add all the strict options in a TypeScript project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next part
&lt;/h3&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-2-full-coverage-typing-4cg1"&gt;next part&lt;/a&gt; of this posts series, we will explain and solve the first problem of TypeScript default behavior: from partial to full coverage typing.&lt;/p&gt;

&lt;p&gt;You want to &lt;strong&gt;contact me&lt;/strong&gt;? Instructions are available in the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;summary&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>TypeScript strictly typed - Intro: reliability and productivity</title>
      <dc:creator>Cyrille Tuzi</dc:creator>
      <pubDate>Wed, 12 Jun 2024 16:48:13 +0000</pubDate>
      <link>https://dev.to/cyrilletuzi/typescript-strictly-typed-intro-reliability-and-productivity-32aj</link>
      <guid>https://dev.to/cyrilletuzi/typescript-strictly-typed-intro-reliability-and-productivity-32aj</guid>
      <description>&lt;p&gt;Before going to the technical core of this posts series, we said in the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;summary&lt;/a&gt; that by default TypeScript:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;only partially enforces typing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;does not handle nullability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;retains some JavaScript's dynamic typing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will explain these 3 problems and their solution in the next parts, but first, why is it important to solve them? Developers coming from Java, C# or Rust may not need to be convinced, and could skip this introduction.&lt;/p&gt;

&lt;p&gt;We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript true promise&lt;/li&gt;
&lt;li&gt;Reliability: bugs reduction&lt;/li&gt;
&lt;li&gt;Productivity: easier and faster debug&lt;/li&gt;
&lt;li&gt;Productivity: better autocompletion&lt;/li&gt;
&lt;li&gt;Productivity: less tests to write&lt;/li&gt;
&lt;li&gt;Scalability: safer refactoring&lt;/li&gt;
&lt;li&gt;Design: better and simpler code&lt;/li&gt;
&lt;li&gt;Put into perspective&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TypeScript true promise
&lt;/h2&gt;

&lt;p&gt;Having a code as correct as possible is not about being picky or about wanting a pretty code. It has very important and concrete consequences for a company.&lt;/p&gt;

&lt;p&gt;Imagine one finds a magic box which can guess the lottery numbers. They just press the obvious big button on it and it guesses 3 out of 6 lottery numbers.&lt;/p&gt;

&lt;p&gt;Now they turn the box upside down and press the little and barely visible secret button with "strict" written on it. Now the box guesses 5 of the 6 lottery numbers. But wait! There is also a super secret button with "strict + lint" written on it. Now the box guesses all the 6 lottery numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using TypeScript with its default behavior is basically the same as using the magic box without the secret buttons.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So answering why enforcing static, strong and complete typing is important is the same as answering why TypeScript is important. Once it is clear, it is just common sense to &lt;strong&gt;use TypeScript to its maximum potential&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability: bugs reduction
&lt;/h2&gt;

&lt;p&gt;It is the most obvious benefit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript: 0% code verified, 100% risk of bugs&lt;/li&gt;
&lt;li&gt;TypeScript without strict mode: ~50% code verified, 50% risk of bugs&lt;/li&gt;
&lt;li&gt;TypeScript with strict mode: ~75% code verified, 25% risk of bugs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript strictly typed: ~100% code verified, 0% risk of bugs&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To be clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;percentages are a rough estimate from my experience, not exact science&lt;/li&gt;
&lt;li&gt;0% risk of bugs = 0% risk of bugs which are handled by strong and static types, but of course there are other types of bugs which are still possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put in a real world context, where front-end teams are often new small teams, &lt;strong&gt;the maintenance costs are very important&lt;/strong&gt;. If a team is made up of only 3 people, and 2 of them use all of their time to fix bugs, it means there is only one person left to add new product features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Productivity: easier and faster debug
&lt;/h2&gt;

&lt;p&gt;To check the code, TypeScript introduces a compilation step, like in other typed languages like Java, C# or Rust. And in TypeScript, compilation is happening in "watch" mode, while one is coding.&lt;/p&gt;

&lt;p&gt;It is &lt;strong&gt;a totally different experience when it comes to debugging&lt;/strong&gt;. Let us take a very basic 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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#missing-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The Matrix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With TypeScript strictly typed, the error is shown directly and immediately as one is coding (via the editor or via the compilation logs). There may even be a suggestion about how to fix the issue. &lt;strong&gt;It takes a few seconds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now going back to the raw JavaScript experience: everything seems OK in the editor. One has to launch a development server, go in the browser and open the console. Yet it is not enough: the console logs may be totally OK at this point. One has to reproduce the steps to trigger the scenario where the faulty code is called.&lt;/p&gt;

&lt;p&gt;We are now talking about &lt;strong&gt;minutes of debugging&lt;/strong&gt;, which can extend to hours.&lt;/p&gt;

&lt;p&gt;And now imagine the faulty code is called in a scenario which does not happen often or which happens only under specific conditions. So it goes totally unnoticed while developing in local environment, and a bug is pushed to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Productivity: better autocompletion
&lt;/h2&gt;

&lt;p&gt;If TypeScript is able to check all the code because everything is correctly typed, it also means the editor can help with autocompletion everywhere.&lt;/p&gt;

&lt;p&gt;Once one goes back to &lt;code&gt;any&lt;/code&gt;, the editor becomes blind, and cannot assist the developer anymore.&lt;/p&gt;

&lt;p&gt;Interesting fact: if editor autocompletion in JavaScript is far better than some years ago, it is because it is now handled by TypeScript, even for pure JavaScript files!&lt;/p&gt;

&lt;p&gt;So in some sense, like it or not, &lt;strong&gt;everyone is doing TypeScript today, and it is just a waste to not go for its full potential&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Productivity: less tests to write
&lt;/h2&gt;

&lt;p&gt;If one is talking about testing strategies, but TypeScript is not in a strictly typed configuration, priorities may have to be reconsidered.&lt;/p&gt;

&lt;p&gt;A very common and indicative case are unit tests checking unexpected &lt;code&gt;undefined&lt;/code&gt; values: &lt;strong&gt;with TypeScript strictly typed, it cannot happen at all, so it does not need to be tested&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Everyone who has already written tests in a front-end project knows how time consuming it is. Also, the more tests = the more time the continuous integration tools (like GitHub Actions or else) take. And as these tools are not free, &lt;strong&gt;the more it costs to the company&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scalability: safer refactoring
&lt;/h2&gt;

&lt;p&gt;For the same reasons as for bugs, &lt;strong&gt;refactoring is a lot easier when in TypeScript strictly typed&lt;/strong&gt;, because if one breaks something while refactoring, compilation will see it and notify it right away.&lt;/p&gt;

&lt;p&gt;The accumulation of technical debt being one of the other major problems of most projects, being able to easily evolve is essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design: better and simpler code
&lt;/h2&gt;

&lt;p&gt;This benefit is rarely evoked, but I realized with experience that &lt;strong&gt;TypeScript is also a good indicator when designing code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Too difficult to express the type of a variable? One may have chosen the wrong data structure, or a too nested one which would be easier to work with if it was flattened.&lt;/p&gt;

&lt;p&gt;Too difficult to express the signature of a function? It may do too much things and not respect the single responsibility principle, or it may try to abstract too much.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put into perspective
&lt;/h2&gt;

&lt;p&gt;While the options names like "strict", which we will discuss in the next parts, may suggest it is an additional effort to do, it is not: enabling all the strict options we will discuss is just &lt;strong&gt;putting JavaScript at an equivalent level than the basic and default mode of the other typed languages&lt;/strong&gt; like Java, C# or Rust.&lt;/p&gt;

&lt;p&gt;One could say that it is TypeScript default mode which is a "loose" mode, while &lt;strong&gt;"strict" mode is just the normal mode if one wants to use strong and static types&lt;/strong&gt;, which is what TypeScript is for in the first place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next part
&lt;/h3&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-part-1-configuring-a-project-9ca"&gt;next part&lt;/a&gt; of this posts series, we will explain how to configure a project to guarantee strict typing, and especially when it is important to do it.&lt;/p&gt;

&lt;p&gt;You want to &lt;strong&gt;contact me&lt;/strong&gt;? Instructions are available in the &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln"&gt;summary&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>TypeScript strictly typed: the true promise of TypeScript</title>
      <dc:creator>Cyrille Tuzi</dc:creator>
      <pubDate>Wed, 12 Jun 2024 16:45:52 +0000</pubDate>
      <link>https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln</link>
      <guid>https://dev.to/cyrilletuzi/typescript-strictly-typed-5fln</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Over the last decade, as a JavaScript expert, I helped companies of all kinds and sizes. Over time, I detected a series of some recurring major problems in nearly all projects.&lt;/p&gt;

&lt;p&gt;One of them is &lt;strong&gt;a lack of typing, resulting in a lack of reliability and an exponential decline in productivity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Yet, all these projects were coded in &lt;a href="https://www.typescriptlang.org" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;. Should not it guarantee typing like in Java, C# or Rust?&lt;/p&gt;

&lt;p&gt;Short answer: no, because by default TypeScript:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;only partially enforces typing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;does not handle nullability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;retains some JavaScript's dynamic typing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These problems can be solved with adequate configuration and the resulting good practices. But for that, &lt;strong&gt;even strict mode&lt;/strong&gt;, if one knows about it, &lt;strong&gt;is not enough&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This posts series claims to be &lt;strong&gt;a reference about a strong, static and complete typing in TypeScript&lt;/strong&gt;, and I will try to keep it up to date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Target audience
&lt;/h3&gt;

&lt;p&gt;This posts series is intended for developers who already know TypeScript and who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;do not know about strict mode&lt;/li&gt;
&lt;li&gt;do know about strict mode but think it is enough to guarantee sufficient typing&lt;/li&gt;
&lt;li&gt;know languages like Java, C# or Rust and want a similar typing level in TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;want to increase reliability of their code&lt;/strong&gt; and reduce the risk of bugs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;want to increase productivity&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This posts series is not intended for people who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;do not like TypeScript and already have a definitive opinion about it&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Changelog
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;2026/04/03: added a note about strict being enabled by default in TypeScript &amp;gt;= 6&lt;/li&gt;
&lt;li&gt;2026/02/26: added Oxlint rules and configuration instead&lt;/li&gt;
&lt;li&gt;2026/02/26: removed Biome rules and configuration, and added a note about Biome not being the most adequate choice when strict typing is a goal, as too many important lint rules are missing&lt;/li&gt;
&lt;li&gt;2026/02/26: updated ESLint configuration example to match the latest updates, and removed ESLint legacy configuration example as it is not supported anymore by the latest ESLint version&lt;/li&gt;
&lt;li&gt;2024/11/18: dangerous assertions mentioned in part 2 can now be caught by the new &lt;code&gt;no-unsafe-type-assertion&lt;/code&gt; ESLint rule&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Contact
&lt;/h3&gt;

&lt;p&gt;You can start a direct discussion with me on &lt;a href="https://www.linkedin.com/in/cyrilletuzi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; (if you cannot send me a message directly, please add a note to your contact request).&lt;/p&gt;

&lt;h3&gt;
  
  
  French version
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/pulse/typescript-strictement-typ%25C3%25A9-cyrille-tuzi-k5ide/" rel="noopener noreferrer"&gt;A French version is available on LinkedIn&lt;/a&gt; (initial version without the updates).&lt;/p&gt;

&lt;h3&gt;
  
  
  Next part
&lt;/h3&gt;

&lt;p&gt;Before going into the topic's technical core, we will start this posts series with an &lt;a href="https://dev.to/cyrilletuzi/typescript-strictly-typed-intro-reliability-and-productivity-32aj"&gt;introduction&lt;/a&gt; about why solving the 3 problems above is important for &lt;strong&gt;reliability and  productivity&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
