<?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: Serhii</title>
    <description>The latest articles on DEV Community by Serhii (@sergchr).</description>
    <link>https://dev.to/sergchr</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%2F87708%2F20cb9621-98d5-4a93-bdd5-177859ca96d6.png</url>
      <title>DEV Community: Serhii</title>
      <link>https://dev.to/sergchr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sergchr"/>
    <language>en</language>
    <item>
      <title>Prefer strict types in Typescript</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Mon, 06 May 2024 13:49:24 +0000</pubDate>
      <link>https://dev.to/sergchr/prefer-strict-types-in-typescript-p4i</link>
      <guid>https://dev.to/sergchr/prefer-strict-types-in-typescript-p4i</guid>
      <description>&lt;p&gt;Types should be as close to reality as possible. Otherwise, they mislead (reduce truthiness in the system) and, thus, slow down development.&lt;/p&gt;

&lt;p&gt;Usually, it's self-evident in many statically typed languages, but it's a different case with Typescript since it allows more types flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  any
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any" rel="noopener noreferrer"&gt;&lt;code&gt;any&lt;/code&gt;&lt;/a&gt; may be a favorite type for many developers who migrated from Javascript recently. It declares that a type could be anything. There are some use cases for using &lt;code&gt;any&lt;/code&gt;, but usually it's recommended to not employ it.  One such example I could think of is silencing the Typescript compiler to run a script quickly. Otherwise, it detracts truth from a system and eliminates the benefits of using Typescript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-5-1.BxLmC4H4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-5-1.BxLmC4H4.gif" alt="any type in typescript visualized"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't know what your data looks like, how are you going to handle it properly? Without proper handling, a system (or part of it) fails.&lt;/p&gt;

&lt;p&gt;The other disadvantage of using &lt;code&gt;any&lt;/code&gt; is silencing any potential errors you make when handling such data, which leads to another system failure.&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;anything&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;word&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;anything&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you remove &lt;code&gt;any&lt;/code&gt; declaration from the &lt;code&gt;anything&lt;/code&gt; constant, Typescript tells you what is wrong exactly.&lt;/p&gt;

&lt;p&gt;What if I don't know the exact type of data? Imagine I retrieve it from a third-party API that may change tomorrow. Or, from a non-typed &lt;code&gt;npm&lt;/code&gt; package because it's written in Javascript. This is where we use &lt;code&gt;unknown&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  unknown
&lt;/h2&gt;

&lt;p&gt;The useful &lt;code&gt;unknown&lt;/code&gt; type states that a variable shape is not known and can be anything, the same point as &lt;code&gt;any&lt;/code&gt; declares. The only difference is that &lt;code&gt;unknown&lt;/code&gt; requires the compiler to check a type first &lt;strong&gt;before&lt;/strong&gt; operating on data.&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;anything&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;anything&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="nx"&gt;anything&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The primary use case for &lt;code&gt;unknown&lt;/code&gt; is to mark variables that are unknown and can be anything, so you must validate a type first before manipulating data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-5-1.BxLmC4H4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-5-1.BxLmC4H4.gif" alt="unknown type visualized"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If data shape is known, it's always better to specify an accurate type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Narrowing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html" rel="noopener noreferrer"&gt;Narrowing&lt;/a&gt; is a process of giving types more accurate shapes. I.e., bringing them to reality, so they reflect a real data form.&lt;/p&gt;

&lt;p&gt;To illustrate the motivation behind it, take a look at 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;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;field2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;field3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, &lt;code&gt;record&lt;/code&gt;, is &lt;code&gt;Record&amp;lt;string, number&amp;gt;&lt;/code&gt;, but it's not accurate enough. &lt;code&gt;Record&lt;/code&gt; means an object with who knows how many fields and their values are of type &lt;code&gt;number&lt;/code&gt;. In this case, a more accurate type is &lt;code&gt;{ field: number; }&lt;/code&gt;. In this example, you can skip declaring a type because the compiler can infer it automatically.&lt;/p&gt;

&lt;p&gt;Another example of bad narrowing:&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;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&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;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, &lt;code&gt;fn&lt;/code&gt; is a function, but this type doesn't specify the details (and as in the case above, you should skip declaring a type explicitly because the compiler will infer it for you automatically).&lt;/p&gt;

&lt;h2&gt;
  
  
  Common types to narrow
&lt;/h2&gt;

&lt;p&gt;For these examples, &lt;code&gt;T&lt;/code&gt; can be any type.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Record&amp;lt;string, T&amp;gt;&lt;/code&gt;: prefer an accurate object shape, &lt;strong&gt;if you know it&lt;/strong&gt;. E.g.,
&lt;/li&gt;
&lt;/ol&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;MyObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;ol&gt;
&lt;li&gt;
&lt;code&gt;T | null | undefined&lt;/code&gt; means you need to handle both &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; cases besides the presence of value. Prefer &lt;code&gt;T | null&lt;/code&gt;, &lt;code&gt;T | undefined&lt;/code&gt;, or merely &lt;code&gt;T&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Function&lt;/code&gt;: prefer an exact function signature, e.g.:
&lt;/li&gt;
&lt;/ol&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;MyFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg1&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;arg2&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;: prefer a more accurate type.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Originally published on &lt;a href="https://absolyd.com/ts-strict-types" rel="noopener noreferrer"&gt;absolyd.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>types</category>
      <category>narrowing</category>
    </item>
    <item>
      <title>Having a type system is more productive</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Sun, 05 May 2024 11:56:19 +0000</pubDate>
      <link>https://dev.to/sergchr/having-a-type-system-is-more-productive-2na9</link>
      <guid>https://dev.to/sergchr/having-a-type-system-is-more-productive-2na9</guid>
      <description>&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Type_system" rel="noopener noreferrer"&gt;type system&lt;/a&gt; enables multiple benefits to developers. At least, it uncovers data flow complexity.&lt;/p&gt;

&lt;p&gt;A codebase with types becomes more intuitive and connected, primarily by making data flow visible. So, at each moment of time when I work with code, I know the input and the result after transformation or some processing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-4-1.B1FzKuv9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-4-1.B1FzKuv9.gif" alt="Types + codebase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the contrary, working with a language like Javascript provides more flexibility. However, the cost is huge: you hide data flow complexity while the problem is still there. By silencing the issue, we don't solve it, even though we can postpone encountering the consequent problems that stem from this root issue.&lt;/p&gt;

&lt;p&gt;For example, I may send to a function invalid input without knowing it (assume this function is large and complex to understand), which results in a runtime error, that we'd like to avoid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-4-2.CMvQuUDc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-4-2.CMvQuUDc.gif" alt="invalid function input"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A type system tells what's wrong when a developer writes code. Thus, it's easier to catch problems before they arise in a production system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-4-3.BoSF97cH.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fabsolyd.com%2F_astro%2Fpost-4-3.BoSF97cH.gif" alt="function input with types"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code becomes more readable since you now understand the interconnectedness between various components better. Both writing and reading code are faster.&lt;/p&gt;




&lt;p&gt;Originally published on &lt;a href="https://absolyd.com/type-system-is-productive" rel="noopener noreferrer"&gt;absolyd.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>types</category>
    </item>
    <item>
      <title>26 No-code Tools to Speed Up Your Idea Release</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Sat, 16 Dec 2023 08:32:00 +0000</pubDate>
      <link>https://dev.to/sergchr/26-no-code-tools-to-speed-up-your-idea-release-1l09</link>
      <guid>https://dev.to/sergchr/26-no-code-tools-to-speed-up-your-idea-release-1l09</guid>
      <description>&lt;p&gt;No-code tools are a game-changer for software engineers and non-coders. They empower them to build, automate, and integrate various applications and services without writing much code, most of the time. This opens up a world of possibilities, allowing us to focus on more complex tasks while accelerating the development process for routine tasks.&lt;/p&gt;

&lt;p&gt;Let’s take a look at some remarkable no-code tools that can enhance your productivity:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Zapier
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://zapier.com"&gt;Zapier&lt;/a&gt; is a versatile tool that lets you connect and automate tasks between different web apps without writing a single line of code. Whether it's automating emails, updating spreadsheets, or integrating your favorite apps, Zapier has you covered.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Integromat
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.integromat.com"&gt;Integromat&lt;/a&gt; is a powerful automation platform that simplifies the integration of various apps and services using visual workflows. Create complex automation scenarios with ease, all without diving into code.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Microsoft Power Automate
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://flow.microsoft.com"&gt;Microsoft Power Automate&lt;/a&gt; (formerly Microsoft Flow) offers seamless workflow automation and integration with Microsoft services and other applications. Leverage your expertise in Microsoft tools without extensive coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Airtable
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://airtable.com"&gt;Airtable&lt;/a&gt; combines the simplicity of a spreadsheet with the complexity of a database, enabling you to create custom workflows and applications effortlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Parabola
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://parabola.io"&gt;Parabola&lt;/a&gt; is a no-code data integration tool that simplifies data manipulation and automation, freeing you from repetitive coding tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Bubble
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://bubble.io"&gt;Bubble&lt;/a&gt; is a no-code platform that empowers you to build web applications with database functionality, providing a coding-free way to bring your ideas to life.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Adalo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.adalo.com"&gt;Adalo&lt;/a&gt; offers a no-code platform for creating mobile and web apps using a visual builder, making app development accessible to non-coders.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. AppSheet
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.appsheet.com"&gt;AppSheet&lt;/a&gt; allows you to create no-code mobile apps directly from data sources like Google Sheets, streamlining app development.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. OutSystems
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.outsystems.com"&gt;OutSystems&lt;/a&gt; is a low-code development platform that combines visual development with full-stack capabilities, providing a bridge between no-code and traditional coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Kissflow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kissflow.com"&gt;Kissflow&lt;/a&gt; is a no-code platform tailored for building and automating business processes and workflows, helping you optimize efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. Quick Base
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.quickbase.com"&gt;Quick Base&lt;/a&gt; provides a no-code application building platform to create custom business apps, making application development more accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. Retool
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://retool.com"&gt;Retool&lt;/a&gt; is a low-code platform focused on building internal tools and workflows quickly, streamlining your internal processes.&lt;/p&gt;

&lt;h3&gt;
  
  
  13. Tonkean
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://tonkean.com"&gt;Tonkean&lt;/a&gt; is an AI-powered no-code platform that assists businesses in automating workflows and optimizing processes, allowing you to work smarter.&lt;/p&gt;

&lt;h3&gt;
  
  
  14. Coda
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://coda.io"&gt;Coda&lt;/a&gt; combines documents, spreadsheets, and apps into a single platform for teams, offering a comprehensive solution for collaboration and automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  15. Stacker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stacker.app"&gt;Stacker&lt;/a&gt; enables you to build web applications from your Airtable data without writing code, simplifying application development.&lt;/p&gt;

&lt;h3&gt;
  
  
  16. Ninox
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ninoxdb.de"&gt;Ninox&lt;/a&gt; is a no-code database platform for building custom business applications, offering a versatile solution for your development needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  17. Adalo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.adalo.com"&gt;Adalo&lt;/a&gt; is a no-code platform for building mobile and web apps with a visual builder. It provides an intuitive interface for designing and developing apps without coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  18. AppSheet
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.appsheet.com"&gt;AppSheet&lt;/a&gt; allows you to create no-code mobile apps directly from data sources like Google Sheets. It simplifies the app development process by generating apps based on your data.&lt;/p&gt;

&lt;h3&gt;
  
  
  19. OutSystems
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.outsystems.com"&gt;OutSystems&lt;/a&gt; is a low-code development platform that combines visual development with full-stack capabilities. While it leans toward low-code, it offers a no-code approach for certain tasks, making it versatile for different development needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  20. Kissflow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kissflow.com"&gt;Kissflow&lt;/a&gt; is a no-code platform for building and automating business processes and workflows. It offers a wide range of pre-built applications and templates to streamline various business operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  21. Quick Base
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.quickbase.com"&gt;Quick Base&lt;/a&gt; provides a no-code application building platform to create custom business apps. It offers a visual interface and powerful customization options for tailoring apps to your specific requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  22. Retool
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://retool.com"&gt;Retool&lt;/a&gt; is a low-code platform focused on building internal tools and workflows quickly. While it offers some coding capabilities, its visual development environment allows for rapid app creation with minimal coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  23. Tonkean
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://tonkean.com"&gt;Tonkean&lt;/a&gt; is an AI-powered no-code platform that helps businesses automate workflows and optimize processes. It uses AI to intelligently orchestrate tasks and data across various systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  24. Coda
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://coda.io"&gt;Coda&lt;/a&gt; combines documents, spreadsheets, and apps into a single platform for teams. It offers a unique approach to building interactive documents and applications without traditional coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  25. Stacker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stacker.app"&gt;Stacker&lt;/a&gt; lets you build web applications from your Airtable data without code. It simplifies the process of turning your Airtable data into user-friendly web apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  26. Ninox
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ninoxdb.de"&gt;Ninox&lt;/a&gt; is a no-code database platform for building custom business applications. It provides robust database and app-building capabilities without requiring extensive coding skills.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://absolyd.com/26-no-code-tools"&gt;Originally published at absolyd.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>links</category>
      <category>nocode</category>
      <category>automation</category>
    </item>
    <item>
      <title>How to create a story game with Javascript</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Thu, 27 Oct 2022 11:00:21 +0000</pubDate>
      <link>https://dev.to/sergchr/how-to-create-a-story-game-with-javascript-47hj</link>
      <guid>https://dev.to/sergchr/how-to-create-a-story-game-with-javascript-47hj</guid>
      <description>&lt;p&gt;If you don't know Javascript or what that is, don't worry! You'll be able to learn along the way or even go without it at all. What we are going to explore is an open-source tool to build interactive stories - &lt;a href="https://github.com/klembot/twinejs"&gt;Twine&lt;/a&gt;(or see its &lt;a href="https://twinery.org/"&gt;website&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;It allows us to make nonlinear stories. It can be presentations, fiction, or text-adventure games. In a nutshell, Twine creates an HTML file with all the content. So, it looks like a usual web page, and the tool is the constructor. You can upload such a "website" on the web or mobile platforms, i.e., anywhere that can parse HTML.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qk2Uz5Zk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/image-7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qk2Uz5Zk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/image-7.png" alt="" width="800" height="644"&gt;&lt;/a&gt;&lt;em&gt;An example of a non-linear story (interactive fiction)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're particularly interested in games / interactive fiction, see an &lt;a href="https://itch.io/games/tag-twine"&gt;extensive collection of them&lt;/a&gt;. So what sort of games are possible? All of them since we can add Javascript. However, the easiest way is to do text-adventure games. Why? You don't need to program anything or much. You add stories and connect them in a meaningful way using links. I.e., if you choose "A", the story "AA" will be shown, if you choose "B", the story "BB" will be shown.&lt;/p&gt;

