<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2022-06-24T12:36:43+00:00</updated><id>/feed.xml</id><title type="html">weeklyJS</title><entry><title type="html">Types as comments for plain JavaScript</title><link href="/typescript,/javascript/2022/06/24/types-as-comments-proposal.html" rel="alternate" type="text/html" title="Types as comments for plain JavaScript" /><published>2022-06-24T07:00:13+00:00</published><updated>2022-06-24T07:00:13+00:00</updated><id>/typescript,/javascript/2022/06/24/types-as-comments-proposal</id><content type="html" xml:base="/typescript,/javascript/2022/06/24/types-as-comments-proposal.html">&lt;p&gt;Today we’re looking into the potential future of JavaScript by reading up on the types as comments proposal that seeks to introduce type information as part of the core JavaScript language.&lt;/p&gt;

&lt;h2 id=&quot;types-as-comments&quot;&gt;Types as comments&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/tc39/proposal-type-annotations&quot;&gt;Types as comments&lt;/a&gt; was proposed by the &lt;a href=&quot;https://github.com/tc39&quot;&gt;TC39&lt;/a&gt; technical committee for JavaScript in late 2020. It proposes the addition of syntax for &lt;strong&gt;type information&lt;/strong&gt; as a core, but optional, part of the JavaScript language.&lt;/p&gt;

&lt;p&gt;Adding type information syntax to the language enables the potential use of static type checkers to prevent certain classes of bugs. That is to say, static type checking would be possible without having to develop in another statically typed language (such as &lt;em&gt;TypeScript&lt;/em&gt; or &lt;em&gt;Flow&lt;/em&gt;) that transpiles to JavaScript.&lt;/p&gt;

&lt;p&gt;For JavaScript developers, this promises at least two things:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;a faster development loop (i.e. without a transpilation step), and&lt;/li&gt;
  &lt;li&gt;free choice of tooling for type checking.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;why-static-type-checking&quot;&gt;Why static type checking?&lt;/h2&gt;

&lt;h3 id=&quot;typeerror-cannot-read-properties-of-undefined-reading-bar&quot;&gt;TypeError: Cannot read properties of undefined (reading ‘bar’)&lt;/h3&gt;

&lt;p&gt;The case for static type checking is not particularly hard.&lt;/p&gt;

&lt;p&gt;As JavaScript developers, we probably all know the language’s famously weak and dynamic type system which has no problem with letting funny code like the following pass to the interpreter without throwing errors:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;node &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'console.log(3 + [])'&lt;/span&gt;
3
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;node &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'console.log({}.foo)'&lt;/span&gt; 
undefined
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ️ Examples were run with Node v16.15.1.&lt;/p&gt;

  &lt;p&gt;ℹ️ Have a look at &lt;a href=&quot;https://www.google.de/books/edition/Programming_TypeScript/Y-mUDwAAQBAJ?hl=en&amp;amp;gbpv=1&amp;amp;pg=PA3&amp;amp;printsec=frontcover&quot;&gt;Programming TypeScript (p.3)&lt;/a&gt; for more examples.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Even though the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; operator may be overloaded to add strings and arrays, it doesn’t make a lot of sense to do that in the first place. Neither does accessing a custom property &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; on a, very obviously, empty object. The developers of JavaScript, in a very questionable attempt to make developer lives easier in the short run, opted to take care of these kinds of problems by&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;in the first case applying &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion&quot;&gt;type coercion&lt;/a&gt;, and&lt;/li&gt;
  &lt;li&gt;in the second case by defaulting to the special value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;undefined&lt;/code&gt; that models undefined values.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have ever ripped your hairs trying to find the cause of the infamous run time errors like “TypeError: Cannot read properties of undefined (reading ‘bar’)”&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;node &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'console.log({}.foo.bar)'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;:1
console.log&lt;span class=&quot;o&quot;&gt;({}&lt;/span&gt;.foo.bar&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                   ^

TypeError: Cannot &lt;span class=&quot;nb&quot;&gt;read &lt;/span&gt;properties of undefined &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;reading &lt;span class=&quot;s1&quot;&gt;'bar'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    at &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;:1:20
    at Script.runInThisContext &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;node:vm:129:12&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    at Object.runInThisContext &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;node:vm:305:38&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    at node:internal/process/execution:76:19
    at &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-wrapper&lt;/span&gt;:6:22
    at evalScript &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;node:internal/process/execution:75:60&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    at node:internal/main/eval_string:27:3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;you probably understand why, in the long run, you want to catch these kinds of problems &lt;strong&gt;before&lt;/strong&gt; running your code. Preferably even, you want to know this immediately when you type the code into your editor of choice.&lt;/p&gt;

&lt;h3 id=&quot;typescript-to-the-rescue&quot;&gt;TypeScript to the rescue&lt;/h3&gt;

&lt;p&gt;Part of the appeal of TypeScript is that it adds this additional layer of &lt;strong&gt;static&lt;/strong&gt;—i.e. before runtime—safety to your JavaScript code.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The main benefit of TypeScript is that it can highlight unexpected behavior in your code, lowering the chance of bugs.”&lt;/p&gt;

  &lt;p&gt;— &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html&quot;&gt;TypeScript in 5 Minutes&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s now, for example, directly run the above code examples with TypeScript (using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts-node&lt;/code&gt;).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ts-node &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'console.log(3 + [])'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;.ts:1:13 - error TS2365: Operator &lt;span class=&quot;s1&quot;&gt;'+'&lt;/span&gt; cannot be applied to types &lt;span class=&quot;s1&quot;&gt;'number'&lt;/span&gt; and &lt;span class=&quot;s1&quot;&gt;'never[]'&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

1 console.log&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3 + &lt;span class=&quot;o&quot;&gt;[])&lt;/span&gt;
              ~~~~~~
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ts-node &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'console.log({}.foo.bar)'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;.ts:1:16 - error TS2339: Property &lt;span class=&quot;s1&quot;&gt;'foo'&lt;/span&gt; does not exist on &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{}'&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