&lt;p&gt;See also &lt;a href="https://twinery.org/cookbook/questions/making.html"&gt;what you can create&lt;/a&gt; with the tool from their docs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w9Rzc5tN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-12-46-13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w9Rzc5tN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-12-46-13.png" alt="" width="800" height="190"&gt;&lt;/a&gt;&lt;em&gt;An example of an actual Twine page with a story&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Creating such a page takes a few minutes on &lt;a href="https://twinery.org/"&gt;the Twine website&lt;/a&gt;(you can do that online). You can add Javascript, videos, music, images, customize styles via CSS and do the linking and playing around. It's a great way to start. Next, I will show you a different approach if you're used to coding in any developer's editor and want version control.&lt;/p&gt;

&lt;p&gt;Try online first, especially if your story/game is small and only needs a little custom functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you may need Javascript
&lt;/h2&gt;

&lt;p&gt;You can go without it and feel fine. But if you have custom stuff, you'll use some macros and scripts. What are they? Imagine Twine as a core, but it has various engines that do things differently. It supports four such engines(story formats) to make the creation process more accessible. Each of them varies in complexity. In this article, I'll be using &lt;a href="https://www.motoslave.net/sugarcube/2/"&gt;SugarCube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This story format has many built-in things you may need. For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Saving a game, resuming it from a save.&lt;/li&gt;
&lt;li&gt;Various events to react to. E.g., when a story is rendered, started rendering, etc.&lt;/li&gt;
&lt;li&gt;Macros, i.e., useful built-in blocks/functions. For example, buttons, custom links, conditional rendering, setting variables, DOM manipulations, etc.&lt;/li&gt;
&lt;li&gt;Audio handling.&lt;/li&gt;
&lt;li&gt;And many other valuable things.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's create a simple project where we want to use custom Javascript and CSS styles, but more importantly - we want to have version control! I don't use the tool's online or desktop version because I can only manage stories as files and have their versions by commit.&lt;/p&gt;