1 console.log&lt;span class=&quot;o&quot;&gt;({}&lt;/span&gt;.foo.bar&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                 ~~~
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As we can see, both problems can easily be detected before running the code by applying static type checking. In the first case, TypeScript tells us that we likely wanted a number on the right-hand side of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; operator (and not an array).&lt;/p&gt;

&lt;p&gt;In the second case, we are informed that empty objects do not magically come with an arbitrary property called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ️ Admittedly, the phrasing of the first error message is a little bit off because we &lt;strong&gt;can&lt;/strong&gt; actually apply the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; operator to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array&lt;/code&gt; types (in our case yielding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt; as shown above). By &lt;a href=&quot;https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-addition-operator-plus&quot;&gt;specification&lt;/a&gt;, however, it is only overloaded for number addition and string concatenation. Moreover, it makes very little sense to “add” numbers and arrays, so the right-hand side value probably was intended to be a number as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These two properties, i.e.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;the plus operator is only used for number addition and string concatenation and&lt;/li&gt;
  &lt;li&gt;custom properties of objects are not accessed before they are set&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;are very reasonable constraints for good JavaScript programs. If they don’t hold, we most likely have found some kind of program bug or otherwise bad code. Consequently, it’s extremely helpful that TypeScript can assert (or, disproof) these properties for us before we run the code.&lt;/p&gt;

&lt;p&gt;Another great aspect of TypeScript’s type checking is that we, for the most part, don’t actually have to add a lot of type information. In simple cases like the above, TypeScript can simply guess the types via &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/type-inference.html&quot;&gt;type inference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unsurprisingly, a lot of JavaScript developers have come to appreciate TypeScript for these and other reasons and it is considered one of the technologies that are considered &lt;em&gt;safe to adopt&lt;/em&gt; by the community. I.e. TypeScript has both a high satisfaction level and is widely used (cf. &lt;a href=&quot;https://2020.stateofjs.com/en-US/technologies/#scatterplot_overview&quot;&gt;State of JS: Satisfaction vs Usage&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2022-06_state-of-js-satisfaction-vs-usage.png&quot; alt=&quot;State of JS 2020: Satisfaction vs Usage&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;making-type-annotations-part-of-javascript&quot;&gt;Making type annotations part of JavaScript&lt;/h2&gt;
&lt;h3 id=&quot;what-does-it-look-like&quot;&gt;What does it look like?&lt;/h3&gt;

&lt;p&gt;The syntax of the &lt;a href=&quot;https://github.com/tc39/proposal-type-annotations&quot;&gt;proposal for types as comments&lt;/a&gt; will probably not surprise anyone who has worked with either TypeScript or Flow. It rather seems like the authors aimed to capture the common subset of both. A lot of code written in TypeScript and Flow therefore already conforms to the proposed syntax.&lt;/p&gt;

&lt;p&gt;Let’s take a look at some examples to illustrate the similarities.&lt;/p&gt;

&lt;h4 id=&quot;type-annotations&quot;&gt;Type Annotations&lt;/h4&gt;

&lt;p&gt;A &lt;strong&gt;type annotation&lt;/strong&gt; is written in the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x: T&lt;/code&gt; where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; is a variable name and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; is a type name. We may use type annotations in variable declarations or in function parameters.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// a variable that stores a string&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;// a function that takes two string parameters and returns a boolean value&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* … */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;type-declarations&quot;&gt;Type declarations&lt;/h4&gt;

&lt;p&gt;Types may be &lt;strong&gt;declared&lt;/strong&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interface&lt;/code&gt; keyword to introduce a new type or using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; keyword to declare aliases.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// An object type with a properties coordinate and radius.&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;coordinate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// A shorter alias for boolean&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Classes also implicitly define types.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Implicitly declares a type Point&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Point&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;implicitly-defined-types&quot;&gt;Implicitly defined types&lt;/h4&gt;

&lt;p&gt;JavaScript’s primitive data types have corresponding predefined types (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ️ Curiously, the proposal suggests ignoring anything in between the curly braces of both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interface&lt;/code&gt; as well as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; declarations. This does not make much sense to me at the moment, but will hopefully be cleared up in the upcoming drafts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;advanced-features&quot;&gt;Advanced features&lt;/h4&gt;

&lt;p&gt;Some more complicated type system features such as&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;type unions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type C = A | B&lt;/code&gt;),&lt;/li&gt;
  &lt;li&gt;generics (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type A&amp;lt;T&amp;gt; = T[]&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interface Box&amp;lt;T&amp;gt; { content: T; }&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;type and non-null assertions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const point = JSON.parse('{&quot;x&quot;: 0, &quot;y&quot;: 0}') as Point&lt;/code&gt; resp. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JSON.parse('{&quot;x&quot;: 0, &quot;y&quot;: 0}')!.x&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;are also proposed to be supported in order to add some more expressiveness.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ️ For the full list of features, take a look at &lt;a href=&quot;https://github.com/tc39/proposal-type-annotations&quot;&gt;the current draft&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;extensions-to-the-module-system&quot;&gt;Extensions to the module system&lt;/h4&gt;

&lt;p&gt;Lastly, an extension to the module system syntax is proposed so that types can be imported and exported as well using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import type&lt;/code&gt; respectively &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export type&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;motivation-for-types-as-comments-in-javascript&quot;&gt;Motivation for types as comments in JavaScript&lt;/h3&gt;

&lt;p&gt;Judging from the widespread adoption of TypeScript, static typing is generally considered useful for JavaScript development. So, the question to address is “why don’t we just not develop in TypeScript if we want to add type information to our JavaScript and/or static type checks to our JavaScript development process?”&lt;/p&gt;

&lt;p&gt;One big argument in favor of types as comments in JavaScript compared to TypeScript (or similar languages and tools) is that it gives us the choice of tooling. For example, we could opt for &lt;a href=&quot;https://flow.org/&quot;&gt;Flow’s&lt;/a&gt; type checker instead of TypeScript’s type checker if we preferred that.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ️ Flow would also be able to read the JavaScript code with type information as we will see later on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another important argument pro types as comments in JavaScript is that it lets us skip the inevitable JavaScript transpilation step. Compare that to developing in TypeScript, where the usual workflow includes running our code through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsc&lt;/code&gt; (the TypeScript compiler) before executing it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node&lt;/code&gt; or in the browser. Dropping the transpilation step may significantly improve the speed of our development loop and moreover may require less set-up (such as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsconfig.json&lt;/code&gt; file).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2022-06_types-as-comments-comparison.png&quot; alt=&quot;Comparison of development workflow: type as comments and TypeScript&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ️ A more elaborate discussion can be found here in &lt;a href=&quot;https://devblogs.microsoft.com/typescript/a-proposal-for-type-syntax-in-javascript/&quot;&gt;this article on the Microsoft dev blog&lt;/a&gt;. (Picture above is also taken from the blog.)&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;Lastly, even if we don’t use type information for static type checking, it could be argued that they are a very good and less verbose replacement for &lt;a href=&quot;https://jsdoc.app/&quot;&gt;JSDoc&lt;/a&gt; style type comments. I.e., this&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
 * @param a {number}
 * @param b {number}
 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;simply would become this&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;what-the-proposal-is-not-about&quot;&gt;What the proposal is not about&lt;/h3&gt;

&lt;p&gt;When I first read through the proposal it strongly reminded me of the way optional type information was introduced via &lt;a href=&quot;https://www.python.org/dev/peps/pep-0484/&quot;&gt;type hints in Python&lt;/a&gt;. I.e. adding type checking is entirely opt-in. You can use it if you want to, but you don’t have to. It is not about introducing a specific type system. And, by extension, neither is it about standardising TypeScript’s type system in the JavaScript specification.&lt;/p&gt;

&lt;p&gt;This is a cautious and smart way to proceed on this topic in my opinion, because there is—as mentioned in the proposal—a very high risk that it would break the web. I.e. if web browsers would run type checks on JavaScript code, a lot of websites might break because they run type-wise unsound code.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;The types as comments proposal laid out by the TC39 technical committee for JavaScript suggests adding syntax for optional typing information to JavaScript. With these syntax additions, we may provide type information in JavaScript code similar to comments. This type information may be used to leverage static type checking just as in TypeScript or Flow in order to improve code quality and safety. Having types as comments in JavaScript makes a lot of sense given the popularity of statically typed languages that compile to JavaScript such as TypeScript and Flow. We can make at least three arguments in favor of types as comments: 1. it gives us the choice of the type checker, 2. we can prune the transpilation step from our development loop, and 3. type information is a less verbose replacement for JSDoc-style type comments.&lt;/p&gt;

&lt;p&gt;Do you have any questions, suggestions, or comments? Get in touch with the author &lt;a href=&quot;https://aemail.com/Z4YQ&quot;&gt;via mail&lt;/a&gt;!&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-friedrich-kurz&quot;&gt;About the Author: Friedrich Kurz&lt;/h2&gt;

&lt;p&gt;Friedrich has been working for MaibornWolff as a full-time software engineer for 2.5 years. In his current project, he’s helping to build the AWS cloud infrastructure for a client’s web platform. Friedrich considers himself a technology generalist with a broad range of interests rather than a technology specialist. He’s, however, also very interested in functional programming and general methods of writing correct, clean, and maintainable code.&lt;/p&gt;</content><author><name>Friedrich Kurz</name></author><category term="typescript," /><category term="javascript" /><summary type="html">Today we’re looking into the potential future of JavaScript by reading up on the types as comments proposal that seeks to introduce type information as part of the core JavaScript language.</summary></entry><entry><title type="html">Type-Aware Rules for ESLint</title><link href="/typescript/2022/06/17/type-aware-rules-for-eslint.html" rel="alternate" type="text/html" title="Type-Aware Rules for ESLint" /><published>2022-06-17T09:00:00+00:00</published><updated>2022-06-17T09:00:00+00:00</updated><id>/typescript/2022/06/17/type-aware-rules-for-eslint</id><content type="html" xml:base="/typescript/2022/06/17/type-aware-rules-for-eslint.html">&lt;p&gt;In a previous article my colleague &lt;a href=&quot;https://www.maibornwolff.de/team/tobias-walle&quot;&gt;Tobias Walle&lt;/a&gt; already discussed how &lt;a href=&quot;https://weeklyjs.io/javascript/2022/04/22/static-code-analysis.html&quot;&gt;Static code analysis in Node.js&lt;/a&gt; can be used to improve the quality of your code, specifically with &lt;a href=&quot;https://eslint.org/&quot;&gt;ESLint&lt;/a&gt;. Most TypeScript developers are probably already aware of the &lt;a href=&quot;https://typescript-eslint.io/&quot;&gt;eslint-plugin&lt;/a&gt; which provides a plethora of additional rules specifically for TypeScript.&lt;/p&gt;

&lt;p&gt;What is slightly less known is that you can opt in to &lt;a href=&quot;https://typescript-eslint.io/docs/linting/#type-aware-rules&quot;&gt;type-aware rules&lt;/a&gt;, albeit at some &lt;a href=&quot;https://typescript-eslint.io/docs/linting/type-linting#how-is-performance&quot;&gt;cost to performance&lt;/a&gt;. It is highly recommended to enable this feature unless the size of your code base makes the use of it prohibitively expensive - in which case you might want to defer these checks to a pre-commit hook.&lt;/p&gt;

&lt;p&gt;Setting this up is slightly more tricky than your average ESLint-plugin, but the &lt;a href=&quot;https://typescript-eslint.io/docs/linting/type-linting&quot;&gt;documentation&lt;/a&gt; does a great job of guiding you through it. Just make sure you read the &lt;a href=&quot;https://typescript-eslint.io/docs/linting/type-linting#troubleshooting&quot;&gt;troubleshooting&lt;/a&gt; section because chances are you will run into issues if you don’t. Or so I am told 🙄.&lt;/p&gt;

&lt;p&gt;So what’s the benefit of all of this? Consider the following (admittedly somewhat silly) piece of code, which will pass conventional linting just fine:&lt;/p&gt;
&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;💥&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;boom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Eagle-eyed developers will quickly spot at least three issues with this (besides the pointlessness of the function 😉):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the function is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt; even though it does not need to be&lt;/li&gt;
  &lt;li&gt;the call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boom&lt;/code&gt; is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt;ed.&lt;/li&gt;
  &lt;li&gt;the function throws a string literal, not an an &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error&quot;&gt;Error object&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where the type-aware rules &lt;a href=&quot;https://typescript-eslint.io/rules/require-await&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require-await&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://typescript-eslint.io/rules/no-floating-promises&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no-floating-promises&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://typescript-eslint.io/rules/no-throw-literal&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no-throw-literal&lt;/code&gt;&lt;/a&gt;, respectively, come to the rescue. Please note that the latter is not enabled by default if your configuration only extends &lt;a href=&quot;https://typescript-eslint.io/docs/linting/configs#recommended-requiring-type-checking&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin:@typescript-eslint/recommended-requiring-type-checking&lt;/code&gt;&lt;/a&gt;, you will either have to enable it manually or also use &lt;a href=&quot;https://typescript-eslint.io/docs/linting/configs#strict&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin:@typescript-eslint/strict&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-raphael-pigulla&quot;&gt;About the author: Raphael Pigulla&lt;/h2&gt;

&lt;p&gt;Raphael has more than ten years of experience in software development and architecture. He specializes in backend development with Node.js and TypeScript. Raphael joined &lt;a href=&quot;https://maibornwolff.de&quot;&gt;MaibornWolff&lt;/a&gt; in 2019.&lt;/p&gt;</content><author><name>Raphael Pigulla</name></author><category term="typescript" /><summary type="html">In a previous article my colleague Tobias Walle already discussed how Static code analysis in Node.js can be used to improve the quality of your code, specifically with ESLint. Most TypeScript developers are probably already aware of the eslint-plugin which provides a plethora of additional rules specifically for TypeScript.</summary></entry><entry><title type="html">Deno - adopt or wait?</title><link href="/deno/2022/06/10/deno.html" rel="alternate" type="text/html" title="Deno - adopt or wait?" /><published>2022-06-10T05:00:13+00:00</published><updated>2022-06-10T05:00:13+00:00</updated><id>/deno/2022/06/10/deno</id><content type="html" xml:base="/deno/2022/06/10/deno.html">&lt;p&gt;Deno is 4 years old now and is slowly maturing. Among other things, the Node alternative has become known for the really good security principles. 
Deno is running in a kind of sandbox, just like the browser sandbox. Many developers really like the idea. But how mature is Deno really? 
Is the effort of changing your runtime worth it if you are already familiar with Node? What’s still missing from the young competitor? Architecture expert Sebastian Springer answers these questions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the most important security feature of Deno?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“The fact that you can manage access permissions to system resources. However, this should be taken with a grain of salt. 
I can a) leave it out and Deno asks me. Or b) make it explicit via options. Or c) turn off security with an option. 
If an application needs too many permissions and asks for them, one is quickly tempted to just choose option c).”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you have to get used to when you switch from Node to Deno?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“Deno does away with many of Node’s weaknesses and, for example, relies on the ECMAScript module system, supports modern JavaScript and TypeScript out of the box.
Unusual is the absence of a package manager, which is reflected in the omission of package.json, package-lock.json and the node_modules directory. 
For Node developers, this removes familiar structures and perhaps a bit of stability, as the packages now come directly from the Internet.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it make sense to change from Node to Deno in existing projects?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“Personally, I continue to rely on Node in the large projects, the platform is stable, established and has a huge ecosystem to utilize. 
For small and medium projects, completed services or prototypes, Deno is definitely a very good solution. 
Even though Deno is already 4 years old, very important developments have taken place only in the last months and years. Like, for example, the collaboration with Node and the community.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“I know that I need Deno when”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“…I implement small and modern applications, attach importance to additional security in the form of a sandbox. Concrete projects are also a great opportunity to learn the Deno way of doing things.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you miss in Deno?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“What I miss with Deno is the stability of Node. There’s a lot happening under the hood right now, the community is growing and evolving. 
That’s excellent for me as a developer, I want to try new things. For my big project, sometimes I don’t want that flexibility and modernity.&lt;/p&gt;

&lt;p&gt;Deno is evolving in a very interesting direction and getting closer and closer to Node. 
My hope is that many of these modern concepts will find their way into Node and both platforms will peacefully coexist and challenge each other 
and make sure that new features find their way into the server-side JavaScript world.”&lt;/p&gt;

&lt;h2 id=&quot;about-the-author&quot;&gt;About the author&lt;/h2&gt;

&lt;p&gt;Sebastian Springer is a JavaScript developer at MaibornWolff, focussing on the architecture of client- and server-side JavaScript. 
He is also regularly speaking about JavaScript at national and international conferences and events.
MaibornWolff is hiring! If you want to work with Sebastian, this job might be interesting to you: &lt;a href=&quot;https://www.maibornwolff.de/en/careers/job-vacancies/web-developer&quot;&gt;Web Developer (m/f/d) Javascript / Typescript&lt;/a&gt;&lt;/p&gt;</content><author><name>Sebastian Springer</name></author><category term="deno" /><summary type="html">Deno is 4 years old now and is slowly maturing. Among other things, the Node alternative has become known for the really good security principles. Deno is running in a kind of sandbox, just like the browser sandbox. Many developers really like the idea. But how mature is Deno really? Is the effort of changing your runtime worth it if you are already familiar with Node? What’s still missing from the young competitor? Architecture expert Sebastian Springer answers these questions:</summary></entry><entry><title type="html">Angular Changedetection Playground</title><link href="/angular/2022/06/03/angular-change-detection.html" rel="alternate" type="text/html" title="Angular Changedetection Playground" /><published>2022-06-03T05:00:13+00:00</published><updated>2022-06-03T05:00:13+00:00</updated><id>/angular/2022/06/03/angular-change-detection</id><content type="html" xml:base="/angular/2022/06/03/angular-change-detection.html">&lt;p&gt;Some colleagues who have not yet dealt much with the topic of ChangeDetection in Angular may find it difficult to imagine what the 
difference between the default and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnPush&lt;/code&gt; approach is.&lt;/p&gt;