&lt;p&gt;You'll need to install &lt;a href="https://www.motoslave.net/tweego/"&gt;Tweego&lt;/a&gt;, a tool that can parse stories as files in any preferred text editor. Be aware of its limitations, though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When writing this article, the last update of Tweego was two years ago.&lt;/li&gt;
&lt;li&gt;Thus, you may not have all of the features from the supported story formats(e.g., Sugarcube).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you need to create a project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir twine-project
$ cd twine-project
$ git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can move the Tweego executable to this folder as well and add it to &lt;code&gt;.gitignore&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It's up to you how to organize files now! An example structure may look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.gitignore
README.md
bin/
src/
├─ config.tw
├─ styles/
│ ├─ menu.css
│ ├─ main.css
├─ modules/
│ ├─ menu/
│ │ ├─ menu.tw
│ │ ├─ menu.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;bin&lt;/code&gt; folder you have the Tweego executable to build the output to HTML(we'll get to that). All the story(game)-related code is under &lt;code&gt;src&lt;/code&gt; folder. Tweego will put all Twine(&lt;code&gt;.tw&lt;/code&gt;) files, CSS styles, Javascript scripts into one HTML. Therefore, it doesn't matter what project structure you have.&lt;/p&gt;

&lt;h3&gt;
  
  
  Twine format
&lt;/h3&gt;

&lt;p&gt;Now, closer to the coding: what is &lt;code&gt;config.tw&lt;/code&gt;? This is where your code will be in Twine format. Take a look at the &lt;a href="https://github.com/iftechfoundation/twine-specs/blob/master/twee-3-specification.md"&gt;specification&lt;/a&gt;. You may name this file whatever you want. It's named &lt;code&gt;config&lt;/code&gt; for readability. There, we specify the settings for our game:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:: StoryTitle
My first game

:: StoryData
{
    "ifid": &amp;lt;a serial number of your game&amp;gt;,
    "format": "SugarCube",
    "format-version": "2.30.0",
    "start": &amp;lt;a name of the story that will be shown first&amp;gt;
}

:: StoryAuthor
&amp;lt;your name if you want&amp;gt;

&amp;lt;&amp;lt;script&amp;gt;&amp;gt;
// in case you'll need to have 3rd-party scripts
// remove this &amp;lt;&amp;lt;script&amp;gt;&amp;gt; section at all for now
importScripts(
    'https://cdn.jsdelivr.net/npm/chance'
)
&amp;lt;&amp;lt;/script&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to generate a serial number for your game, i.e., IFID. Read more about how to do that &lt;a href="https://ifdb.org/help-ifid"&gt;here&lt;/a&gt;. But for now, you can use &lt;code&gt;0000A000-A0E0-00C0-00B0-CF000E000D0E&lt;/code&gt; to skip this boring step.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;format&lt;/code&gt; tells Tweego which story format to use. We'll use &lt;code&gt;SugarCube&lt;/code&gt;. &lt;code&gt;format-version&lt;/code&gt; is a version for this story format, currently supported is &lt;code&gt;2.30.0&lt;/code&gt; only. However, there are newer versions(a limitation of Tweego).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;start&lt;/code&gt; is a story that will be shown first. Let's create a file &lt;code&gt;start.tw&lt;/code&gt; with this content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:: StartOfMyGame

This is the first screen of my game, yay!

[[Start playing]]
[[Read about the author]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;::&lt;/code&gt; here indicates the ID of your passage(i.e., a page). It can be anything, e.g., &lt;code&gt;:: start-of-my-game&lt;/code&gt; or &lt;code&gt;:: something like this&lt;/code&gt;. Now that you have the ID, change your &lt;code&gt;config.tw&lt;/code&gt; to have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"start": "StartOfMyGame"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the passage(page) ID, you do whatever you want. In our case, we wrote, &lt;em&gt;"This is the first screen of my game, yay!"&lt;/em&gt;, and it'll be rendered as regular text, that's it! The &lt;code&gt;[[Start playing]]&lt;/code&gt; thing is a &lt;strong&gt;link&lt;/strong&gt; to another passage(page).&lt;/p&gt;

&lt;p&gt;To build that to HTML, run Tweego(it'll be watching for files changes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./bin/tweego -w src -o ./output/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we're telling it to watch the &lt;code&gt;src&lt;/code&gt; folder and build an output HTML into the &lt;code&gt;output&lt;/code&gt; folder as &lt;code&gt;index.html&lt;/code&gt;. Run this command, and you'll see the HTML output in that folder. Don't forget to add &lt;code&gt;output&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;. Open &lt;code&gt;output/index.html&lt;/code&gt; in a browser and you'll see something like this(with a more dark background color):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LNR6LF1C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-10-54-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LNR6LF1C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-10-54-1.png" alt="" width="346" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We create the links, but we also need to create such pages. So, we need to change the &lt;code&gt;start.tw&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:: StartOfMyGame

This is the first screen of my game, yay!

[[Start playing]]
[[Read about the author]]

:: Start playing
&amp;lt;&amp;lt;back&amp;gt;&amp;gt;
It's another page called "Start playing".

:: Read about the author
&amp;lt;&amp;lt;back&amp;gt;&amp;gt;
I'm the author. This is my page.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've added two more pages, so whenever you click on, for example, "Start playing", you'll be redirected to the "Start playing" passage:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5zvNtDY2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-14-55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5zvNtDY2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-14-55.png" alt="" width="344" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see a new link here - "Back"! &lt;code&gt;&amp;lt;&amp;lt;back&amp;gt;&amp;gt;&lt;/code&gt; is a SugarCube &lt;a href="https://www.motoslave.net/sugarcube/2/docs/#macros-macro-back"&gt;macro&lt;/a&gt; that redirects a user to the previous passage(&lt;code&gt;StartOfMyGame&lt;/code&gt;). It's a more convenient way of doing that than storing a navigation history each time.&lt;/p&gt;

&lt;p&gt;We might create these two new passages in the other files or create all the game passages in one file. It doesn't matter because Tweego puts all of the files together into a single HTML file. You don't need to care about importing something!&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Javascript to Twine stories
&lt;/h3&gt;

&lt;p&gt;Let's imagine we want to store some information about a player's choices. There are two approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We may use the &lt;a href="https://www.motoslave.net/sugarcube/2/docs/#macros-macro-set"&gt;&lt;code&gt;&amp;lt;&amp;lt;set&amp;gt;&amp;gt;&lt;/code&gt; macro&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;We may use Javascript.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When using &lt;code&gt;&amp;lt;&amp;lt;set&amp;gt;&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:: StartOfMyGame

This is the first screen of my game, yay!

&amp;lt;&amp;lt;link "Start playing" "StartPlaying"&amp;gt;&amp;gt;
    &amp;lt;&amp;lt;set $choice to "StartPlaying"&amp;gt;&amp;gt;
&amp;lt;&amp;lt;/link&amp;gt;&amp;gt;
&amp;lt;&amp;lt;link "Read about the author" "AboutTheAuthor"&amp;gt;&amp;gt;
    &amp;lt;&amp;lt;set $choice to "AboutTheAuthor"&amp;gt;&amp;gt;
&amp;lt;&amp;lt;/link&amp;gt;&amp;gt;

:: StartPlaying
&amp;lt;&amp;lt;back&amp;gt;&amp;gt;
It's another page called "Start playing".
The choice is &amp;lt;&amp;lt;= $choice&amp;gt;&amp;gt;

:: AboutTheAuthor
&amp;lt;&amp;lt;back&amp;gt;&amp;gt;
I'm the author. This is my page.
The choice is &amp;lt;&amp;lt;= $choice&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few new things here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;&amp;lt;link&amp;gt;&amp;gt;&lt;/code&gt;&lt;a href="https://www.motoslave.net/sugarcube/2/docs/#macros-macro-link"&gt;macro&lt;/a&gt; does the same as &lt;code&gt;[[]]&lt;/code&gt;, but it adds more customizability. In our case, we kept the link text, but indicated a different passage ID(&lt;code&gt;StartPlaying&lt;/code&gt;, e.g.). Also, we can do something when a link is pressed, e.g., a &lt;code&gt;&amp;lt;&amp;lt;set&amp;gt;&amp;gt;&lt;/code&gt; instruction below.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;&amp;lt;set&amp;gt;&amp;gt;&lt;/code&gt; macro stores a variable.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;&amp;lt;= $choice&amp;gt;&amp;gt;&lt;/code&gt; is a macro to evaluate expressions. In our case, it's displaying &lt;code&gt;$choice&lt;/code&gt; variable we set before.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6jEWLr0M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/Screenshot-from-2022-10-27-14-38-20.png" alt="" width="340" height="135"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can achieve the same using Javascript(however, it seems unnecessary complicated in this example):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:: StartOfMyGame

This is the first screen of my game, yay!

&amp;lt;&amp;lt;link "Start playing" "StartPlaying"&amp;gt;&amp;gt;
    &amp;lt;&amp;lt;script&amp;gt;&amp;gt;
        State.setVar('$choice', 'StartPlaying (Javascript)')
    &amp;lt;&amp;lt;/script&amp;gt;&amp;gt;
&amp;lt;&amp;lt;/link&amp;gt;&amp;gt;

:: StartPlaying
&amp;lt;&amp;lt;back&amp;gt;&amp;gt;
It's another page called "Start playing".
The choice is &amp;lt;&amp;lt;= $choice&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I removed the second passage to not duplicate the code. Here are a few new things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We still do the scripting inside &lt;code&gt;&amp;lt;&amp;lt;link&amp;gt;&amp;gt;&lt;/code&gt; macro. But we use &lt;code&gt;&amp;lt;&amp;lt;script&amp;gt;&amp;gt;&lt;/code&gt; macro now. Inside of it, we use a global object &lt;code&gt;State&lt;/code&gt;'s method &lt;code&gt;setVar&lt;/code&gt; which does the same as &lt;code&gt;&amp;lt;&amp;lt;set&amp;gt;&amp;gt;&lt;/code&gt; in the previous example.&lt;/li&gt;
&lt;li&gt;We still display the &lt;code&gt;$choice&lt;/code&gt; variable not using Javascript, but we could find that HTML block using jQuery(which is built-in in SugarCube scripts), and then set the value of it to &lt;code&gt;$choice&lt;/code&gt;, but it's unnecessary.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you use Javascript, you have access to the story format's APIs, so it's more customizability. However, you may not encounter such complexity in your game.&lt;/p&gt;

&lt;p&gt;That's it for now! There are more things to do in a game, of course. But you have the documentation and tools to discover and learn more independently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metacognitive.me/how-to-create-a-story-game-with-javascript/"&gt;Source&lt;/a&gt;&lt;/p&gt;

</description>
      <category>twine</category>
      <category>games</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Next.js vs. React: what should you use?</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Tue, 25 Oct 2022 04:27:48 +0000</pubDate>
      <link>https://dev.to/sergchr/nextjs-vs-react-what-should-you-use-3ol8</link>
      <guid>https://dev.to/sergchr/nextjs-vs-react-what-should-you-use-3ol8</guid>
      <description>&lt;p&gt;React is a tool for building a front end. Next.js serves the same purpose. However, both instruments offer a slightly different set of features. More precisely, Next.js gives you more than React. But it doesn't mean you should choose it every time.&lt;/p&gt;

&lt;p&gt;See also &lt;a href="https://metacognitive.me/why-do-i-use-next-js-in-my-projects/"&gt;why I use Next.js in my projects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mb0RzA-H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/image-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mb0RzA-H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/image-4.png" alt="" width="800" height="378"&gt;&lt;/a&gt;&lt;em&gt;A difference between Next.js and React: Next.js gives you more features&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of React.js
&lt;/h2&gt;

&lt;p&gt;If you don't know what React is, it's an instrument that simplifies the development of web pages. It allows you to build components(thus, separating your pages and UI elements into convenient parts) using an advantageous markup(JSX).&lt;/p&gt;

&lt;p&gt;Angular and Vue do the same job with some implementation differences. However, these tools bring us convenience in developing the web.&lt;/p&gt;

&lt;p&gt;With React, it's simple to start a project(use &lt;a href="https://reactjs.org/docs/create-a-new-react-app.html"&gt;create-react-app&lt;/a&gt;), and we have a bundler and a compiler. The next step is to run the app with one command. "We got it. It's simple, fine, fine!"&lt;/p&gt;

&lt;p&gt;To compare React and Next.js, let's look at what Next allows us to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js benefits
&lt;/h2&gt;

&lt;p&gt;A satisfactory &lt;strong&gt;tl;dr&lt;/strong&gt; would be: " &lt;strong&gt;Next.js is React but with more features.&lt;/strong&gt;" Next is a framework that uses React. React is a library that gives you the pros you read above, but also it gives you freedom of choice. You may use a different compiler or bundler, or you may use it in the react-native platform. Also, you choose your set of tools: a routing system, an SCSS compiler(if you need SCSS over CSS), and so on.&lt;/p&gt;

&lt;p&gt;Next.js gives you React but with an improved developer experience. You don't need to spend time making the choices. But if you want, you can, of course.&lt;/p&gt;

&lt;p&gt;Let's look at the specific benefits of Next over React.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pytwLik0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/image-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pytwLik0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/10/image-5.png" alt="" width="781" height="344"&gt;&lt;/a&gt;&lt;em&gt;Next.js saves you time, while React gives more choices, which you may not need&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Routing
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: you don't need to spend time choosing a router. There are many routers for React, and you may not know the best fit for your situation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next has the router built-in. You only need to put your pages in the &lt;code&gt;src/pages&lt;/code&gt; folder. So, the "contact.tsx"(&lt;code&gt;tsx&lt;/code&gt; is a JSX with Typescript) file will be available as a page at "yourAppAddress/contact". There is dynamic routes support too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static pages generation
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: if you need static pages for your app(e.g., a landing page that leads to the app), and you don't want to make them dynamic(because of the performance), you'll need to configure a server that will serve HTML pages in addition to your React app.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can generate static pages with Next.js because it has a built-in server.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why care: the same thing as above, except that you want to generate a page upon each request.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Static generation outputs the HTML that &lt;strong&gt;will be reused on each request&lt;/strong&gt;. The Server-side rendering method will generate HTML upon each request. The former is recommended because of better performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Fetching
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: if you want to fetch data skipping CORS or get data from the database directly from your app or read files, you'll need a server.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next.js data-fetching methods allow you to do all of that without configuring a server. For example, you can generate a static page using fetching local files at build time. Or, you can request a third-party server omitting CORS because Next has an intermediary - an API server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Image optimization
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: you don't need to think about image optimization. I.e., how to reduce an image size, what format to choose, and how to lazy-load the images.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are usually two apparent problems with images:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Image size. I.e., reducing a 3MB JPG into a 40KB Webp.&lt;/li&gt;
&lt;li&gt;Loading them after a page is rendered to reduce the network load.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next solves these problems for a developer, so they can think about the other parts of the app. All the images inside that use &lt;code&gt;next/image&lt;/code&gt; will be optimized and lazy-loaded. Also, you may set a loading priority for each of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  It uses &lt;a href="https://swc.rs/"&gt;SWC&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: you need faster build times.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next uses SWC, which is, according to their claim, " &lt;strong&gt;20x faster than Babel&lt;/strong&gt; on a single thread and &lt;strong&gt;70x faster&lt;/strong&gt; on four cores". Such speeds are a good enhancement during build times and "hot" reloading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in ESlint
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: you spend time configuring ESlint.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Imagine you wrote a few lines of code and already have the lint issues warnings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in TypeScript support
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: you want to write in Typescript, but configuring it takes some time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This feature is a huge dealbreaker for me because configuring Typescript takes time. Sometimes it's merely installing the package(&lt;code&gt;npm install typescript&lt;/code&gt;), and adding the basic &lt;code&gt;tsconfig.json&lt;/code&gt;. Still, you need to configure it correctly according to your project needs. Since you have various files in a Next.js project(stylesheets, &lt;code&gt;public&lt;/code&gt; files, JSX, js), imagine going through them to figure out what can be ignored, what rules(configuration) to add, and then to have to break changes with the framework updates.&lt;/p&gt;

&lt;p&gt;Next.js does it for us, yay!&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment Variables
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: if you want to store some private information like secrets, API keys, etc., and you don't want to expose them in an app's bundle. You may create a server to pull that data from or use some third-party provider, but it takes time and one more place for your code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The framework supports &lt;code&gt;.env&lt;/code&gt; files: create a &lt;code&gt;.env.local&lt;/code&gt;, add the secrets, and nobody will see them. You may also expose some by prefixing them with &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scripts handling and performance
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: you're thinking about lazy-loading some Javascript scripts(3rd-party ones, too), loading them first, or setting any other priority.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next.js can do all of that if you use &lt;code&gt;\&amp;lt;Script\&amp;gt;&lt;/code&gt; instead of the standard &lt;code&gt;\&amp;lt;script\&amp;gt;&lt;/code&gt;. Also, it can offload the scripts to a web worker using &lt;a href="https://partytown.builder.io/"&gt;Partytown&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  It has a server
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why care: you need a server environment. E.g., to make database queries.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We talked about it in the Data fetching section, but it's a good point to highlight one more time because you may need a server for not data fetching only. For example, maybe you need to do some filesystem-heavy logic and then fetch the results via Next.js API server.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, why React, then?
&lt;/h2&gt;

&lt;p&gt;Next.js has more features than I described here(those I like personally and wanted to highlight). So, we come to the question of why we need React when starting a new project.&lt;/p&gt;

&lt;p&gt;Sometimes, you don't need such a beast for a simple use-case. For example, if you have a single static page and you don't fetch any data. Also, you don't have much dynamic logic. Thus, there's no need to bring all of the mentioned features because you need to learn the framework(though its docs are great) and the resources to support the build overhead. I.e., why configure the Next.js CI process if you can have merely an HTML page?&lt;/p&gt;

&lt;p&gt;Choose Next.js for a better developer experience, so you don't need to spend time configuring some tools but coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metacognitive.me/next-js-vs-react/"&gt;Original article&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Why do I use Next.js in my projects</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Mon, 28 Mar 2022 07:29:23 +0000</pubDate>
      <link>https://dev.to/sergchr/why-do-i-use-nextjs-in-my-projects-of8</link>
      <guid>https://dev.to/sergchr/why-do-i-use-nextjs-in-my-projects-of8</guid>
      <description>&lt;p&gt;It simplifies development workflow, provides many built-in solutions and optimizations, simply put. Next.js is a React framework that employs the latter to make a developer's life easier when creating web apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  How did I develop web apps/websites before
&lt;/h2&gt;

&lt;p&gt;It's sort of a retrospective on how things were before fancy technologies. It's a short journey on how do we come up with React. Feel free to skip it and read more about Next.js in the next sections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pure HTML, CSS era: simple websites
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Lpxdfc6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Lpxdfc6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image.png" alt="" width="800" height="500"&gt;&lt;/a&gt;&lt;em&gt;An old and simple website written in HTML&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When I was getting started with web development, I put simple &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; blocks into Notepad, adding some CSS styles. It's straightforward. I don't need to know any frameworks, additional technologies. A few more &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; blocks, then some text and buttons, and I got a sidebar, a menu, and a content block with text.&lt;/p&gt;

&lt;p&gt;The problem with this approach begins when I want to add more pages: I should copy-paste those sidebar and menu codes into the new page. As a result, I should amend the code on every page if I want to change, say, the color of the button placed on every page in a header.&lt;/p&gt;

&lt;p&gt;Not an ideal method, but it works well for a plain one-page website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using template engines to re-use components
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lVYPH2aa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lVYPH2aa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-1.png" alt="" width="800" height="347"&gt;&lt;/a&gt;&lt;em&gt;A template engine like Pug allows creating atomic components to avoid code duplication&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There were(and still are) tools that decreased code duplication. Tools like &lt;a href="https://pugjs.org"&gt;Pug&lt;/a&gt; and &lt;a href="https://expressjs.com/en/resources/template-engines.html"&gt;others&lt;/a&gt; are Javascript scripts that compile custom HTML syntax into standard HTML. With their help, a developer can create one component(e.g. a header with links) and put it on many pages without duplicating the component code. If I need to change the component style or structure, I alter the code in one place.&lt;/p&gt;

&lt;p&gt;They also provide helpers to format HTML. For example, Javascript functions to capitalize text. Now it's easier to build a multi-page website. I create multiple fundamental components for my website and I re-use them on almost every page.&lt;/p&gt;

&lt;h3&gt;
  
  
  From websites to web apps: handling an app's state
&lt;/h3&gt;

&lt;p&gt;There was a time when businesses started to replace desktop apps with web apps. The other ones wanted to automate many things for customers. They began creating websites to receive orders, for example. When we create a many-page website with custom logic to handle users' input, sending data to a server, showing errors, etc., it becomes harder to manage the state. State? We need to store, memorize what users want, what did we show/tell them, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dHHAIEVZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dHHAIEVZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-2.png" alt="" width="800" height="441"&gt;&lt;/a&gt;&lt;em&gt;Handling a web app's state&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We may keep state on a server, but in such a way we add more complexity there. Also, it's not always convenient. For example, I want to store a lot of info about the current user and use it immediately on the next page, then forget about it. Say, it's transforming a picture into a black-and-white one via Javascript. It'd be more efficient to not load our server and make such a transformation client-side.&lt;/p&gt;

&lt;p&gt;We could store a state, or even many states, in a browser's local storage, or IndexedDB, right? Correct. However, we then need to have a logic to update our UI if the state changes. We might update everything when anything in our state changes, but then another issue appears. Our website's responsiveness isn't fine: performance is bad.&lt;/p&gt;

&lt;p&gt;React, for example, solves the components issue(templating), state management problem. With it, I may create optimized web apps, simplify interactions between many components. Why choose React or Vue? They ease the development of complicated web apps. Handling local(component-level) and global state is simpler. Re-using components is much simpler. These tools are libraries, not opinionated, hence not giving you plain constraints: what you should and shouldn't do. Instead, they tell you rules of good behavior - what code is better to avoid, for example, when writing components.&lt;/p&gt;

&lt;h2&gt;
  
  
  React: pros and cons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J4Qd4gKM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J4Qd4gKM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-3.png" alt="" width="600" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We talked about how it was difficult to not duplicate code in other web pages. React allows a developer to create small, large components and re-use them anywhere. We may include small components into bigger ones and include them in larger components. Thus, we diminish repeatable code and we have full control of a local component state. Hence, we optimize a web app(or, we make it worse).&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro: it's performant because of virtual DOM
&lt;/h2&gt;

&lt;p&gt;React creates an additional layer of API of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction"&gt;DOM&lt;/a&gt; to optimize performance. Since the library allows you to create UI consisting of many components, it tries to update an as small number of them as possible to avoid the standard load on a browser's re-rendering. By standard, I mean not updating the entire web page when we have only a minor state change. Why re-draw all elements in DOM if we can re-draw the ones that depend on the modified data, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro: a massive community
&lt;/h2&gt;

&lt;p&gt;Any great technology is backed up by a large community. If it's not large, then it's difficult to find answers on weird(or any) issues on Stackoverflow, or, to find a library to draw a simple green circle. In the Javascript world, this community is among the largest. The same applies to React, a part of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nCmZaQ5f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nCmZaQ5f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-4.png" alt="" width="712" height="492"&gt;&lt;/a&gt;&lt;em&gt;A large community provides many already built solutions for a web app&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If I need to make a well-styled table in React, I may find it in a moment on Google. If I have hard times figuring out some peculiar behavior with the library, it's easy to find an answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cons: not for me
&lt;/h2&gt;

&lt;p&gt;React works well for the problems it solves. It's easy to instantiate a new project and start coding. For me, it's not difficult to learn. And, later, it speeds up the development. Then why this article about Next.js?&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js advantages after using React
&lt;/h2&gt;

&lt;p&gt;React community created &lt;code&gt;create-react-app&lt;/code&gt; CLI tool to instantiate a new project and see the result immediately. And I liked that for my simple web apps.&lt;/p&gt;

&lt;p&gt;However, my next projects had public pages, a blog. A solution could be to set up a server and render the pages there, to return prepared HTML. Or, to bring other tools: a blog engine, a static site engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in server/static rendering
&lt;/h2&gt;

&lt;p&gt;Next.js cares about this and lets a developer continue writing code. It's why I didn't need to use other tools to build a blog or a regular page optimized for search engines and performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why care about server rendering?
&lt;/h3&gt;

&lt;p&gt;When exposing a web page to search engines, it's better to provide them HTML page without Javascript. Google, for example, &lt;a href="https://www.practicalecommerce.com/seo-how-google-reads-and-renders-javascript"&gt;can also understand Javascript&lt;/a&gt; there(hence a regular React app can be "understood"), but it sends a website to a rendering queue, which takes more time than processing pages when a Googlebot is reading a website right now.&lt;/p&gt;

&lt;p&gt;Server rendering may come with a complex setup if one tries this for the first time: I need a server, at least, to render those web pages there.&lt;/p&gt;

&lt;p&gt;The other thing intertwined with the previous one is improved performance for users(and search bots). A server renders a page and browsers show it without the necessity to compile Javascript. It comes with an additional load on the server though: it should render a page for every user(especially if the page consists of dynamic data).&lt;/p&gt;

&lt;p&gt;We could cache such pages or make them not so dynamic. Anyway, they will be fetched and shown fast for a user. Consequently, our web vitals become better.&lt;/p&gt;

&lt;p&gt;Next.js allows me to create a page that is &lt;a href="https://nextjs.org/docs/basic-features/pages"&gt;pre-rendered by default&lt;/a&gt;. Either at build time(static generation, pages are reused for every request) or at a compile-time(SSR, hence rendering on every request). Static generation is a preferred way since it generates pages at build time. Even if I have dynamic data on the pages but I can fetch it at build time, it's an ideal way to optimize performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Programmatic SEO
&lt;/h3&gt;

&lt;p&gt;Programmatic SEO is a technique to automate creating a lot of web pages that target almost similar keywords. They may have one search intent but it varies in details. Imagine you have an agency that lists realtors in different cities and countries: to help people who look for an apartment to find agents quickly. You make a website with the primary keyword "best realtors". However, this keyword is popular and a new website won't gain traction from Google. Hence, we may target long-tail keywords: we save the primary intent("best realtors") but specify a location. In this way, "best realtors in Kyiv" isn't as popular as "best realtors" and we target more specific intent on our web page.&lt;/p&gt;

&lt;p&gt;However, we'd require more time to build such pages one by one, right? Most of the code could be copy-pasted, only the list with realtors differs. If we target "best realtors" in 10,000 various cities, it's a lot of work. What if we want then to target for "best agents in Kyiv"-like keywords? We alter a word, and we require additional 10,000 web pages.&lt;/p&gt;

&lt;p&gt;Here's the thing: we have the realtors lists in various cities already, we have a web page template. With Next.js, building a lot of pages for programmatic SEO is simple. Have a list of keywords, have one code(template) and the framework will build a page for every keyword you specified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in routing
&lt;/h2&gt;

&lt;p&gt;Remember how do you choose a router for a new React project? They're almost the same, have some differences, and some libraries are stable. With a Next.js project, I don't need to think about what router to use this time(maybe some other library?). It has a built-in router. And it's a simple one: you put a file in the &lt;code&gt;pages&lt;/code&gt; folder and it becomes a page.&lt;/p&gt;

&lt;p&gt;For example, I want to make a page with the URL &lt;code&gt;&amp;lt;myapp&amp;gt;/sign-in&lt;/code&gt;. I put &lt;code&gt;sign-in.tsx&lt;/code&gt; component or &lt;code&gt;sign-in&lt;/code&gt; folder with &lt;code&gt;index.tsx&lt;/code&gt; component there and it works.&lt;/p&gt;

&lt;p&gt;The router provides all the necessary features: dynamic routes, nested routes, linking pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in API server
&lt;/h2&gt;

&lt;p&gt;There's &lt;code&gt;pages/api&lt;/code&gt; folder where I may specify API endpoints. Some good use cases are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;API middlewares. When I want to alter a request(e.g. its headers) to make another one to a different server, for example.&lt;/li&gt;
&lt;li&gt;Request resources on other domains. To avoid the CORS issue(&lt;a href="https://github.com/vercel/next.js/tree/canary/examples/api-routes-cors"&gt;an example project&lt;/a&gt;). Oftentimes, I need to request some 3rd-party resource, but I can't due to CORS. One solution is to make a server, make the request there, and then redirect it to the 3rd-party. Let's save time though. For simple requests(and even a bit complicated, Next.js can handle it too), it'd better use &lt;code&gt;pages/api&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Build-in images and fonts optimization
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---k4t3rI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---k4t3rI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://metacognitive.me/content/images/2022/03/image-5.png" alt="" width="760" height="382"&gt;&lt;/a&gt;&lt;em&gt;Next.js built-in image optimization&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I don't want to optimize such assets on every page I code. At the beginning of some project, it's usually not a top priority. But it's great when the framework does the 80%-like(there are other complicated optimization tricks we usually don't need) job at optimizing assets. You paste an image and it's automatically smaller, without layout shifts, and it lazy-loads!&lt;/p&gt;

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

&lt;p&gt;There are 2 environments that are available when you code a Next.js app: a browser, a server. Environment variables in a browser are visible if one wants to find them in the bundled code. The server variables are hidden since users don't have access to remote hosts and their code.&lt;/p&gt;

&lt;p&gt;With Next.js, I can create both env. variables without setting up webpack and installing another library to handle env. vars for a server. The framework has built-in support for them!&lt;/p&gt;

&lt;p&gt;There's a &lt;code&gt;.env&lt;/code&gt; file where I specify server vars, and in the same file I may specify browser vars by adding a prefix to a var - &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt;. Incredibly convenient to me.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Next.js saves me time a lot with current and new projects. I can combine a few apps seamlessly and have one codebase only. The advantages I wrote about may not apply to your use case though. If you use React now, it's worth trying: the framework adds up useful features on top of the React pros.&lt;/p&gt;

&lt;p&gt;If you have questions or feedback, let &lt;a href="https://twitter.com/sergchr"&gt;me&lt;/a&gt; know.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Implementing push notifications with Firebase for Javascript apps</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Fri, 21 Jan 2022 18:39:22 +0000</pubDate>
      <link>https://dev.to/sergchr/implementing-push-notifications-with-firebase-for-javascript-apps-4n3o</link>
      <guid>https://dev.to/sergchr/implementing-push-notifications-with-firebase-for-javascript-apps-4n3o</guid>
      <description>&lt;p&gt;These notifications we're used to on smartphones are available in browser environments too. If you know why are you here exactly, skip this part and jump directly to the solution.&lt;/p&gt;

&lt;p&gt;And these notifications on the web that we hate because every spam site asks our permissions about sending us their spam. However, the technology itself is useful. I didn't implement web push notifications before. There was no such case, but recently I needed to notify my users about important information as soon as possible. Email is good, but a user should open an email client first. With notifications, you see the popup immediately.&lt;/p&gt;

&lt;p&gt;I decided to write this article because I didn't find comprehensive information about implementing browser notifications for React, Next.JS, Node apps. We'll be using Firebase for this purpose, to save time ourselves by not building solutions from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of browser push notifications
&lt;/h2&gt;

&lt;p&gt;So as we said, it's like those mobile notifications but used in browsers mostly for spamming. It's worth noting, that you need to send them to a user if that's really what he subscribed to. Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new comments under the user's post;&lt;/li&gt;
&lt;li&gt;new message on some platform;&lt;/li&gt;
&lt;li&gt;important information that should be handled fast;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The other non-important things may go to email.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it work
&lt;/h3&gt;

&lt;p&gt;First, you ask a user permission to show the notifications. If you get an acceptance, your website installs a &lt;a href="https://developers.google.com/web/fundamentals/primers/service-workers" rel="noopener noreferrer"&gt;service worker&lt;/a&gt; that'll be handling the notifications. You also send the request to register this particular user in a messaging server, you'll be asking it to send a notification to someone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmetacognitive.me%2Fcontent%2Fimages%2F2022%2F01%2Fimage-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmetacognitive.me%2Fcontent%2Fimages%2F2022%2F01%2Fimage-1.png" alt="Push notifications overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a messaging server registers your users, it'll send you a unique for your user token that you'll be using as an addressee to send push notifications programmatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmetacognitive.me%2Fcontent%2Fimages%2F2022%2F01%2Fimage-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmetacognitive.me%2Fcontent%2Fimages%2F2022%2F01%2Fimage-2.png" alt="Firebase push notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You save the registration token from a messaging server. When you want to send a notification, you'll point out this token for the user you want to send a message to, thus the messaging server understands to whom to send the notification. When a user agrees to receive notifications, your website installs a service worker, it's a background script that'll be running on the user's browser. It's programmed to handle the messages from the messaging server. When it receives one, it'll assemble a notification to show to this user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Messaging server?&lt;/strong&gt; This is any server that knows how to communicate with your service worker. You can build it by yourself and code a service worker that will be managing messages from there. But we won't complicate our life and we'll be using Firebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firebase push notifications
&lt;/h2&gt;

&lt;p&gt;If we use Firebase, we don't care about the proper messaging server setup because we got covered. What we need is to code logic to ask for the notifications permissions, install a service worker and write a logic to send notifications from our app.&lt;/p&gt;

&lt;p&gt;For further setup, you should create a project in the &lt;a href="https://console.firebase.google.com" rel="noopener noreferrer"&gt;Firebase Console&lt;/a&gt;, and have config from there(a JSON file).&lt;/p&gt;

&lt;h3&gt;
  
  
  Front-end set up
&lt;/h3&gt;

&lt;p&gt;I have a Next.js app, but this algorithm covers any app written in Javascript, it's a library- and framework-independent.&lt;/p&gt;

&lt;p&gt;Install Firebase to your project so we can leverage simple functions rather than doing requests to FCM(Firebase Cloud Messaging) manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;firebase
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add firebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find a place where do you want to ask a user about the notification permission. For example, it can be a button that says "Subscribe to browser notifications". On this button click, you'll be calling a function &lt;code&gt;getFCMToken()&lt;/code&gt; written below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initializeApp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getMessaging&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getToken&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase/messaging&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Replace these values with your project's ones&lt;/span&gt;
&lt;span class="c1"&gt;// (you can find such code in the Console)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxxxx-xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxxx.firebaseapp.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxxx-xxxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;storageBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxxx.appspot.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messagingSenderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;00000000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0:00000:00000000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebaseConfig&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;messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getMessaging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getFCMToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Don't forget to paste your VAPID key here&lt;/span&gt;
        &lt;span class="c1"&gt;// (you can find it in the Console too)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&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;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;vapidKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;YOUR_VAPID_KEY&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;token&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;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getFCMToken error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;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;With this code, we initialize the Firebase library and write this &lt;code&gt;getFCMToken()&lt;/code&gt; function. It retrieves a registration token from FCM, and &lt;strong&gt;it also asks a user for notification permission&lt;/strong&gt;. If the permissions are accepted, only then it'll communicate with FCM to register this user. Otherwise, the code throws an error, which you catch in the &lt;code&gt;catch&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;Then, you get an FCM token(a user's unique token in the FCM system), which you'll be using to send notifications. So you need to &lt;strong&gt;store it&lt;/strong&gt; somewhere. Usually, you have a server where you may send the token and it'll save it in the database for this particular user. Otherwise, you won't be able to send notifications to users. It's required to have the Firebase Admin SDK, which is available on server environments.&lt;/p&gt;

&lt;p&gt;There are some exceptions though. In some cases when you want only to subscribe users to your notifications like in a newsletter, you may not store the FCM tokens. Firebase has them and you can send the notifications &lt;strong&gt;manually&lt;/strong&gt; from the Console. But it's not possible to send them automatically(programmatically) because you can't differentiate users(you don't have the tokens).&lt;/p&gt;

&lt;p&gt;And the last thing is to have a service worker that will handle the notifications from FCM. Create a file that'll be available on the root of your web app, the file named &lt;code&gt;firebase-messaging-sw.js&lt;/code&gt;. It should be accessible on &lt;code&gt;https://yourwebsite.com/firebase-messaging-sw.js&lt;/code&gt;. Its contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// It's a static script file, so it won't be covered by a module bundling system&lt;/span&gt;
&lt;span class="c1"&gt;// hence, it uses "importScripts" function to load the other libs&lt;/span&gt;
&lt;span class="nf"&gt;importScripts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;importScripts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Replace the values with yours&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;storageBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messagingSenderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebaseConfig&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;messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Not necessary, but if you want to handle clicks on notifications&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notificationclick&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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;pathname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;FCM_MSG&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;link&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;pathname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;

    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchAll&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;window&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;includeUncontrolled&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;clientsArr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hadWindowToFocus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clientsArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;windowClient&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;windowClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;windowClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&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="kc"&gt;false&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;hadWindowToFocus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;windowClient&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;windowClient&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;windowClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
                        &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="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;That's all on the front-end side! You can test your button, on the press, it should ask your permission(a browser asks, to be precise) to send you notifications. When you allow it, you should see an FCM token(console.log it somewhere)&lt;/p&gt;

&lt;h3&gt;
  
  
  Sending notifications from the server
&lt;/h3&gt;

&lt;p&gt;In my case, it's a Node.js server and we'll be installing the SDK for it, but the general principle is the same for other languages/platforms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;firebase-admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also have a configuration for the backend in the Console. It differs from the client-side one because it has a private key that you need to sign your notification, which will be sent to FCM. Put this &lt;code&gt;firebase.json&lt;/code&gt; file(it's called service account) somewhere to be accessible from code, you may put it as an environment variable.&lt;/p&gt;

&lt;p&gt;Then you should initialize the Firebase library on a server start(or later if you want to control the flow). I've put this logic into a separate file:&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;import&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;serviceAccount&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config/firebase.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serviceAccount&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;On a server start, call &lt;code&gt;init()&lt;/code&gt; and Firebase is ready to serve you.&lt;/p&gt;

&lt;p&gt;I won't cover storing the FCM tokens, I'm sure you know how to do it and it's not the purpose of this article. So, given you have an initialized Firebase on the server(from the last paragraph) and you have a user's FCM token, you're ready to send push notifications to a user's browser! It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getMessaging&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin/messaging&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// I use Typescript, you may not, but types will help you&lt;/span&gt;
&lt;span class="c1"&gt;// to understand what data structures FCM expects.&lt;/span&gt;
&lt;span class="c1"&gt;// It's an internal structure though, firebase-admin has&lt;/span&gt;
&lt;span class="c1"&gt;// good typings in the library&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Message&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;body&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;requireInteraction&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="nl"&gt;link&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="c1"&gt;// Use this function to send push notifications to a specific user&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendFCMMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fcmToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&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;getMessaging&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;webpush&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://your-website.com/favicon.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;requireInteraction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requireInteraction&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="na"&gt;actions&lt;/span&gt;&lt;span class="p"&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="s1"&gt;Open&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;}],&lt;/span&gt;
                    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fcmToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&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;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sendFCMMessage error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&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;Now, some details on the notification payload. Firebase supports various platforms, here I use the &lt;code&gt;webpush&lt;/code&gt; field for my payload. FCM supports other fields:&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;BaseMessage&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="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nl"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;android&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;AndroidConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;webpush&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;WebpushConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;apns&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ApnsConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;fcmOptions&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;FcmOptions&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;I've tried to use &lt;code&gt;notification&lt;/code&gt; as a general-purpose one, but I had issues with clicking on notifications, a browser didn't handle clicks(the service worker had the click handler). Plus, there were problems with showing icons on notifications. It's better to use &lt;code&gt;webpush&lt;/code&gt; if you target desktop users. An FCM token can be for various platforms: Android, iOS, web.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;webpush&lt;/code&gt;, there are &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt; that correspond to a notification's title and body. There's &lt;code&gt;icon&lt;/code&gt; if you want your notification to have an icon. Put a publicly accessible image you want to be shown. Set &lt;code&gt;requireInteraction&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; if you don't want the notification to be closed after a few seconds, it should wait for the user's explicit reaction.&lt;br&gt;&lt;br&gt;
There's a custom &lt;code&gt;link&lt;/code&gt; field inside &lt;code&gt;data&lt;/code&gt;, it's aimed for the service worker to be read and handle the click on notifications correctly.&lt;/p&gt;

&lt;p&gt;I don't know about all browsers, but my browser(Brave) doesn't handle the default notification click on the whole area, there should be custom buttons. I define them in the &lt;code&gt;actions&lt;/code&gt; field. It seems it doesn't matter what buttons with actions I put, the "Open" button(action) will open the URL from &lt;code&gt;data.link&lt;/code&gt; property I send.&lt;/p&gt;

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

&lt;p&gt;Web push notifications aren't difficult to implement if you can use Firebase. Also, it's easy to send messages to various devices on different platforms. Only obtain an FCM token client-side(on a mobile, web, or desktop), and send notifications from a server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metacognitive.me/implementing-push-notifications-with-firebase/" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>firebase</category>
      <category>notifications</category>
      <category>node</category>
    </item>
    <item>
      <title>How to do text classification with Javascript</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Sun, 21 Nov 2021 11:23:13 +0000</pubDate>
      <link>https://dev.to/sergchr/how-to-do-text-classification-with-javascript-klp</link>
      <guid>https://dev.to/sergchr/how-to-do-text-classification-with-javascript-klp</guid>
      <description>&lt;p&gt;A few months ago I tried to find information about doing some natural language processing with Javascript. There was not much of it. Most of the time, I stumbled upon tutorials on how to do so in Python. I'm writing this article in the hope to help someone do the same with Javascript. At least, try to. Javascript ecosystem is large, yet machine learning is mostly done in Python. For some custom(complicated) cases, you maybe will decide not to use Javascript. I'll explain why you may do so.&lt;/p&gt;

&lt;p&gt;I want to point out that I'm not a machine learning engineer. I'll cover simple cases with no deep explanations of the underlying algorithms.&lt;/p&gt;

&lt;p&gt;There are manageable cases when you may try JS packages that do the classification. In some others, and if you understand ML concepts, you may create custom models using TensorFlow.js.&lt;/p&gt;

&lt;p&gt;My case seemed simple. I wanted to classify potential business problems(opportunities) for my &lt;a href="https://olwi.xyz"&gt;Reddit advanced search tool&lt;/a&gt;. I'll tell you soon how it went, once we cover the tools. Let's start with simple cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://naturalnode.github.io/"&gt;Natural.js&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;It's a package for Node.js that helps deal with natural language. It has many useful built-in helpers. For example, it can do a sentiment analysis from the box and without any setup. Let's install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; natural
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Easy sentiment analysis, right?&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SentimentAnalyzer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PorterStemmer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;natural&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analyzer&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;SentimentAnalyzer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;English&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PorterStemmer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;afinn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSentiment&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I&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;love&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;cakes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0.66&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, it's easy. &lt;code&gt;PorterStemmer&lt;/code&gt; is a transformation function that converts words to theirs &lt;a href="https://searchenterpriseai.techtarget.com/definition/stemming#:~:text=Stemming%20is%20the%20process%20of,natural%20language%20processing%20(NLP).&amp;amp;text=When%20a%20new%20word%20is,can%20present%20new%20research%20opportunities."&gt;stems&lt;/a&gt;. To their original form, simply put. We pass an array of words to &lt;code&gt;getSentiment&lt;/code&gt; function, but we may use built-in &lt;a href="https://naturalnode.github.io/natural/Tokenizers.html"&gt;tokenizers&lt;/a&gt; to do so automatically.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where is a promised text classification, Lebowski?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wanted to show the simplicity of usage, without even training some complex algorithms. Now let's see how it deals with text classification.&lt;/p&gt;

&lt;p&gt;The package supports the &lt;a href="http://en.wikipedia.org/wiki/Naive_Bayes_classifier"&gt;Naive Bayes classifier&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Logistic_regression"&gt;logistic regression&lt;/a&gt;. They work differently, so try each one and see what fits your case better.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BayesClassifier&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;natural&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;classifier&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;BayesClassifier&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;buy our limited offer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spam&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;grow your audience with us&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spam&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;our company provides a great deal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spam&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I like to read books and watch movies&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;regular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My friend likes to walk near the mall&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;regular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pizza was awesome yesterday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;regular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;we would like to propose our offer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// spam&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;m feeling tired and want to watch something&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// regular&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually, you need a lot of examples. With a small amount of them, any method you choose(this library or a custom model) will output not the best results. Pay vast attention to your data, it's a major element in text classification. Maybe Natural.js will cover your case and you can finish the reading. If you need a more custom setup(if you think so, review your data again), read further.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/BrainJS/brain.js#brainjs"&gt;Brain.js&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This library helps you to build neural networks. Natural works with more simple algorithms. Neural networks are many algorithms that work as one, simply saying. They reflect the behavior of biological neurons that are great at &lt;strong&gt;recognizing patterns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now you can customize the algorithms. Specifically, you can build your own neural networks architectures - specify how many layers you need, activation functions, learning rate, and other parameters. This is where it gets trickier. There are no "gold rules" at building neural net architectures. The process greatly varies from a use case. We may use the default options in the cases like defining a color from RGB params:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;brain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;brain.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Build a default neural net&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;brain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NeuralNetwork&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// This is where we specify our data: input and the result(output)&lt;/span&gt;
&lt;span class="c1"&gt;// the data is an array of examples(input and output).&lt;/span&gt;
&lt;span class="c1"&gt;// And then the network trains on them.&lt;/span&gt;
&lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="c1"&gt;// we tell it: if "r" from RGB scheme is 0.03, and "g" is 0.7&lt;/span&gt;
  &lt;span class="c1"&gt;// then the output should be "black"&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.03&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;black&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// notice that we skip some values from RGB, in this case we&lt;/span&gt;
  &lt;span class="c1"&gt;// missed "g"&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// here we point out all the RGB values&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// This is how we run the network to get a prediction&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// { white: 0.81, black: 0.18 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a powerful way to build such a network without understanding the underlying concepts, data normalization. Just point out a few examples and you're done. However, in reality, you need more examples for better precision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transforming text to numeric vectors
&lt;/h3&gt;

&lt;p&gt;Now we're talking about data normalization. For text classification, we need to transform the text into numeric values because Brain.js doesn't have &lt;em&gt;custom&lt;/em&gt; data transformation flow for regular neural nets, yet you may try it for &lt;a href="https://github.com/BrainJS/brain.js/blob/master/examples/javascript/childrens-book.js"&gt;LSTM, for example&lt;/a&gt;. Why convert strings to numbers? Neural networks training is a process of many math calculations, which require numbers, not other data types. You might use raw strings, they would be converted to their numeric representations, however, not to the format you(and the algorithms) probably want. What these "algorithms" do is figure out the patterns of the input to build a function that can calculate the output based on the input. So it's important how you do this transformation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first option&lt;/strong&gt; , you may propose, is to convert every character to their numeric order in the alphabet. For instance, "a" is 0, "b" is 1, "c" is 2 and so on. Thus, we will have 26 possible values for every character. It means, the word "car" can be represented as &lt;code&gt;[2, 0, 17]&lt;/code&gt;. In this case, if your task is to classify text with many sentences, your input dimensionality becomes 2D, which isn't fine, because input should be 1D. We might flatten the 2D array, but then it gets delicate. It means, the text like this "I want apples" converts to "iwantapples"(and then to a numeric 1D vector). It may be fine, yet we're not sure the network recognizes a pattern there to classify correctly.&lt;/p&gt;

&lt;p&gt;The big problem with such an approach is that every character is seen by a net &lt;strong&gt;independently&lt;/strong&gt; , not as a word. Thus, "car" is &lt;code&gt;[2, 0, 17]&lt;/code&gt;, and the resulting function(a set of functions that process the input) may "think" it's almost the same as "bar" - &lt;code&gt;[1, 0, 17]&lt;/code&gt;. It doesn't think, of course, but the pattern says so. Thus, it's difficult to retrieve any context, we just perceive every character independently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second option&lt;/strong&gt; is to do the same, but for words. In reality, we retrieve context mainly from words, not by characters separately. Such an approach also simplifies the calculations: we don't need to convert 2D input into 1D and a neural network gets fewer numbers to process, which is a performance boost. To convert words to a number, we should figure out what numbers to assign to them. You may create examples of text you will be training on, tokenize it into words(omitting punctuation because it doesn't add context), make a dictionary of these words, where every one of them gets an ordering number. It's like adding words to a &lt;code&gt;Set&lt;/code&gt; and their number is an order in which they appear in it. E.g. if I have a text "I want apples.", my dictionary is &lt;code&gt;["i", "want", "apples"]&lt;/code&gt;, where the word "I" will be assigned to 0, "want" to 1, and "apples" to 2.&lt;/p&gt;

&lt;p&gt;We may optimize this approach by also &lt;a href="https://en.wikipedia.org/wiki/Stemming"&gt;stemming&lt;/a&gt; words to their root form, e.g. "apples" become "apple" because the net doesn't need to know(except the use cases where your task is to classify singular or plural forms) whether it's a singular or a plural form, it's better to have a numeric representation for a word abstraction - apples("apple", "apples").&lt;/p&gt;

&lt;p&gt;It's the most simple method to vectorize text. Though, it also has problems. In cases, where you need your neural net to "figure out" the context by looking for a set of words, it's difficult because in the example above, "I" and "want" are placed as neighbors (0 and 1 accordingly), but they aren't similar, they mean different things. For example, "car" and "automobile" mean the same but can be represented as 14 and 8233 with this approach. Thus, your model may derive different results based on whether your examples have synonyms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The third option&lt;/strong&gt; is to use pre-generated vectors. The ones that were generated by processing a lot of texts and deriving which words are similar, and which ones are different. Thus, for example, a vector for "car" may be &lt;code&gt;[0.45, 0.78, 0.97, 0.34, 0.87]&lt;/code&gt;, and for "automobile" it may be &lt;code&gt;[0.49, 0.73, 0.98, 0.33, 0.88]&lt;/code&gt;. As you noticed, they're not single numbers, but vectors for every word. Thus, you get a 2D array for the whole text. I'd suggest you go with pre-generated vectors such as &lt;a href="https://nlp.stanford.edu/projects/glove/"&gt;GloVe&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting back to Brain.js
&lt;/h3&gt;

&lt;p&gt;Now you know how to convert strings to vectors, you can use the library to help you. It has various types of &lt;a href="https://github.com/BrainJS/brain.js#neural-network-types"&gt;pre-defined neural networks&lt;/a&gt;. The one we saw before is the &lt;a href="https://en.wikipedia.org/wiki/Feedforward_neural_network"&gt;feedforward neural net&lt;/a&gt; with backpropagation. This is where things get delicate too, again - in choosing the right network type. A feedforward net is a simple one that takes an input, does some calculations-transformations, and returns the results. It sees every input independently, it doesn't have a memory. It means it can't derive context from multiple words. If your task requires so, you better choose recurring neural nets such as &lt;a href="https://en.wikipedia.org/wiki/Recurrent_neural_network"&gt;RNN&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Long_short-term_memory"&gt;LSTM&lt;/a&gt;(&lt;a href="https://github.com/BrainJS/brain.js#neural-network-types"&gt;see the Brain.js details on them&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  TensorFlow.js
&lt;/h2&gt;

&lt;p&gt;This is a path where you decided you require more custom setup. This is a Javascript version of a powerful machine learning framework for Python. It allows you to build any models or use already created ones by the community. However, they don't have much. And their functionality of converting Python models to JS ones and vice versa doesn't work well enough yet.&lt;/p&gt;

&lt;p&gt;The code may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tensorflow/tfjs-node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// assume we already have vector representations of the text examples&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vectorRepresentations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// imagine we have such 3 classes&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// tensors are TensorFlow vectors to simplify the internal&lt;/span&gt;
&lt;span class="c1"&gt;// processing for the library&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputTensors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputs&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;outputTensors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outputs&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;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sequential&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 1st layer: a 1d convolutional network&lt;/span&gt;
&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conv1d&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;kernelSize&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="na"&gt;strides&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;activation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;relu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;valid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputShape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;MAX_WORDS_LENGTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GLOVE_VECTOR_DIMENSIONS&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="c1"&gt;// transform 2d input into 1d&lt;/span&gt;
&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;globalMaxPool1d&lt;/span&gt;&lt;span class="p"&gt;({}));&lt;/span&gt;

&lt;span class="c1"&gt;// the final layer with one neuron&lt;/span&gt;
&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dense&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;activation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sigmoid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="c1"&gt;// here are some tuning, read in the TF docs for more&lt;/span&gt;
&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;optimizer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;adam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LEARNING_RATE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;binaryCrossentropy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accuracy&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;// print the model architecture&lt;/span&gt;
&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// train the model&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// the default size, how many inputs to process per time&lt;/span&gt;
    &lt;span class="na"&gt;batchSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// how many times to "process", simply put&lt;/span&gt;
    &lt;span class="na"&gt;epochs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EPOCHS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// the fraction of the inputs to be in the validation set:&lt;/span&gt;
    &lt;span class="c1"&gt;// the set, which isn't trained on, but participates in calculating&lt;/span&gt;
    &lt;span class="c1"&gt;// the model's metrics such as accuracy and loss&lt;/span&gt;
    &lt;span class="na"&gt;validationSplit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// shuffle inputs randomly to have a different starting seed every time&lt;/span&gt;
    &lt;span class="na"&gt;shuffle&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;// save the model to load in the future and run classifications&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file://./data/models/myFirstModel&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;Here we built a model to do text classification for 3 pseudo-classes(0, 1, 2). We used a 1d convolutional network for the 1st layer. TensorFlow allows you to specify any amount of layers you want, set training epochs, validation split, choose different ML algorithms, activation functions for every layer, and many other options. Though, we need to know how to build ML models. If we don't, we may add anything, tune parameters, and won't receive good results.&lt;/p&gt;

&lt;p&gt;I went to TensorFlow.js for more customizability but spent months on adjusting a lot of stuff and didn't get great results. I learned many things along the way, but still, I'm not an ML engineer, so it's better(faster) to use models built by professionals and not create your own wheel. But if it's for fun, why not! Then, let's understand the code I wrote.&lt;/p&gt;

&lt;p&gt;I chose this architecture due to its performance: convolutional networks are faster for text processing and also they process input in a kind of context. They're mainly used in computer vision because they process input matrices, not just 1d arrays of numbers. So, for example, if you get an image, 100x100 px, a convolutional network may process 5x5 pixel window per time. Thus, some noise and details can be classified correctly. For text, it's almost the same - we need to take multiple words in a batch and don't process them independently. Thus, simplifying a model's job in recognizing patterns.&lt;/p&gt;

&lt;p&gt;I chose GloVe vector representations, so my input data was a 2D array of numbers, where every subarray was a word representation. The &lt;code&gt;kernelSize&lt;/code&gt; parameter in a convolutional network is responsible for the "sliding window" - those 5x5 pixels to process per time. In my case, I specified &lt;code&gt;kernelSize&lt;/code&gt; to &lt;code&gt;3&lt;/code&gt;. It means the network processes 3 vectors(3 words) per time. The &lt;code&gt;filters&lt;/code&gt; param tells how many neurons you want. &lt;code&gt;strides&lt;/code&gt; means how many "steps" to take per once when moving the "sliding window". For example, for the text "I want to eat apples tomorrow", the first batch is &lt;code&gt;["i", "want", "to"]&lt;/code&gt;, the second batch is &lt;code&gt;["want", "to", "eat"]&lt;/code&gt;, the 3rd is &lt;code&gt;["to", "eat", "apples"]&lt;/code&gt; , and so on. So, it moves by one word per time to the right.&lt;/p&gt;

&lt;h2&gt;
  
  
  General learnings
&lt;/h2&gt;

&lt;p&gt;I spent some time with Natural.js, then Brain.js, and TensorFlow. I went to the last one for custom configuration and spent a lot of time building custom models. It'd be better to use an already built model for text classification. However, I didn't find a good way to transform Python TensorFlow models into Javascript ones, that's why in the end I switched to a Python setup with HuggingFace. But my task wasn't so straightforward. I wanted to classify potential people's problems and pains: where someone hates using something or complaining about things.&lt;/p&gt;

&lt;p&gt;There were some things I learned while building custom models with tensorFlow.js I wish I knew earlier. Write your experiments in a logbook. You'll be building various models with various hyperparameters and it becomes difficult to recall what worked well for you and what didn't. Also, don't forget about the test set(assuming you have a validation one too).&lt;/p&gt;

&lt;p&gt;There is a lot of things to mention about building ML models. Here are some I highlighted in my logbook. I hope it saves someone's time in narrowing the search when troubleshooting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to stop training&lt;/strong&gt;. If a validation loss starts increasing. It should be similar to but slightly higher than a training loss. If it's lower or almost equal to a training loss, a model requires more training. If training loss is reducing without an increase in validation loss then again keep doing more training.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You have 1.0 accuracy&lt;/strong&gt;. In most cases, if you have 100% train accuracy, you've probably greatly overfitted. Or, a model recognized a "false" pattern in your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Overfitting"&gt;Overfitting&lt;/a&gt;&lt;/strong&gt;? A big topic. Here's some reference(not mine, but I can't find the source):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If validation loss &amp;gt;&amp;gt; training loss you can call it overfitting.
If validation loss &amp;gt; training loss you can call it some overfitting.
If validation loss &amp;lt; training loss you can call it some underfitting.
If validation loss &amp;lt;&amp;lt; training loss you can call it underfitting.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A higher than training loss validation loss means overfitting, a model learned the patterns that happen to be true in training data, but they're not in real-world data.&lt;/p&gt;

&lt;p&gt;If you have a too powerful model(the one that has too many parameters and not much training data, see &lt;code&gt;model.summary()&lt;/code&gt;), review it again and simplify, because for me some of the models memorized the data, and thus, have greatly overfitted.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Another evidence of overfitting is that your loss is increasing, Loss is measured more precisely, it's more sensitive to the noisy prediction if it's not squashed by sigmoids/thresholds (which seems to be your case for the Loss itself). Intuitively, you can imagine a situation when the network is too sure about output (when it's wrong), so it gives a value far away from the threshold in case of random misclassification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Accuracy or loss fluctuates&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;some portion of examples is classified &lt;strong&gt;randomly&lt;/strong&gt; , which produces fluctuations, as the number of correct random guesses always fluctuates (imagine accuracy when coin should always return "heads"). Basically, sensitivity to noise (when classification produces random results) is a common definition of &lt;strong&gt;overfitting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The training loss at each epoch is &lt;em&gt;usually&lt;/em&gt; computed on &lt;strong&gt;the entire training set&lt;/strong&gt;.  The validation loss at each epoch is &lt;em&gt;usually&lt;/em&gt; computed on &lt;strong&gt;one minibatch of the validation set&lt;/strong&gt; , so it is normal for it to be noisier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Take care of your batch size. Sometimes it needs to be adjusted:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Smaller batch sizes give noisy gradients but they converge faster because per epoch you have more updates. If your batch size is 1 you will have N updates per epoch. If it is N, you will only have 1 update per epoch. On the other hand, larger batch sizes give a more informative gradient but they convergence slower and increase computational complexity.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>tensorflow</category>
      <category>brain</category>
      <category>natural</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Typescript tutorial for Javascript developers</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Fri, 05 Nov 2021 06:55:11 +0000</pubDate>
      <link>https://dev.to/sergchr/typescript-tutorial-for-javascript-developers-man</link>
      <guid>https://dev.to/sergchr/typescript-tutorial-for-javascript-developers-man</guid>
      <description>&lt;p&gt;I wrote an &lt;a href="https://metacognitive.me/reasons-to-use-typescript/"&gt;article&lt;/a&gt; on why to use Typescript if you're still in doubt about whether to use it in your projects. In short, Typescript allows you to write maintainable code. Javascript works well for prototyping but becomes frustrating when you return to a project again. Suddenly, you see blocks of code where you can't understand what kind of data passes there.&lt;/p&gt;

&lt;p&gt;In this article, I want to introduce you to Typescript while playing with code. Thus, you see it in action and don't overflow with an unnecessary theory. I recommend playing with the code you'll meet here in &lt;a href="https://www.typescriptlang.org/play"&gt;Typescript Playground&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Imagine you want to count items, which have the field &lt;code&gt;meta&lt;/code&gt; that contains the field &lt;code&gt;countable&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt;, in an array. If an item doesn't have &lt;code&gt;meta.countable&lt;/code&gt;, we don't count it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAmount&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arr&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;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;countable&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;length&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;em&gt;Typescript array type with anything in there&lt;/em&gt;&lt;br&gt;
 Why are you using &lt;code&gt;any&lt;/code&gt;? It's not OK! It's for an example. Don't use &lt;code&gt;any&lt;/code&gt; in such cases. Read more about it later in the article.&lt;/p&gt;

&lt;p&gt;We see the &lt;code&gt;any&lt;/code&gt; keyword near the &lt;code&gt;arr&lt;/code&gt; argument, that's new to us! I guess you already know what it is. This way we tell TS that &lt;code&gt;arr&lt;/code&gt; is of &lt;code&gt;any[]&lt;/code&gt; type. It literally means any Javascript type in an array. I.e. &lt;code&gt;arr&lt;/code&gt; is an array and every item of it is of type &lt;code&gt;any&lt;/code&gt;. It safe you from writing such 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="c1"&gt;// Argument of type 'string' is not assignable to parameter of type 'any[]'&lt;/span&gt;
&lt;span class="nf"&gt;getAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Argument of type 'number' is not assignable to parameter of type 'any[]'&lt;/span&gt;
&lt;span class="nf"&gt;getAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler ensures you should pass exactly what you've pointed out as an &lt;code&gt;arr&lt;/code&gt; argument for the &lt;code&gt;getAmount&lt;/code&gt; function. What if you need to pass several types, for example, an array and a string? And if &lt;code&gt;arr&lt;/code&gt; is a string, then return 0. A weird case, but imagine you work on a legacy system that uses this function in many places, so somewhen you may get a string.&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;getAmount&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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;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;arr&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arr&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;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;countable&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;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;55&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// now it's possible to pass a string&lt;/span&gt;
&lt;span class="nf"&gt;getAmount&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;countable&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;|&lt;/code&gt; means "or". Thus, &lt;code&gt;arr&lt;/code&gt; can be an array of anything(&lt;code&gt;any[]&lt;/code&gt;) or a string. Refer to &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html"&gt;this page&lt;/a&gt; for more everyday types in Typescript.&lt;/p&gt;

&lt;p&gt;The compiler is smart enough to even infer a return type of &lt;code&gt;getAmount&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// function getAmount(arr: any[] | string): number&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAmount&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// because we always return a number&lt;/span&gt;
    &lt;span class="c1"&gt;// 0 or arr.length(filtered&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Type inferring for a function that always returns a number&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, Typescript can't infer a type because of ambiguity. Usually, it's a &lt;a href="https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-function-return-type.md"&gt;good practice&lt;/a&gt; to explicitly indicate a return type of a function.&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;getAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Syntax: don't forget this&lt;/span&gt;
&lt;span class="c1"&gt;// |&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;myFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&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;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* function body */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// |&lt;/span&gt;
&lt;span class="c1"&gt;// a type this function returns&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you know how to write functions and point arguments and return types! In most cases, that's what you need. All other code is still Javascript. With more types. However, let's dive deeper and highlight more complicated cases and what things to avoid.&lt;/p&gt;

&lt;p&gt;Someone may pass anything in 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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getAmount&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="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;// no error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not what we expect. TS works well in this case, we specified &lt;code&gt;any[]&lt;/code&gt;, so what problems? &lt;strong&gt;Don't use &lt;code&gt;any&lt;/code&gt; if there's no real need for it&lt;/strong&gt;. It's easier to pass &lt;code&gt;any&lt;/code&gt; than describing an advanced type, but that's what Typescript is for. Don't shoot yourself in a foot in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typescript objects
&lt;/h2&gt;

&lt;p&gt;We may want to replace &lt;code&gt;any[]&lt;/code&gt; with &lt;code&gt;object[]&lt;/code&gt; and it would work as we pass objects there, right? Correct, but an &lt;code&gt;null&lt;/code&gt; and a function are also objects. It's not what we expect either. &lt;strong&gt;Don't use &lt;code&gt;object&lt;/code&gt;, try to narrow types&lt;/strong&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;Item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;countable&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAmount&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arr&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;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;countable&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;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getAmount&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;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;countable&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;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it works as expected. We specified a separate &lt;code&gt;interface&lt;/code&gt; for a possible array element. Interfaces and types allow you to create your own types using basic Typescript types. Some examples:&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;// is also called "type alias"&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Hash&lt;/span&gt; &lt;span class="o"&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;// interface are "object" types and allow us&lt;/span&gt;
&lt;span class="c1"&gt;// to specify an object immediately&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;isOkay&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="c1"&gt;// it's the same as using a type alias&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;isOkay&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;
  
  
  Types and interfaces
&lt;/h2&gt;

&lt;p&gt;Let's start implementing a booking tickets service to dive deeper into these types and interfaces. We want to have the possibility to book a ticket for a person.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from&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;to&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;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bookTicket&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Ticket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// some procesing&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;bookTicket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Paris&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Joey&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;The code seems okay. However, we can book a ticket to Mars using the function, but we don't fly to Mars yet. What we may rectify in our code to adjust to reality? We could add validation for &lt;code&gt;from&lt;/code&gt; and &lt;code&gt;to&lt;/code&gt; fields inside the function, but we also can do this with TypeScript. For example, we could list possible locations we're flying to and from.&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;AvailableLocation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Paris&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Moon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;London&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AvailableLocation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AvailableLocation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bookTicket&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AvailableLocation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AvailableLocation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Ticket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// some procesing&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Error: Argument of type '"Mars"' is not assignable to parameter of type 'AvailableLocation'&lt;/span&gt;
&lt;span class="nf"&gt;bookTicket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Paris&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Joey&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;We narrowed possible options for locations. Thus, eliminated cases when we can write code that calls the function with invalid locations like "Mars" or "Andromeda Galaxy". We listed multiple allowed options via "or" operator - &lt;code&gt;Paris | Moon&lt;/code&gt;. We might be using enums for this purpose too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Locations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Paris&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Moon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;London&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Ticket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;bookTicket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Paris&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Moon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Joey&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;There are differences in using types and enums, I won't cover them this time, but you may refer to &lt;a href="https://stackoverflow.com/questions/40275832/typescript-has-unions-so-are-enums-redundant"&gt;this page&lt;/a&gt; for the details.&lt;/p&gt;

&lt;p&gt;As you might notice, somewhere I used &lt;code&gt;interface&lt;/code&gt; for an object type and then declared another one via &lt;code&gt;type&lt;/code&gt;. Use what you like more for such cases or use based on your project code guidelines. For more information about the difference, &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces"&gt;read here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;Record&lt;/code&gt; to type objects
&lt;/h2&gt;

&lt;p&gt;Sometimes you have generic objects, where a key is always &lt;code&gt;string&lt;/code&gt;(and it's &lt;strong&gt;always&lt;/strong&gt; a string, if you want to use other values, use &lt;code&gt;Map&lt;/code&gt; instead) and a value is always &lt;code&gt;string&lt;/code&gt; too. In this case, you may define its type as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SomeObject&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SomeObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string value&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;There's another way to do the same using &lt;code&gt;Record&amp;lt;keyType, valueType&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SomeObject&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="c1"&gt;// it means an object with string values, e.g. {who: "me"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's something new here: &lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html"&gt;generics&lt;/a&gt;, computed types to re-use the existing ones. Let's re-create the &lt;code&gt;Record&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, if we want to create an object, we don't need to write such signatures every time. So, an object with number values is as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We may need more complex types, for example, to represent the state of our API requests. Imagine you have a global state where you put all the API data. Thus, you know where to show a loader, when to remove it, and to show relevant data.&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;StateItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isLoading&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="nl"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;State&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="nx"&gt;StateItem&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;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getInvoices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;isLoading&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="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you see the inconveniences here? We might narrow a type for &lt;code&gt;state&lt;/code&gt; keys: it's a string, but we want to be sure we put valid API request names there. The second thing is the &lt;code&gt;unknown&lt;/code&gt; I put for the &lt;code&gt;response&lt;/code&gt;(an object with &lt;code&gt;unknown&lt;/code&gt; values), yet it's still better than &lt;code&gt;any&lt;/code&gt;, because you should determine its type before any processing.&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;APIRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getInvoices&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getUsers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getActions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;isOk&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetInvoicesResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetUsersResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetActionsResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StateItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isLoading&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="nl"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;GetInvoicesResponse&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;GetUsersResponse&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;GetActionsResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;State&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="nx"&gt;APIRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StateItem&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;// Type is missing the following properties from type 'State': getUsers, getActions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getInvoices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;isLoading&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="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;isOk&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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item&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;Let's disassemble some pieces of the above:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;APIRequest&lt;/code&gt; type is a list of possible requests names. Narrowing types are for the better. See the error comment near the &lt;code&gt;state&lt;/code&gt; const? Typescript requires you to specify all the requests.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BaseResponse&lt;/code&gt; represents a default and basic response, we always know that we receive &lt;code&gt;{isOk: true | false}&lt;/code&gt;. Thus, we may prevent code duplication and re-use the type.&lt;/li&gt;
&lt;li&gt;We made a type for every request possible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While it's better than it was before, but we could do even better. The problem with these types is that &lt;code&gt;response&lt;/code&gt; is too generic: we may have  &lt;code&gt;GetInvoicesResponse | GetUsersResponse | GetActionsResponse&lt;/code&gt;. If there are more requests, there is more ambiguity. Let's employ generics to reduce duplicate 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;type&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;isOk&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetInvoicesResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetUsersResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[]};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GetActionsResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BaseResponse&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StateItem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isLoading&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="nl"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getInvoices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StateItem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetInvoicesResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StateItem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetUsersResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;getActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StateItem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetActionsResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's more readable and safe to specify every request separately, thus there's no need to check &lt;code&gt;state.getInvoices.response&lt;/code&gt; on every response type possible.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don't use &lt;code&gt;any&lt;/code&gt; type. Prefer &lt;code&gt;unknown&lt;/code&gt;. In such a way, you should be checking the type before doing any further operations with it.
&lt;/li&gt;
&lt;/ol&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;Obj&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="nx"&gt;unknown&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;o&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Object is of type 'unknown'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Prefer &lt;code&gt;Record&amp;lt;string, T&amp;gt;&lt;/code&gt; over &lt;code&gt;object&lt;/code&gt;, which can be &lt;code&gt;null&lt;/code&gt;, any kind of object, a function.  &lt;code&gt;T&lt;/code&gt; refers to a generic type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Narrow types where possible. If it's a few strings you use often, probably they can be combined in one type(see the example about API requests state).&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;GoogleEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@gmail.com`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// yet it's still a string&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GoogleEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my@gmail.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Type '"my@example.com"' is not assignable to type '`${string}@gmail.com`'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GoogleEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a new thing here: template types. Any email is a string, but if you can narrow a type, then why not(it's an example, sometimes it's an overhead).&lt;/p&gt;

&lt;h2&gt;
  
  
  Other use cases you may encounter
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Generics in functions
&lt;/h4&gt;

&lt;p&gt;You saw generics, it's a powerful way to re-use the code, the other examples include functions:&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;Response&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isOk&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="nl"&gt;statusCode&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;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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callAPI&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;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&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="nx"&gt;Response&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="c1"&gt;// it's a pseudo-fetch, the real API differs&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// some manipulations with data&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&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, the syntax is &lt;code&gt;function &amp;lt;name&amp;gt;:&amp;lt;type&amp;gt; (args) {}&lt;/code&gt;. You may use &lt;code&gt;T&lt;/code&gt;(or other names for a generic, or, a few of them) inside a function too.&lt;/p&gt;

&lt;h4&gt;
  
  
  Specifying types for readability
&lt;/h4&gt;

&lt;p&gt;Imagine you work a lot with variables that are strings, but it's hard to understand which is what type exactly. For example, when dealing with OAuth tokens.&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;AccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;IdToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&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;Both tokens are JWT strings, but sometimes it's useful to understand the 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;function&lt;/span&gt; &lt;span class="nf"&gt;callProviderEndpoint&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AccessToken&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;decodeUserInfo&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IdToken&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, the syntax is &lt;code&gt;function &amp;lt;name&amp;gt;:&amp;lt;type&amp;gt; (args) {}&lt;/code&gt;. You may use &lt;code&gt;T&lt;/code&gt;(or other names for a generic, or, a few of them) inside a function too.&lt;/p&gt;

&lt;h4&gt;
  
  
  Type assertions
&lt;/h4&gt;

&lt;p&gt;There are cases when you need to cast(transform to for the compiler) a type to another one. For example, when a library method returns object and you know it's not useful, you need a more narrow type. You may write const result = libResult as Record. as allows you to transform a type into a desired one(if it's possible). The easiest cast is for any types: the compiler doesn't know anything about a value, so it trusts you. There are cases when you'd want to cast something into any for compatibility, but often it's laziness to write correct types. Invest type into writing good(corresponding to reality) types.&lt;/p&gt;

&lt;p&gt;You may also do casts like follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyCorrectType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;libResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// the same as&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;libResponse&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;MyCorrectType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Some general questions one may ask
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Should I learn Typescript?
&lt;/h4&gt;

&lt;p&gt;Definitely. I presume you're already familiar with Javascript, which is simple and fast to prototype. Typescript adds type safety and readability. Your app's logic becomes more predictable. Read more about reasons to use Typescript.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to learn Typescript?
&lt;/h4&gt;

&lt;p&gt;Read the documentation about the basic types, or this article. Practice the examples by yourself and go code! Install the environment(many frameworks have their already prepared Typescript ecosystem for you to install and use instantly) and make things happen. It's okay you don't understand some things or you're tired of the compiler errors. It's getting easier.&lt;/p&gt;

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

&lt;p&gt;I didn't cover all the things in the article. The mentioned above should be enough to spark your interest and learn the basics that cover most cases you'll encounter. Learn as you go. The theory might seem to be complicated and boring, it's okay. Write me on Twitter if you need more details or help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metacognitive.me/typescript-tutorial-for-javascript-developers/"&gt;Original&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What are the common questions should be answered better?</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Tue, 17 Aug 2021 11:27:03 +0000</pubDate>
      <link>https://dev.to/sergchr/what-are-the-common-questions-should-be-answered-better-1426</link>
      <guid>https://dev.to/sergchr/what-are-the-common-questions-should-be-answered-better-1426</guid>
      <description>&lt;p&gt;Hi! I've created the &lt;a href="https://metacognitive.me/programming-general-faq/"&gt;general programming FAQ page&lt;/a&gt; where I tried to cover frequently asked questions beginners ask.&lt;br&gt;
For example, how to find a job, how to start learning, etc.&lt;/p&gt;

&lt;p&gt;I want to supplement the page.&lt;/p&gt;

&lt;p&gt;What the questions you asked or wanna ask that should be covered better? Maybe with simpler explanations?&lt;/p&gt;

</description>
      <category>programming</category>
      <category>discuss</category>
      <category>help</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to learn Javascript easily</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Fri, 13 Aug 2021 14:32:34 +0000</pubDate>
      <link>https://dev.to/sergchr/how-to-learn-javascript-easily-2dfb</link>
      <guid>https://dev.to/sergchr/how-to-learn-javascript-easily-2dfb</guid>
      <description>&lt;p&gt;&lt;em&gt;tl;dr search for "learn javascript theory" in Google and pick any website. Go repeat what they teach in Codepen. Repeat for every theory section.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So you're prepared to learn something exciting! The first thing you need: a theory on how those things work. Only basic things such as syntax and programming fundamentals. Like what? Understand why do we need programming it at all. What things are possible, what aren't&lt;/p&gt;

&lt;p&gt;Step 0. &lt;strong&gt;A place where to write and execute code&lt;/strong&gt;. To see the result of your code. Go to Codepen and create a pen. Or choose another code editor. This is where you'll be writing programs while studying.&lt;/p&gt;

&lt;p&gt;Step 1. &lt;strong&gt;Choose any website where you can learn about the language syntax&lt;/strong&gt;. Google "javascript tutorial", "learn js" and so. The source doesn't matter at this point, pick any.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://javascript.info/"&gt;This&lt;/a&gt; is a great resource.&lt;/p&gt;

&lt;p&gt;Get familiar with how to write code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to create a variable;&lt;/li&gt;
&lt;li&gt;how to make a function;&lt;/li&gt;
&lt;li&gt;how to call a function;&lt;/li&gt;
&lt;li&gt;how to read function arguments, handle them, and return something useful;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congrats on this milestone! You now can write basic code. Note that it isn't so straightforward to write it though in the beginning. It's okay you can't follow tutorials. Try to write basic things. Get used to the style and then go further.&lt;/p&gt;

&lt;p&gt;Don't go to the next step until you code the practice tasks in the tutorials you followed. It's important! Don't skip the tasks!&lt;/p&gt;

&lt;p&gt;Step 2. &lt;strong&gt;Learn about data structures and when to use them.&lt;/strong&gt; There are primitive structures such as numbers, strings, booleans. And there are more complex types such as arrays, objects. You should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;understand when to use arrays and objects;&lt;/li&gt;
&lt;li&gt;know the difference between the two;&lt;/li&gt;
&lt;li&gt;write a lot of code using various data structures;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't go further if you aren't comfortable with writing Javascript code. Functions, operations with objects, arrays. If you don't understand some part, it's okay and it doesn't mean you're dumb. I was trying to learn to code a lot of times and it was hard. Go back and read the theory, then solve the practical tasks. If you can't deal with them, go to Stackoverflow and see solutions. Understand how they work.&lt;/p&gt;

&lt;p&gt;Most of the time if you don't understand something, it's because you skipped a section. Or, didn't read it carefully. Or, the information isn't simple enough. Try following a different source. See a video tutorial. Still, finding it difficult? Write me.&lt;/p&gt;

&lt;p&gt;Step 3. &lt;strong&gt;Deciding your niche in applying Javascript.&lt;/strong&gt; With JS, you can program:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;front-ends(interactive visual representation). It's websites with logic. You need HTML, CSS to create visual blocks and JS to say a browser what to do. For example, when you press a button, JS handles the press and does something useful. Sends your data to a server to save in a database;&lt;/li&gt;
&lt;li&gt;back-ends(server-side code: Node.JS). This is where you can handle the data a website sends you. Store it in a database, or send it somewhere else. Or, transform it and save it;&lt;/li&gt;
&lt;li&gt;mobile apps. With React Native framework you can do such, isn't that cool?&lt;/li&gt;
&lt;li&gt;desktop apps;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 4. &lt;strong&gt;When you decide what path you want to take, learn the specifics of that environment.&lt;/strong&gt;&lt;br&gt;
For browsers(front-end path) you need to learn DOM. I.e. how to interact with visual elements on a website page. Think what projects you'd want to create - a personal website, an online store. Or something else. And create it! Make only a super simple and tiny version. Find a theory you will need when you encounter unknowns. E.g. how to find all buttons on a page and handle clicks on every one of them.&lt;/p&gt;

&lt;p&gt;If you prefer server-side coding, you should learn Node.JS. It's a thing that helps you to run Javascript in a server-side environment. Learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a basic HTTP server;&lt;/li&gt;
&lt;li&gt;handle the HTTP requests. E.g. when calling &lt;code&gt;GET /api/hello&lt;/code&gt; to return "Hi!";Then practice. Pick up the Express library. It simplifies creating code on a server. Make some HTTP routes, do some transformations of data you receive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, of course, create an interesting project! A server for an online store website? A Discord bot?&lt;/p&gt;

&lt;p&gt;For mobile and desktop apps, the strategy is the same. Learn specifics about the frameworks(React Native for mobiles or Electron for desktops). Create pet projects.&lt;/p&gt;

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

&lt;p&gt;The most important thing in learning Javascript fast enough is to practice a lot. Don't skip it. Thus you learn applicable things that solidify what you've been reading a lot.&lt;/p&gt;

&lt;p&gt;Focus on one area. Solidify your knowledge in one niche, then go further after understanding the basics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/sergchr"&gt;Follow me on Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Reasons to use Typescript</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Sat, 05 Jun 2021 13:15:26 +0000</pubDate>
      <link>https://dev.to/sergchr/reasons-to-use-typescript-1ig6</link>
      <guid>https://dev.to/sergchr/reasons-to-use-typescript-1ig6</guid>
      <description>&lt;p&gt;Typescript is a superset of Javascript. It's Javascript with type definitions and the code will be checked when compiling.&lt;/p&gt;

&lt;p&gt;Why to adopt TS if ...&lt;/p&gt;

&lt;h2&gt;
  
  
  Javascript is fast to prototype
&lt;/h2&gt;

&lt;p&gt;We can code fast with Javascript. The language is simple and allows us to do a lot of things. A prototyping time can be amazingly short. A downside of this is code readability. If we need to prototype something quickly to understand if the idea is viable, we skip thinking about architecture, writing documentation, tests. Eventually, we have a working piece. It has some bugs, but they can be fixed relatively fast. The piece is doing its intended job, we add more functionality to it, but some problems start to emerge.&lt;/p&gt;

&lt;p&gt;To add a simple functionality, it's hard to understand whether some service passes you an object with 20 fields, a string, or it may not pass anything at all. It's difficult to fathom API contracts between code pieces you wrote! By writing more console.log's you see the contracts and adjust the code to new requirements.&lt;br&gt;
After some time, your colleague asks a team's help to assist in debugging "what these objects are". Next month a manager asks why it takes so long to modify a tiny bit of the functionality. The company even hired 5 additional developers for the last week. In the next week, the CEO along with CTO decided to rewrite the product from scratch.&lt;/p&gt;

&lt;p&gt;Could the situation be different if the team adopted Typescript? Not really. But TS could help to eliminate bugs initially and with the next releases. Plus, it would take less time to modify existing code. Why? Doesn't TS add more time to write, because you should think about types, write them down? We'll get back to this question.&lt;/p&gt;
&lt;h2&gt;
  
  
  Typescript eliminates problems when you write the code
&lt;/h2&gt;

&lt;p&gt;IDEs have great TS support, so they will highlight potential errors you encounter. But, what kind of errors? Imagine you construct an object, convert it to some other form, pass it to a chain of 5 functions and then send the result to UI. It's easy to follow the object properties when constructing it in the beginning. It's difficult to follow a contract further. The next function can remove necessary fields from the object, another one will add some new ones, etc. With Typescript, you code how the object should look like, what properties are required, what are optional, and this contract will be followed. Otherwise, you'll get compile errors(and errors highlights before that).&lt;/p&gt;

&lt;p&gt;Another situation: there is a function that should be returning a number, but returns undefined. The function is complicated and we can't exactly know where the problem occurs(i.e. why it can't handle 10).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;calculateXfromNum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./otherService&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// there is a function from other service&lt;/span&gt;
&lt;span class="c1"&gt;// it calculates some number from other number&lt;/span&gt;
&lt;span class="c1"&gt;// this function should return number, at least we expect that&lt;/span&gt;
&lt;span class="c1"&gt;// judging by the code&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateXfromNum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// num is undefined&lt;/span&gt;

&lt;span class="c1"&gt;// this function expect a number&lt;/span&gt;
&lt;span class="nf"&gt;doStuffWithResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  It improves code readability
&lt;/h2&gt;

&lt;p&gt;Have you struggled with situations where you didn't know what to expect from functions, 3rd-party services responses? Like in the example above. Types allow you to see what other functions take as arguments and what they'll return. Have you seen the console.log debugging process? To understand what form an object has, people log it to the output a few times along the function execution.&lt;/p&gt;

&lt;p&gt;You could use debugger also, it may help more. But why make things so complicated? Isn't it enjoyable to know what this class method returns from the first glance at the code?&lt;/p&gt;

&lt;p&gt;The subsequent question you may derive from the reasons above may be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What about the time we spend on documenting types and writing more code? The coding won't be so fast then.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  It accelerates the development process
&lt;/h2&gt;

&lt;p&gt;How is that possible?&lt;br&gt;
If you think you will document all the types when using TS, thus it slows you down, that's not the case. Typescript is smart enough to infer types from code. In cases where it can't do that, you need to indicate a type explicitly. 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;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// n is number&lt;/span&gt;

&lt;span class="c1"&gt;// here, "num" can't be inferred, because you can pass anything here&lt;/span&gt;
&lt;span class="c1"&gt;// TS can't know that&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// if you point that "num" is number, TS knows the returning type&lt;/span&gt;
&lt;span class="c1"&gt;// will be a number too&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fn2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Still, even if Typescript can infer types in simple cases, a developer should write complex types, so how the development becomes faster?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How much time do you think developers in mid/large-size JS projects spend on debugging to understand what an object will be returned by some function? I think a lot. We don't write code for machines, but humans. The code should be understandable. You take a glance and you get a basic idea of what's going on.&lt;/p&gt;

&lt;p&gt;Learning Typescript syntax takes a few minutes to start coding if you already understand Javascript. What you need to know is how to declare type/interface. Then, you need some time to get used to advanced cases.&lt;/p&gt;

&lt;p&gt;The additional development time will go to defining types, which isn't so time-consuming. At least, it takes much less time than:&lt;/p&gt;

&lt;p&gt;asking a colleague where to find documentation about a service;&lt;br&gt;
asking a colleague who wrote that;&lt;br&gt;
asking the person who wrote that to explain what the form of an object is;&lt;br&gt;
writing comments about object type after debugging it;&lt;br&gt;
rewriting the comments because you didn't expect other use cases;&lt;br&gt;
Save yourself and your team many human hours of reading and understanding the code.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to migrate to Typescript
&lt;/h2&gt;

&lt;p&gt;I'll provide points for you to decide is it worth adopting at all, and how simple the process is.&lt;/p&gt;
&lt;h3&gt;
  
  
  It's easy to learn
&lt;/h3&gt;

&lt;p&gt;Understand how to declare types/interfaces and you're good to go. Basically, it's:&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;Human&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Human&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sergiy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While you write more code, you'll get to know many other things along the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  It's easy to start right away
&lt;/h3&gt;

&lt;p&gt;If you have a Javascript project already, all it takes for you to start writing TS code is to have Typescript installed, maybe some tsconfig configuration, and to set the --allowJs flag, so you can mix TS with JS code. As you code more, you'll add more types, and maybe you convert all the codebase to TS. At least, you can TSify crucial parts of the code right now.&lt;/p&gt;

&lt;p&gt;However, you'll need to compile the project to Javascript. An additional build step in your workflow.&lt;/p&gt;

&lt;p&gt;If you're convinced to switch or migrate to Typescript, there are some thoughts to ponder about. As a person who leads a team, you should be responsible to explain to the developers why do you choose TS, what are pros and cons. Otherwise, programmers may think of it as a tool that slows them down. You may encounter situations when a developer write something like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&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;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;object&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While it's a valid code, it doesn't add more readability. A developer may find using any is a good thing to save time. The idea the developers should understand is that if something is unknown, it's better to figure out the actual type and document it.&lt;/p&gt;

&lt;p&gt;Almost the same situation with wide types like object: the data may be an object with any properties, a function, an array. The more narrow type, the better.&lt;/p&gt;

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

&lt;p&gt;Use Typescript if you need better code readability, hence development speed up in the long run. It takes a little time to get started with TS if you know Javascript. You can integrate TS in your Javascript project without rewriting JS parts right away.&lt;/p&gt;

&lt;p&gt;Typescript is a tool that should be regarded as such and not as a thing that solves abstract problems like "improving the code".&lt;/p&gt;




&lt;p&gt;&lt;a href="https://twitter.com/sergchr"&gt;Follow me on Twitter&lt;/a&gt; and &lt;a href="https://metacognitive.me"&gt;see my other articles&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