&lt;p&gt;When your application gets larger this topic gets more relevant tou you.&lt;/p&gt;

&lt;p&gt;Here I would like to compare and show how ChangeDetection can have an effect on the performance of an application.&lt;/p&gt;

&lt;h2 id=&quot;what-is-changedetection&quot;&gt;What is ChangeDetection?&lt;/h2&gt;

&lt;p&gt;ChangeDetection in Angular is a process which check if components have to rerender.&lt;/p&gt;

&lt;p&gt;By Default, each component is permanently checked whether values have changed.&lt;/p&gt;

&lt;p&gt;In my main project which grew over the years it is a nearly endless type of processing.&lt;/p&gt;

&lt;p&gt;So the idea was, step by step migrate to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnPush&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But what is the difference?&lt;/p&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnPush&lt;/code&gt; it’s up to you to trigger the ChangeDection yourself, using the available tools.&lt;/p&gt;

&lt;p&gt;In this articls I hope to give you a better overview of the differences and why it is important to not ignore that topic.&lt;/p&gt;

&lt;h2 id=&quot;before-to-start&quot;&gt;Before to start&lt;/h2&gt;

&lt;p&gt;what is the difference between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markForCheck&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detectChanges&lt;/code&gt;?&lt;/p&gt;

&lt;h3 id=&quot;markforcheck&quot;&gt;markForCheck&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markForCheck&lt;/code&gt; should always be used if you have to signal the detector to check that view.&lt;/p&gt;

&lt;h3 id=&quot;detectchanges&quot;&gt;detectChanges&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detectChanges&lt;/code&gt; should be used to check the view and the children of it.&lt;/p&gt;

&lt;p&gt;If you want to check only a small scope of your detection tree, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detach&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warning: detach components should be done with caution!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;expectation&quot;&gt;Expectation&lt;/h2&gt;

&lt;p&gt;Default: Angular will rather check the DOM tree too many times than not enough.&lt;/p&gt;

&lt;p&gt;OnPush: In Angular it’s your own responsibility to use build-in capabilities like Pipes, Components and the ChangeDetectorRef to define where checks are necessary outside the lifecycle routines.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;Angular ~13&lt;/p&gt;

&lt;p&gt;Material ~13&lt;/p&gt;

&lt;p&gt;Now I going to use the following two components to build my test angular component tree.&lt;/p&gt;

&lt;p&gt;AppComponent - the App Wrapper&lt;/p&gt;

&lt;p&gt;DetectionBlockComponent - Components which create recursive Child Components.&lt;/p&gt;

&lt;h2 id=&quot;playground&quot;&gt;Playground&lt;/h2&gt;

&lt;p&gt;My Component tree looks like:&lt;/p&gt;

&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;| App
| - 1
|   - 3
|     - 4
|       - 5
|         - 6
| - 2
|   - 7
|     - 8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;test-process&quot;&gt;Test Process&lt;/h2&gt;

&lt;p&gt;The following steps I clicked in the appliation:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open Page&lt;/li&gt;
  &lt;li&gt;click detectChanges 4&lt;/li&gt;
  &lt;li&gt;click markForCheck 7&lt;/li&gt;
  &lt;li&gt;click markForCheck 4&lt;/li&gt;
  &lt;li&gt;click detectChanges 2&lt;/li&gt;
  &lt;li&gt;click markForCheck App&lt;/li&gt;
  &lt;li&gt;click detectChanges App&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;test-results&quot;&gt;Test results&lt;/h1&gt;

&lt;h2 id=&quot;app-in-default-detection&quot;&gt;app in default detection&lt;/h2&gt;

&lt;p&gt;We come to the following numbers&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Step&lt;/th&gt;
      &lt;th&gt;check cycles&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;15&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;13&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;12&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;13&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;11&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;total&lt;/td&gt;
      &lt;td&gt;83&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;explaination&quot;&gt;Explaination&lt;/h3&gt;

&lt;p&gt;the complete tree will be check from the detector on initial.&lt;/p&gt;

&lt;p&gt;After the initial check, the app component in default mode will check multiple times itself and the children of it.&lt;/p&gt;

&lt;p&gt;When click on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detectChanges&lt;/code&gt; of a node in the tree, itself and its children will be checked. If you don’t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detach&lt;/code&gt; the ChangeDetection will start at the top of the tree and check until the origin of the detection event.&lt;/p&gt;

&lt;p&gt;And again, default, app will check their children multiple times.&lt;/p&gt;

&lt;p&gt;What happens with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markForCheck&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;checks 7&lt;/li&gt;
  &lt;li&gt;checks app&lt;/li&gt;
  &lt;li&gt;checks 1&lt;/li&gt;
  &lt;li&gt;checks 2&lt;/li&gt;
  &lt;li&gt;checks 7&lt;/li&gt;
  &lt;li&gt;checks 8&lt;/li&gt;
  &lt;li&gt;double checks app again&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;app-in-onpush-detection&quot;&gt;app in onpush detection&lt;/h2&gt;

&lt;p&gt;We come to the following numbers&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Step&lt;/th&gt;
      &lt;th&gt;check cycles&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;11&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;total&lt;/td&gt;
      &lt;td&gt;55&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;explaination-1&quot;&gt;Explaination&lt;/h3&gt;

&lt;p&gt;Wow! Just app component onPush v.s. default performed better by about 45%!&lt;/p&gt;

&lt;p&gt;In initial check, ‘1’ and ‘2’ won’t check twice, only app still check multiple times in that setup.&lt;/p&gt;

&lt;p&gt;Also additional steps won’t check as often.&lt;/p&gt;

&lt;p&gt;App is more stable and won’t check the tree everytime so “aggressive”.&lt;/p&gt;

&lt;p&gt;What’s the pitfall here? Mutations in objects without trigger detection by yourself can occure stale views. So be careful how you write component logic. Best practices IMHO are observables with async subscription in the template or call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markForCheck&lt;/code&gt; after async processes in the component.&lt;/p&gt;

&lt;h2 id=&quot;detach-components-after-view-init&quot;&gt;detach components after view init&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;This section is more experimental!
In this case, the simple application setup made it possible to receive the same application behavior then before.
Larger apps may get more stale and shaky when detach without caution!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you have call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detach&lt;/code&gt; the components after intial rendering show the following numbers&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Step&lt;/th&gt;
      &lt;th&gt;check cycles&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;11&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;total&lt;/td&gt;
      &lt;td&gt;38&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;explaination-2&quot;&gt;Explaination&lt;/h3&gt;

&lt;p&gt;Awesome, from 83 to 38 is a lot of circles which we safed!&lt;/p&gt;

&lt;p&gt;What’s the reason?&lt;/p&gt;

&lt;p&gt;By detaching all components from the ChangeDetection, you take over the full control over the ChangeDetection of them.&lt;/p&gt;

&lt;p&gt;For example, after ‘initial’ step the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detectChanges&lt;/code&gt; of ‘4’ will only effect app, ‘4’ and ‘5’.&lt;/p&gt;

&lt;p&gt;‘5’ is the child, ‘4’ itself and app because it’s the root node and have to check how much of the total tree (which nomore exists more or less) has to check like before.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The reason for multiple checks of app is not clear to me, I’ll check it later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What are the risks with this setup?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Detach can hide changes in the detector circles, so changes in your component won’t notify the renderer and the DOM becomes stale.&lt;/li&gt;
  &lt;li&gt;You have to do a lot of things manually, like detection and detach(reattach) the component&lt;/li&gt;
  &lt;li&gt;Child components may not render or act correctly. In my first experiments with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MatButton&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MatInput&lt;/code&gt; it won’t display correct.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;my-learning-while-writing-this-post&quot;&gt;My learning while writing this post&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detach&lt;/code&gt; static “leaf” components can safe performance&lt;/li&gt;
  &lt;li&gt;From &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Default&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnPush&lt;/code&gt; can be hard but is essential for larger applications&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;numbers-behind-the-tests&quot;&gt;Numbers behind the tests&lt;/h3&gt;

&lt;p&gt;See &lt;a href=&quot;../assets/numbers.md&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-nils-heinemann&quot;&gt;About the author: Nils Heinemann&lt;/h2&gt;

&lt;p&gt;Nils has more than five years of experience in software development and architecture. He specializes in frontend development with Angular and TypeScript. Nils joined MaibornWolff in 2018.&lt;/p&gt;</content><author><name>Nils Heinemann</name></author><category term="angular" /><summary type="html">Some colleagues who have not yet dealt much with the topic of ChangeDetection in Angular may find it difficult to imagine what the difference between the default and the OnPush approach is.</summary></entry><entry><title type="html">Avoid canceled requests when using RxJS combineLatest()</title><link href="/angular/2022/05/27/rxjs-operators.html" rel="alternate" type="text/html" title="Avoid canceled requests when using RxJS combineLatest()" /><published>2022-05-27T05:00:13+00:00</published><updated>2022-05-27T05:00:13+00:00</updated><id>/angular/2022/05/27/rxjs-operators</id><content type="html" xml:base="/angular/2022/05/27/rxjs-operators.html">&lt;p&gt;If you work with Angular in your project, then you can’t avoid the reactive framework RxJS. This offers a lot of of operators. While some are rarely used, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;combinedLatest&lt;/code&gt; is certainly one of the great favorites of any Angular developer. It is used to combine multiple observable streams. It emits a value as soon as all incoming observables emit at least one value.&lt;/p&gt;

&lt;h2 id=&quot;example-with-backend-request&quot;&gt;Example with backend request&lt;/h2&gt;
&lt;p&gt;Our example is quite simple. We have two observables: day and month. These are combined with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;combineLatest&lt;/code&gt;. As soon as the combined observable changes, a request is executed against a backend. The request is in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switchMap()&lt;/code&gt;. In the UI we have three buttons to change the day, the month and both at the same time (day + month).&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;day$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BehaviorSubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dayCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;month$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BehaviorSubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;monthCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;combineLatest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;day$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;month$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;debounceTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;switchMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dataService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apiCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;increaseDay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dayCount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;day$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dayCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;increaseMonth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;monthCount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;month$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;monthCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;increaseDayAndMonth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;increaseDay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;increaseMonth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you click on the button in the UI to trigger &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changeDay()&lt;/code&gt;, a request is sent to the backend. With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;increaseMonth()&lt;/code&gt;
it is the same. So far everything is fine.&lt;/p&gt;

&lt;p&gt;But if we now use the method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;increaseDayAndMonth()&lt;/code&gt; to change both at the same time, i.e. day and month,
then we see that a canceled request is displayed in our console.&lt;/p&gt;

&lt;p&gt;The request is canceled because we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switchMap&lt;/code&gt;, which ensures that only the most recent request is active.&lt;/p&gt;

&lt;p&gt;So the problem is that in a very short time our incoming observables are changing and therefore triggering the backend request twice in a row.&lt;/p&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;p&gt;To avoid the problem, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debounceTime&lt;/code&gt; operator with the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; can be used. The value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; means that 0 milliseconds are waited until the emitted values pass through.&lt;/p&gt;

&lt;p&gt;However, it also says that this will only happen at the end of the call stack. This can be considered as a kind of loop, only when the loop has run through, the request is 
executed. Since within the loop is not only the change of “days”, but also the change of “month”, the request is executed only once.&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-fabian-birke&quot;&gt;About the author: Fabian Birke&lt;/h2&gt;

&lt;p&gt;Fabian joined MaibornWolff GmbH in 2019 and has several years of experience as a full-stack developer. Currently he focuses on the development of dynamic frontend applications.&lt;/p&gt;</content><author><name>Fabian Birke</name></author><category term="angular" /><summary type="html">If you work with Angular in your project, then you can’t avoid the reactive framework RxJS. This offers a lot of of operators. While some are rarely used, combinedLatest is certainly one of the great favorites of any Angular developer. It is used to combine multiple observable streams. It emits a value as soon as all incoming observables emit at least one value.</summary></entry><entry><title type="html">Handling Conditional Classes in Angular</title><link href="/angular/2022/05/20/conditional-classes-angular.html" rel="alternate" type="text/html" title="Handling Conditional Classes in Angular" /><published>2022-05-20T13:00:13+00:00</published><updated>2022-05-20T13:00:13+00:00</updated><id>/angular/2022/05/20/conditional-classes-angular</id><content type="html" xml:base="/angular/2022/05/20/conditional-classes-angular.html">&lt;p&gt;How do you handle conditional classes at a dom element in Angular? There are two main options: class-bindings and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngclass&lt;/code&gt;. But which one is better?
I tested both to get a definite answer.&lt;/p&gt;

&lt;h2 id=&quot;ngclass-vs-class-binding&quot;&gt;ngclass vs class-binding&lt;/h2&gt;

&lt;p&gt;How to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngclass&lt;/code&gt;?&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;[ngClass]=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{
  class0: condition,
  classN: condition
}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And how would class-binding look like?&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;[class.class0]=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;condition&quot;&lt;/span&gt;
     &lt;span class=&quot;na&quot;&gt;[class.classN]=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;condition&quot;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;test-scenario&quot;&gt;Test Scenario&lt;/h2&gt;

&lt;h3 id=&quot;project-structure&quot;&gt;Project Structure&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;app.component.class.html =&amp;gt; contains class-binding version of the template

app.component.ngclass.html =&amp;gt; contains ngclass version of the template

app.component.css =&amp;gt; basic css to provide the demo styles

app.component.ts =&amp;gt; align state and callbacks for the buttons to change the alignment

index.html =&amp;gt; basic resetted index file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;do-it-yourself&quot;&gt;Do it yourself&lt;/h3&gt;

&lt;p&gt;just clone the &lt;a href=&quot;https://github.com/SourceCodeBot/angular-class-binding-demo&quot;&gt;repository&lt;/a&gt; and execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;on http://localhost:4200 you can directly interact with the current selected version.&lt;/p&gt;

&lt;h3 id=&quot;test-plan&quot;&gt;Test Plan&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Open the Devtools&lt;/li&gt;
  &lt;li&gt;Open the &lt;a href=&quot;https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh&quot;&gt;angular profiler plugin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;switch to “profiler” tab&lt;/li&gt;
  &lt;li&gt;start recording by click the round button which become red by hover&lt;/li&gt;
  &lt;li&gt;press
    &lt;ol&gt;
      &lt;li&gt;top&lt;/li&gt;
      &lt;li&gt;bottom&lt;/li&gt;
      &lt;li&gt;left&lt;/li&gt;
      &lt;li&gt;right&lt;/li&gt;
      &lt;li&gt;center&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;click “safe profile” to export a json with the detail report&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;my-result&quot;&gt;My Result&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;numbers in seconds&lt;/p&gt;
&lt;/blockquote&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Direction&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;ngclass&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Class-binding&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;top&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,4999&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,2999&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;bottom&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,7000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,4000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;left&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,6000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,4000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;right&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,3999&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,3000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Center&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,4000&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0,0999&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;recommandation&quot;&gt;Recommandation&lt;/h2&gt;

&lt;p&gt;To avoid complexity in your change detection circle you should probably use class-binding instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngclass&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For more complex usecases or if you want to bind a object with the typesignature &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Record&amp;lt;string, boolean&amp;gt;&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngclass&lt;/code&gt; would be the right way.&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-nils-heinemann&quot;&gt;About the author: Nils Heinemann&lt;/h2&gt;

&lt;p&gt;Nils has more than five years of experience in software development and architecture. He specializes in frontend development with Angular and TypeScript. Nils joined MaibornWolff in 2018. If you want to work with Nils, we are looking for &lt;a href=&quot;https://www.maibornwolff.de/en/careers/job-vacancies/web-developer&quot;&gt;Web Developers&lt;/a&gt;!&lt;/p&gt;</content><author><name>Nils Heinemann</name></author><category term="angular" /><summary type="html">How do you handle conditional classes at a dom element in Angular? There are two main options: class-bindings and ngclass. But which one is better? I tested both to get a definite answer.</summary></entry><entry><title type="html">Writing CLI tools with TypeScript</title><link href="/typescript/2022/05/06/writing-cli-tools.html" rel="alternate" type="text/html" title="Writing CLI tools with TypeScript" /><published>2022-05-06T07:00:13+00:00</published><updated>2022-05-06T07:00:13+00:00</updated><id>/typescript/2022/05/06/writing-cli-tools</id><content type="html" xml:base="/typescript/2022/05/06/writing-cli-tools.html">&lt;p&gt;There are quite a couple of technology options when it comes to writing a &lt;em&gt;command-line interface&lt;/em&gt; (CLI) tool. Most modern languages at the very least provide some kind of out-of-the-box support for command-line argument parsing. In addition, the ecosystems of modern languages also typically contain at least one mature and feature-rich CLI library.&lt;/p&gt;

&lt;p&gt;TypeScript is a good choice for writing CLI tools for a couple of reasons including developer-friendliness, static checks, as well as a broad choice of tooling options. As with every TypeScript project, there is however an initial setup hurdle. We’ll have a look at how to set up a TypeScript CLI project with linting, formatting, testing, and packaging to a standalone binary in this post.&lt;/p&gt;

&lt;p&gt;To give a few examples, here are some of the libraries and languages I’ve used recently to write CLIs&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.rs/clap/latest/clap/&quot;&gt;clap&lt;/a&gt; (Rust)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.python-guide.org/scenarios/cli/&quot;&gt;Click&lt;/a&gt; (Python)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://picocli.info/picocli-2.0-groovy-scripts-on-steroids.html&quot;&gt;Picocli&lt;/a&gt; (Groovy)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/tj/commander.js&quot;&gt;Commander.js&lt;/a&gt; (JavaScript)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, why would we prefer writing a CLI in TypeScript given all these other choices?&lt;/p&gt;

&lt;p&gt;Well, TypeScript is an overall good choice for a couple of reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;compatibility&lt;/strong&gt; with JavaScript (TypeScript is a superset of—and by that token compatible with—JavaScript),&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;popularity&lt;/strong&gt; (TypeScript was ranked 7th in the &lt;a href=&quot;https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-programming-scripting-and-markup-languages&quot;&gt;2021 Stack Overflow Developer Survey&lt;/a&gt; with JavaScript being 1st),&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;tooling choice&lt;/strong&gt; (the Node.js ecosystem provides &lt;a href=&quot;https://openbase.com/categories/js/best-javascript-cli-libraries&quot;&gt;quite a lot of CLI libraries&lt;/a&gt;),&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;developer friendliness&lt;/strong&gt; (TypeScript is a scripted language but also has an advanced type system and static type checking which helps writing high-quality code),&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;performance&lt;/strong&gt; (since TypeScript code is, in the end, typically run by Node.js, it is in general sufficiently performant thanks to the &lt;a href=&quot;https://v8.dev/&quot;&gt;v8  engine&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nonetheless, a typically non-trivial part of any TypeScript project is the setup. Writing a CLI with e.g. Python and the &lt;a href=&quot;https://click.palletsprojects.com/en/8.1.x/&quot;&gt;Click&lt;/a&gt; library requires little more than writing a file with the &lt;a href=&quot;https://docs.python.org/3/library/__main__.html#packaging-considerations&quot;&gt;main function&lt;/a&gt;. This higher setup complexity is of course owed to the fact that TypeScript is a superset of JavaScript. To run TypeScript code, you typically transpile it to JavaScript and then execute the JavaScript code with Node.js. (Yes, even &lt;a href=&quot;https://github.com/TypeStrong/ts-node&quot;&gt;ts-node&lt;/a&gt; does that.) So, before running a program written in TypeScript, we need to transpile it to JavaScript first. This requires tooling and therefore setup.&lt;/p&gt;

&lt;p&gt;Preferably, we also want to have a single, packaged binary as the result of building our project, rather than a script file, to reduce installation overhead on part of the user. To assure a high level of code quality, we also typically want to include code formatting, linting, and tests.&lt;/p&gt;

&lt;h2 id=&quot;getting-started-writing-a-typescript-cli&quot;&gt;Getting started writing a TypeScript CLI&lt;/h2&gt;

&lt;p&gt;To hit the ground running, I created a starter project which already contains all required boilerplate and dependencies for running, formatting, linting, testing, and packaging the code to a standalone binary.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ℹ️ The starter project can be found on my &lt;a href=&quot;https://github.com/fkurz/typescript-cliutil-starter&quot;&gt;GitHub&lt;/a&gt; and via &lt;a href=&quot;https://www.npmjs.com/package/@fkurz/typescript-cliutil-starter/&quot;&gt;npm&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We first clone it and install dependencies.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git@github.com:fkurz/typescript-cliutil-starter.git my-cli
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;my-cli 
npm i
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Our starter project uses&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the &lt;a href=&quot;https://www.npmjs.com/package/commander&quot;&gt;&lt;em&gt;commander&lt;/em&gt;&lt;/a&gt; package for argument parsing and executing commands,&lt;/li&gt;
  &lt;li&gt;code linting and formatting with &lt;a href=&quot;https://eslint.org/&quot;&gt;eslint&lt;/a&gt; and &lt;a href=&quot;https://prettier.io/&quot;&gt;prettier&lt;/a&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://jestjs.io/&quot;&gt;Jest&lt;/a&gt; as test runner and assertion library, and&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/vercel/pkg&quot;&gt;pkg&lt;/a&gt; to build a stand-alone binary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;basic-development-flow&quot;&gt;Basic development flow&lt;/h2&gt;

&lt;p&gt;To illustrate the development flow, we now add an example subcommand &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yell&lt;/code&gt; and test it. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yell&lt;/code&gt; is similar to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;say&lt;/code&gt; command (that already exists in the project) but a bit less subtle.&lt;/p&gt;

&lt;p&gt;To do this, we add a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/yell.ts&lt;/code&gt; and then add the following code.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/yell.ts&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;commander&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;yell&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Say the word passed as the first argument but louder&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;lt;word&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toLocaleUpperCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We also have to register our yell command with the main CLI command in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/cmd.ts&lt;/code&gt;, i.e. add an import statement for our subcommand and register it using &lt;em&gt;Commander.addCommand&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/cmd.ts&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// … &lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;buildYellCmd&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./yell&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-g, --greet&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`Say &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HELLO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addCommand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;buildSayCmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addCommand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;buildYellCmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addHelpCommand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showHelpAfterError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// …&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Having done that, we can do a quick test run using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt; script defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt; script simply executes our TypeScript code with &lt;a href=&quot;https://github.com/TypeStrong/ts-node&quot;&gt;ts-node&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm run dev &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; yell &lt;span class=&quot;s1&quot;&gt;'hey!'&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; @fkurz/typescript-cliutil-starter@1.0.0 dev /private/tmp/my-cli
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ts-node src/main.ts &lt;span class=&quot;s2&quot;&gt;&quot;yell&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hey!&quot;&lt;/span&gt;

HEY!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can also add a test by adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/yell.test.ts&lt;/code&gt; with the following content&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;buildCmd&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./cmd&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;jest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;spyOn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;jest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;spyOn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Yell subcommand&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Should say 'HEY!' when passed 'hey!'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;buildCmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;yell&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hey!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;HEY!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since our Jest configuration expects JavaScript test files, we first have to transpile our code with the build script using the TypeScript compiler &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tsc&lt;/code&gt;. The transpiled JavaScript source code is put into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dist/&lt;/code&gt; folder.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm run build
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; @fkurz/typescript-cliutil-starter@1.0.0 build /private/tmp/my-cli
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; tsc &lt;span class=&quot;nt&quot;&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can now run our test suite with Jest using the test script. New test files will automatically get recognized by Jest if they have—as in our case—the suffix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.test.js*&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm run &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; @fkurz/typescript-cliutil-starter@1.0.0 &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; /private/tmp/my-cli
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; jest

...

Test Suites: 3 passed, 3 total
Tests:       8 passed, 8 total
Snapshots:   0 total
Time:        0.41 s, estimated 1 s
Ran all &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;suites.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As a final step, we can build a native binary by executing npm run package. This script will conveniently bundle all source code and dependencies into a single, stand-alone binary file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/main&lt;/code&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pkg&lt;/code&gt; tool.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm run package

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; @fkurz/typescript-cliutil-starter@1.0.0 package /private/tmp/my-cli
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; pkg dist/main.js &lt;span class=&quot;nt&quot;&gt;--no-bytecode&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--public-packages&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'*'&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--public&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt; host &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; bin/main

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; pkg@5.3.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The packaged binary is automatically made executable using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;postpackage&lt;/code&gt; script.
Packaging our CLI into a standalone binary has the major advantage that we can now simply run our CLI as a binary from the shell without a Node.js installation and without having to download any dependency whatsoever.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./bin/main yell &lt;span class=&quot;s1&quot;&gt;'hey!'&lt;/span&gt;
HEY!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;TypeScript is a good choice for writing a CLI tool due to various factors.&lt;/p&gt;

&lt;p&gt;Not only is TypeScript a developer-friendly language but it also has static checks to assure code quality and its ecosystem offers a wide range of tooling choices for command-line programs.&lt;/p&gt;

&lt;p&gt;Additionally, as shown above, developing a CLI utility written in TypeScript does not preclude the option of exporting a stand-alone, native binary if we use a tool like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pkg&lt;/code&gt; to bundle our program and dependencies into an application binary.&lt;/p&gt;

&lt;p&gt;Do you have any questions, suggestions, or comments? Get in touch with the author &lt;a href=&quot;https://aemail.com/Z4YQ&quot;&gt;via mail&lt;/a&gt;!&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-friedrich-kurz&quot;&gt;About the Author: Friedrich Kurz&lt;/h2&gt;

&lt;p&gt;Friedrich has been working for MaibornWolff as a full-time software engineer for 2.5 years. In his current project, he’s helping to build the AWS cloud infrastructure for a client’s web platform. Friedrich considers himself a technology generalist with a broad range of interests rather than a technology specialist. He’s, however, also very interested in functional programming and general methods of writing correct, clean, and maintainable code.&lt;/p&gt;</content><author><name>Friedrich Kurz</name></author><category term="typescript" /><summary type="html">There are quite a couple of technology options when it comes to writing a command-line interface (CLI) tool. Most modern languages at the very least provide some kind of out-of-the-box support for command-line argument parsing. In addition, the ecosystems of modern languages also typically contain at least one mature and feature-rich CLI library.</summary></entry><entry><title type="html">RxJS Best Practices and an Idea</title><link href="/javascript/2022/04/29/rxjs-best-practices.html" rel="alternate" type="text/html" title="RxJS Best Practices and an Idea" /><published>2022-04-29T07:00:13+00:00</published><updated>2022-04-29T07:00:13+00:00</updated><id>/javascript/2022/04/29/rxjs-best-practices</id><content type="html" xml:base="/javascript/2022/04/29/rxjs-best-practices.html">&lt;p&gt;There are some best practices in RxJS for several regular use cases.
First of all I’ll share my personal recommandations from my long time project, before we go into an idea how to improve them.&lt;/p&gt;

&lt;h2 id=&quot;clean-flow&quot;&gt;Clean flow&lt;/h2&gt;

&lt;p&gt;Nothing is more important for my colleageues and me than a clean flow of operators in a pipe block:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userName$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loginService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onLogin$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;switchMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authenticate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;tap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;navigate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;filterNotNull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// custom&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;userName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;share&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;resetOnRefCountZero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;connector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReplaySubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, is this really clean? Yes, it somehow is, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tap&lt;/code&gt; isn’t a great choice in this position, as side effects in a pipe flow should be avoided as much as possible.
What would that look like in a “bad” case?&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userName$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loginService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onLogin$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;switchMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authenticate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;tap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;navigate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])),&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;filterNotNull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// custom&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;userName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;share&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;resetOnRefCountZero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;connector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReplaySubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;“Bad” is too much of a harsh word for this example, but I hope it gives a rough overview of the problem.
&lt;strong&gt;Important&lt;/strong&gt;: in case of errors it could sometimes be necessary to nest some pipes. Keep an eye on that!&lt;/p&gt;

&lt;h2 id=&quot;custom-operators&quot;&gt;Custom operators&lt;/h2&gt;

&lt;p&gt;Have you ever seen something like this?&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;....&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dtoOrNull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dtoOrNull&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Looks familiar, right? Yes, but a simple TypeScript trick and RxJS operator can fix that.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filterNotNull&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;OperatorFunction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Exclude&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;value$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Exclude&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Why is that casting necessary? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&amp;lt;T&amp;gt;&lt;/code&gt; is a mono type operator function that mean Input = Output type.
If you see multiple combinations of operators in several pipes, you can just extract them into one custom pipe. Try it out!&lt;/p&gt;

&lt;h2 id=&quot;operatorfunctions-from-services&quot;&gt;OperatorFunctions from Services&lt;/h2&gt;

&lt;p&gt;Now, let’s move on from these known best practices to a new idea: this short sample should give a brief overview.&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Injectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FilterService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;termSubject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BehaviorSubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;currentTerm$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;termSubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;asObservable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filterFn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;matchFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MonoTypeOperatorFunction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;source$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;combineLatest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;source$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;currentTerm$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    	&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(({&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;matchFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setFilterTerm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;termSubject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;Injectable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ListService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;listItems$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apiService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listData$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filterService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filterFn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ListItem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filterService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FilterService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Basically it directly emits the observable at the point where we use the service function in our pipe, we don’t need to combine something anymore or do anything else. Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FilterService&lt;/code&gt; can be used in our filter field and every time if the component emit a new term to the service, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listItems$&lt;/code&gt; will update. many other useacses for this are conceivable.&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-nils-heinemann&quot;&gt;About the author: Nils Heinemann&lt;/h2&gt;

&lt;p&gt;Nils has more than five years of experience in software development and architecture. He specializes in frontend development with Angular and TypeScript. Nils joined MaibornWolff in 2018. If you want to work with Nils, we are looking for &lt;a href=&quot;https://www.maibornwolff.de/en/careers/job-vacancies/web-developer&quot;&gt;Web Developers&lt;/a&gt;!&lt;/p&gt;</content><author><name>Nils Heinemann</name></author><category term="javascript" /><summary type="html">There are some best practices in RxJS for several regular use cases. First of all I’ll share my personal recommandations from my long time project, before we go into an idea how to improve them.</summary></entry><entry><title type="html">Static code analysis in Node.js</title><link href="/javascript/2022/04/22/static-code-analysis.html" rel="alternate" type="text/html" title="Static code analysis in Node.js" /><published>2022-04-22T07:00:13+00:00</published><updated>2022-04-22T07:00:13+00:00</updated><id>/javascript/2022/04/22/static-code-analysis</id><content type="html" xml:base="/javascript/2022/04/22/static-code-analysis.html">&lt;p&gt;JavaScript is a very powerful language.
This has a lot of advantages, but it can also decrease the readability of your code if misused.&lt;/p&gt;

&lt;p&gt;Static code analysis can be used to detect common errors in your code and keep the style consistent 
across your team. In this article I want to share some of the tools that I can recommend.&lt;/p&gt;

&lt;h2 id=&quot;typescript&quot;&gt;Typescript&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;Typescript&lt;/a&gt; is a statically typed superset 
of JavaScript. By attaching the type information to the variables and&lt;br /&gt;
functions in your code, it helps finding errors before executing the 
code. It also boosts your productivity by improving the autocompletion of your editor.
The best thing is, most of the time Typescript can infer the type of a variable and you don’t need 
to declare it. You can even &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html&quot;&gt;check the types of a normal JavaScript project&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;prettier&quot;&gt;Prettier&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://prettier.io/&quot;&gt;Prettier&lt;/a&gt; formats your code by a very opinionated rule set.
It avoids unnecessary changes caused by different formatting in your git commits.
This is especially useful in code reviews, as you don’t get distracted by bloated diffs.&lt;/p&gt;

&lt;h2 id=&quot;eslint&quot;&gt;Eslint&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://eslint.org/&quot;&gt;Eslint&lt;/a&gt; is the de facto standard linter for JavaScript projects.
It comes with a large ruleset and is easily extendable with plugins.
I would recommend to start with the &lt;a href=&quot;https://eslint.org/docs/rules/&quot;&gt;recommended rules&lt;/a&gt; by setting 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;extends&quot;: &quot;eslint:recommended&quot;&lt;/code&gt; in the configuration and enable/disable individual rules as needed.&lt;/p&gt;

&lt;p&gt;If you want to use Eslint with Typescript, you should install and configure the &lt;a href=&quot;https://www.npmjs.com/package/@typescript-eslint/parser&quot;&gt;Typescript Eslint Parser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The following plugins might be useful to you:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/eslint-config-prettier&quot;&gt;eslint-config-prettier&lt;/a&gt;
disables all the eslint rules, that might conflict with the prettier formatting.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-import&quot;&gt;eslint-plugin-import&lt;/a&gt;
provides a set of rules to manage the imports in your project. I especially recommend
the &lt;a href=&quot;https://github.com/benmosher/eslint-plugin-import/blob/HEAD/docs/rules/order.md&quot;&gt;order&lt;/a&gt; rule,
which automatically sorts your imports. This also avoids unnecessary diffs in your pull requests.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-unused-imports&quot;&gt;eslint-plugin-unused-imports&lt;/a&gt;.
Unused imports can increase your application size and reduce readability. With this plugin you can automatically 
remove imports with no reference in your code.&lt;/li&gt;
  &lt;li&gt;The default eslint rules are great, but 
&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-unicorn&quot;&gt;eslint-plugin-unicorn&lt;/a&gt; 
adds a lot more. 
For example with the &lt;a href=&quot;https://github.com/sindresorhus/eslint-plugin-unicorn/blob/HEAD/docs/rules/prevent-abbreviations.md&quot;&gt;prevent-abbreviations&lt;/a&gt; rule,
you can ban abbreviations that might reduce clarity of you code.
I suggest that you use the recommended configuration of this plugin.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-promise&quot;&gt;eslint-plugin-promise&lt;/a&gt;.
Promises and async/await are great and really help to keep your async JavaScript code
clean. This plugin detects common pitfalls and bad practices while using Promises
and async/await.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-node&quot;&gt;eslint-plugin-node&lt;/a&gt; extends ESLint
with some Node.js specific rules. For example, it can enforce the use of the new promise
based 
&lt;a href=&quot;https://nodejs.org/dist/latest-v10.x/docs/api/fs.html#fs_fs_promises_api&quot;&gt;fs&lt;/a&gt; 
module with the 
&lt;a href=&quot;https://github.com/mysticatea/eslint-plugin-node/blob/HEAD/docs/rules/prefer-promises/fs.md&quot;&gt;node/prefer-promises/fs&lt;/a&gt; 
rules.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-json&quot;&gt;eslint-plugin-json&lt;/a&gt; includes JSON specific rules.
This is especially useful, to prevent malformatted json configurations.&lt;/li&gt;
  &lt;li&gt;Last but not least, the
&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-eslint-comments&quot;&gt;eslint-plugin-eslint-comments&lt;/a&gt;
detects the abuse of eslint escape comments like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/* eslint-disable */&lt;/code&gt;. For example
it warns you, if the exception is to general or redundant.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start with the recommended settings of each plugin and enable or disable individual rules based
on your project needs. An exception is the 
&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-import&quot;&gt;eslint-plugin-import&lt;/a&gt;.
As the individual rules are relatively slow, I would just pick the rules that 
are worth the performance impact. You can measure the performance impact of each rule
by setting the environment variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TIMING=1&lt;/code&gt; 
(&lt;a href=&quot;https://stackoverflow.com/questions/38458067/which-eslint-rules-in-my-config-are-slow&quot;&gt;source&lt;/a&gt;). 
I would also recommend setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cache&lt;/code&gt; flag of eslint to improve performance.&lt;/p&gt;

&lt;p&gt;That’s it! I hope I could help you to improve the static analysis 
of your JavaScript project. Do you think I missed something? 
Please let me know in the comments.&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-tobias-walle&quot;&gt;About the Author: Tobias Walle&lt;/h2&gt;

&lt;p&gt;Tobias works as a full-stack developer at MaibornWolff since 2016. He works regularly with several languages, including Typescript, Kotlin and Rust
and loves to deep dive into new technical topics.&lt;/p&gt;</content><author><name>Tobias Walle</name></author><category term="javascript" /><summary type="html">JavaScript is a very powerful language. This has a lot of advantages, but it can also decrease the readability of your code if misused.</summary></entry><entry><title type="html">Best Practices FP in TypeScript</title><link href="/typescript/2022/04/08/fp-with-typescript.html" rel="alternate" type="text/html" title="Best Practices FP in TypeScript" /><published>2022-04-08T09:00:13+00:00</published><updated>2022-04-08T09:00:13+00:00</updated><id>/typescript/2022/04/08/fp-with-typescript</id><content type="html" xml:base="/typescript/2022/04/08/fp-with-typescript.html">&lt;p&gt;Some of us have a background in functional programming and are now moving into a TypeScript environment.&lt;/p&gt;

&lt;p&gt;If you are part of this group, you might be wondering how much FP is possible in TypeScript.&lt;/p&gt;

&lt;p&gt;Bad news first: not as much as you might like. However, some things will work. We’ll take a look at function abstraction and currying for compose.&lt;/p&gt;

&lt;h2 id=&quot;simple-function-abstraction&quot;&gt;Simple function abstraction&lt;/h2&gt;

&lt;p&gt;Some anomynous functions can be extracted very simple:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// query dto from api and transform into ui-model&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ApiService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UiModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;?filter=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mapIntoUiModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mapIntoUiModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ResponseData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;UiModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// magic here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also Array transform functions can extract abstract to utils:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;extractValuesByKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;K&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;keyof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// usage: list.map(extractValuesByKey('prop'))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Nothing complicated here, right?&lt;/p&gt;

&lt;h2 id=&quot;currying-for-compose&quot;&gt;currying for compose&lt;/h2&gt;

&lt;p&gt;But there is more. In FP it’s sometimes a good practices to build new functions by composing. Compose is based on a simple law:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/fp_2022_08_04.png&quot; alt=&quot;Compose in FP&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In Typescript it would look like this:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ComposeFn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// g o f =&amp;gt; g(f(arg))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ComposeFn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s look at a small example now:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// sort items&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sortFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// filter items&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filterFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filterFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// items -&amp;gt; sort -&amp;gt; filter&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filterAndSort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sortFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;finalData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;filterAndSort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

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

&lt;p&gt;That Functions return functions can also be useful for other use cases, in this example with Cypress:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseApiFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;mySuite&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseUrlFn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseApiFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Cypress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;should ...&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userApi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseUrlFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/user&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;intercept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;userApi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do something&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  
  &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;should ... something other&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;authApi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseUrlFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;/token&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;intercept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authApi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do something&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;cy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;@login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We built a function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;baseApiFn&lt;/code&gt; to manage a preloaded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;baseUrl&lt;/code&gt; value and evaluate the final result on demand.&lt;/p&gt;

&lt;p&gt;In a more advanced variant of this we additionally replace path variable:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ParameterBaseUrlFn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;subPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseApiFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseUrlFnWithPathVariables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ParameterBaseUrlFn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseFn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseApiFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;subPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`{&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;}`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;baseFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;subPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is how you can use currying for compose in TypeScript.&lt;/p&gt;

&lt;h2 id=&quot;about-the-author-nils-heinemann&quot;&gt;About the author: Nils Heinemann&lt;/h2&gt;

&lt;p&gt;Nils has more than five years of experience in software development and architecture. He specializes in frontend development with Angular and TypeScript. Nils joined MaibornWolff in 2018.&lt;/p&gt;</content><author><name>Nils Heinemann</name></author><category term="typescript" /><summary type="html">Some of us have a background in functional programming and are now moving into a TypeScript environment.</summary></entry></feed>