tinytiptinytip is a collection of small tips & tricks for developers.2024-02-25T00:00:00Zhttps://tinytip.cotinytiphello@tinytip.coListen for specific keys in Angular Templates2021-06-14T00:00:00Zhttps://tinytip.co/tips/angular-event-key-modifiers/<p>Angular allows you to listen for specific keys of a keyboard event similar to <a href="https://v3.vuejs.org/guide/events.html#key-modifiers">Vue's Key Modifiers</a>. When listing for a keyboard event like <code>keydown</code> or <code>keyup</code> you can add a key or key combination that you want to listen for.</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- Listen for all keys --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">(keydown)</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onKeyDown()<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /><br /><span class="token comment"><!-- Listen for enter --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">(keydown.enter)</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onEnter()<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /><br /><span class="token comment"><!-- Listen for arrow down --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">(keydown.arrowdown)</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onArrowDown()<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><br /><br /><span class="token comment"><!-- Listen for shift + f --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">(keydown.shift.f)</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onShiftF()<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
Get the current text color with currentColor in CSS2021-06-14T00:00:00Zhttps://tinytip.co/tips/css-current-color/<p>In CSS the special variable <code>currentColor</code> gives you access to
the current text color of the element. You can use this value
in other properties like <code>border-color</code> to automatically adjust the border
to match the text color.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.button</span> <span class="token punctuation">{</span><br /> <span class="token property">border</span><span class="token punctuation">:</span> 1px solid currentColor<span class="token punctuation">;</span> <span class="token comment">/* border color is blue */</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> blue<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.button:hover</span> <span class="token punctuation">{</span><br /> <span class="token comment">/* border color automatically changes to darkblue */</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> darkblue<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
Use $0 in the browser console to get the current element2021-06-14T00:00:00Zhttps://tinytip.co/tips/devtools-console-current-element/<p>When you select an element in the Elements tab of the Browser DevTools you
can use <code>$0</code> in the Console tab to refer to that element.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Logs the selected element of the Elements tab</span><br />$0<span class="token punctuation">;</span><br /><br /><span class="token comment">// Access any property or method on that element</span><br />$0<span class="token punctuation">.</span>href<span class="token punctuation">;</span></code></pre>
Find elements in the browser console with $$2021-06-14T00:00:00Zhttps://tinytip.co/tips/devtools-console-query-selector/<p>Use <code>$$(...)</code> in the Console tab of the DevTools to query elements.
It's a quick way for using <code>querySelectorAll</code>.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Find all "a" elements</span><br /><span class="token function">$$</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Find all div elements with "container" in the class attribute</span><br /><span class="token function">$$</span><span class="token punctuation">(</span><span class="token string">"div[class*='container']"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
Copy text in the browser console with the copy() function2021-06-14T00:00:00Zhttps://tinytip.co/tips/devtools-copy-text/<p>The DevTools provide a global <code>copy()</code> function.
Use that function in the Console tab to copy any content into your clipboard.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Copy some static text into the clipboard</span><br /><span class="token function">copy</span><span class="token punctuation">(</span><span class="token string">"hello world"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Copy the page title</span><br /><span class="token function">copy</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span>title<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Copy some content from localStorage</span><br /><span class="token function">copy</span><span class="token punctuation">(</span>localStorage<span class="token punctuation">.</span><span class="token function">getItem</span><span class="token punctuation">(</span><span class="token string">"test"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
Restart TypeScript server in VS Code with a command2021-06-14T00:00:00Zhttps://tinytip.co/tips/vscode-restart-ts/<p>Sometimes the TypeScript server in Visual Studio Code crashes
which results in broken auto completion. You can restart the server with a single command.</p>
<p>Make sure that you have a TypeScript file open, press <code>Ctrl+Shift+P</code> (or <code>Cmd+Shift+P</code> on macOS) to open the Command Palette and type <code>restart</code>, then select the command "TypeScript: Restart TS server".</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/fHg1vwqcqu-300.webp 300w, https://tinytip.co/assets/img/fHg1vwqcqu-736.webp 736w, https://tinytip.co/assets/img/fHg1vwqcqu-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/fHg1vwqcqu-300.jpeg 300w, https://tinytip.co/assets/img/fHg1vwqcqu-736.jpeg 736w, https://tinytip.co/assets/img/fHg1vwqcqu-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Restart TS server command in VS Code" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/fHg1vwqcqu-300.jpeg" width="1472" height="989" /></picture></p>
<p>The status bar at the bottom of the window will show the status of the server.</p>
Navigate easier in large files via symbols in VS Code2021-06-14T00:00:00Zhttps://tinytip.co/tips/vscode-symbol-navigation/<p>When you open a file in VS Code and you look for a specific function, class, ... you can navigate by symbols. Press <code>Ctrl+Shift+O</code> (or <code>Cmd+Shift+O</code> on macOS) to see all symbols of the current file. You can filter the list and navigate through the results with arrow down / arrow up. VS Code will automatically scroll to the focused element. Press <code>esc</code> to close the list (and navigate back to the original scroll position) or <code>enter</code> to focus that symbol.</p>
<p>This works for many different languages like JavaScript, TypeScript and even headings in Markdown.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/uc0cOHeK9u-300.webp 300w, https://tinytip.co/assets/img/uc0cOHeK9u-736.webp 736w, https://tinytip.co/assets/img/uc0cOHeK9u-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/uc0cOHeK9u-300.jpeg 300w, https://tinytip.co/assets/img/uc0cOHeK9u-736.jpeg 736w, https://tinytip.co/assets/img/uc0cOHeK9u-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Symbol Search in VS Code" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/uc0cOHeK9u-300.jpeg" width="1472" height="1034" /></picture></p>
Emulate a focused page in DevTools to debug overlay elements2021-06-17T00:00:00Zhttps://tinytip.co/tips/devtools-focused-page/<p>Some overlay elements like dropdowns or flyout menus automatically hide/remove themselves when
the focus is lost. Whenever you switch to the DevTools the page is not focused anymore and the
element gets hidden.</p>
<p>The Chrome DevTools have a feature to emulate page focus. Open the DevTools, press <code>Ctrl+Shift+P</code> (or
<code>Cmd+Shift+P</code> on macOS) and search for "Emulate a focused page".</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/t5uACyUN_x-300.webp 300w, https://tinytip.co/assets/img/t5uACyUN_x-736.webp 736w, https://tinytip.co/assets/img/t5uACyUN_x-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/t5uACyUN_x-300.jpeg 300w, https://tinytip.co/assets/img/t5uACyUN_x-736.jpeg 736w, https://tinytip.co/assets/img/t5uACyUN_x-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Emulate a focused page in DevTools" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/t5uACyUN_x-300.jpeg" width="1472" height="303" /></picture></p>
Find files by name on GitHub2021-06-17T00:00:00Zhttps://tinytip.co/tips/github-file-finder/<p>Open a repository on GitHub and press <code>t</code> to open the File Finder.
This let's you find files by name (or name of the directory) in the current repo.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/OUN-nxUNel-300.webp 300w, https://tinytip.co/assets/img/OUN-nxUNel-736.webp 736w, https://tinytip.co/assets/img/OUN-nxUNel-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/OUN-nxUNel-300.jpeg 300w, https://tinytip.co/assets/img/OUN-nxUNel-736.jpeg 736w, https://tinytip.co/assets/img/OUN-nxUNel-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="File Finder on GitHub" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/OUN-nxUNel-300.jpeg" width="1472" height="564" /></picture></p>
Open GitHub repositories in VS Code directly in your browser2021-06-17T00:00:00Zhttps://tinytip.co/tips/github-repo-in-code/<p>You can view any public GitHub repository in VS Code directly in your browser.
Just open the repository on GitHub in your browser and change the domain to <code>github1s.com</code>.</p>
<p>This will open a readonly VS Code instance directly in your browser.</p>
<p>Example: <a href="https://github1s.com/facebook/react/">github1s.com/facebook/react/</a></p>
Insert multiple HTML elements at once with DocumentFragment2021-06-19T00:00:00Zhttps://tinytip.co/tips/js-document-fragment/<p>When you need to create multiple HTML elements and insert them into the DOM, you can use a document fragment. A document fragment allows you to assemble all elements and insert them all at once.
That is more efficient than adding them one by one.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Create a new fragment</span><br /><span class="token keyword">const</span> fragment <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createDocumentFragment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">const</span> item1 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />item1<span class="token punctuation">.</span>innerText <span class="token operator">=</span> <span class="token string">"item 1"</span><span class="token punctuation">;</span><br />fragment<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>item1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Append a child</span><br /><br /><span class="token keyword">const</span> item2 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />item2<span class="token punctuation">.</span>innerText <span class="token operator">=</span> <span class="token string">"item 2"</span><span class="token punctuation">;</span><br />fragment<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>item2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Append another child</span><br /><br /><span class="token comment">// Append all child to the document</span><br /><span class="token comment">// The document fragment will not be part of the DOM</span><br />document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>fragment<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// The document fragment is now empty</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fragment<span class="token punctuation">.</span>childElementCount<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// logs 0</span></code></pre>
Separate large numbers in TypeScript with underscore2021-06-19T00:00:00Zhttps://tinytip.co/tips/ts-number-underscore-separator/<p>In TypeScript numbers can be separated using underscore.
This improves the readability of large numbers.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token comment">// Bad, hard to read. How many zeros are there?</span><br /><span class="token keyword">const</span> <span class="token constant">MAGIC_NUMBER</span> <span class="token operator">=</span> <span class="token number">1000000</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Good</span><br /><span class="token keyword">const</span> <span class="token constant">MAGIC_NUMBER</span> <span class="token operator">=</span> <span class="token number">100_000</span><span class="token punctuation">;</span></code></pre>
Assert that all possible cases in a switch statement are handled2021-06-19T00:00:00Zhttps://tinytip.co/tips/ts-switch-assert-unreachable/<p>Let's say you have a <code>switch</code> statement that handles all values of an enum (or some other type with a limited number of possible values). When you extend that enum sometime in the future you may forget to add a new case to the statement.</p>
<p>With TypeScript you can use an <code>assertUnreachable()</code> function to ensure that all possible cases are handled:</p>
<pre class="language-typescript"><code class="language-typescript"><span class="highlight-line"><span class="token keyword">function</span> <span class="token function">myFunction</span><span class="token punctuation">(</span>value<span class="token operator">:</span> SomeEnum<span class="token punctuation">)</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token keyword">switch</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token keyword">case</span> SomeEnum<span class="token punctuation">.</span><span class="token constant">ONE</span><span class="token operator">:</span></span><br /><span class="highlight-line"> <span class="token comment">// ...</span></span><br /><span class="highlight-line"> <span class="token keyword">break</span><span class="token punctuation">;</span></span><br /><span class="highlight-line"></span><br /><span class="highlight-line"> <span class="token keyword">case</span> SomeEnum<span class="token punctuation">.</span><span class="token constant">TWO</span><span class="token operator">:</span></span><br /><span class="highlight-line"> <span class="token comment">// ...</span></span><br /><span class="highlight-line"> <span class="token keyword">break</span><span class="token punctuation">;</span></span><br /><span class="highlight-line"></span><br /><span class="highlight-line"> <span class="token keyword">default</span><span class="token operator">:</span></span><br /><span class="highlight-line"> <span class="token comment">// Ensures that all cases are handled</span></span><br /><mark class="highlight-line highlight-line-active"> <span class="token function">assertUnreachable</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span></mark><br /><span class="highlight-line"> <span class="token punctuation">}</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>The <code>assertUnreachable()</code> function works by defining an argument of type <code>never</code>:</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">function</span> <span class="token function">assertUnreachable</span><span class="token punctuation">(</span>_value<span class="token operator">:</span> <span class="token builtin">never</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">never</span> <span class="token punctuation">{</span><br /> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">"Statement should be unreachable"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>When you now extend the enum TypeScript will show an error:</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/WXeQyddLWW-300.webp 300w, https://tinytip.co/assets/img/WXeQyddLWW-736.webp 736w, https://tinytip.co/assets/img/WXeQyddLWW-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/WXeQyddLWW-300.jpeg 300w, https://tinytip.co/assets/img/WXeQyddLWW-736.jpeg 736w, https://tinytip.co/assets/img/WXeQyddLWW-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="TypeScript Error for unhandled cases" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/WXeQyddLWW-300.jpeg" width="1472" height="686" /></picture></p>
Generate code with Emmet in VS Code2021-06-19T00:00:00Zhttps://tinytip.co/tips/vscode-emmet-abbreviations/<p>Emmet let's you generate code by writing CSS-like expressions.
Write a small expression, press tab and it will generate the output for you.
VS Code supports Emmet out of the box.</p>
<p>Here is an example that generates a submit button with id <code>submit</code>, class <code>primary</code> and the content "Submit" as shown in the preview tooltip.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/IWryYRZvv2-300.webp 300w, https://tinytip.co/assets/img/IWryYRZvv2-736.webp 736w, https://tinytip.co/assets/img/IWryYRZvv2-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/IWryYRZvv2-300.jpeg 300w, https://tinytip.co/assets/img/IWryYRZvv2-736.jpeg 736w, https://tinytip.co/assets/img/IWryYRZvv2-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Example of using Emmet in VS Code" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/IWryYRZvv2-300.jpeg" width="1472" height="993" /></picture></p>
<p>Here is another example:</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- Expression --></span><br />ul.list>li.item*5<br /><br /><span class="token comment"><!-- Output --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>item<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre>
<p>See the official <a href="https://docs.emmet.io/cheat-sheet/">cheat sheet</a> for more information.</p>
Generate strings with brace expansion2021-06-20T00:00:00Zhttps://tinytip.co/tips/bash-brace-expansion/<p>Brace expansion lets you generate arbitrary strings in your terminal.
Place a comma-separated list of items in curly braces <code>{}</code> and add prefix and/or suffix.
It will repeat the prefix / suffix for every item in the list.</p>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># Deletes image-01.png, image-17.png and image-42.png</span><br />$ <span class="token function">rm</span> image-<span class="token punctuation">{</span>01,17,42<span class="token punctuation">}</span>.png<br /><br /><br /><span class="token comment"># "Hello " must be in quotes because it ends with a white space</span><br /><span class="token comment"># Without quotes it would generate "Hello World everyone"</span><br />$ <span class="token builtin class-name">echo</span> <span class="token string">"Hello "</span><span class="token punctuation">{</span>World,everyone<span class="token punctuation">}</span><br />Hello World Hello Everyone<br /><br /><br /><span class="token comment"># Installs @radix-ui/react-accordion, @radix-ui/react-checkbox</span><br /><span class="token comment"># and @radix-ui/react-switch</span><br /><span class="token function">npm</span> i @radix-ui/<span class="token punctuation">{</span>react-accordion,react-checkbox,react-switch<span class="token punctuation">}</span></code></pre>
Amend the previous commit and keep the commit message2021-06-20T00:00:00Zhttps://tinytip.co/tips/git-amend-commit/<p>Did you just commit some changes and forget to delete that <code>console.log('test')</code> statement?
Use <code>git commit</code> with <code>--amend</code> to edit the previous commit and <code>--no-edit</code> to keep the previous commit message.</p>
<pre class="language-bash"><code class="language-bash"><span class="highlight-line"><span class="token comment"># 1. Delete the console.log</span></span><br /><span class="highlight-line"></span><br /><span class="highlight-line"><span class="token comment"># 2. Stage the changes</span></span><br /><span class="highlight-line"><span class="token function">git</span> <span class="token function">add</span> my-file.js</span><br /><span class="highlight-line"></span><br /><span class="highlight-line"><span class="token comment"># 3. Commit by updating the previous commit</span></span><br /><mark class="highlight-line highlight-line-active"><span class="token function">git</span> commit <span class="token parameter variable">--amend</span> --no-edit</mark></code></pre>
<p>Do this for local commits only. Don't amend commits that you already pushed.</p>
Style console log outputs in JavaScript2021-06-20T00:00:00Zhttps://tinytip.co/tips/js-console-styles/<p>Console Log statements can be styled with a limited set of CSS features.
Insert <code>%c</code> in your log message add an additional parameter with the style.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Logs "hello world" in red letters</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"%chello world"</span><span class="token punctuation">,</span> <span class="token string">"color:red"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Use multiple "%c" and multiple style arguments</span><br /><span class="token comment">// Logs "hello world" and "hello" is red</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"%chello %cworld"</span><span class="token punctuation">,</span> <span class="token string">"color:red"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// "hello" is italic and "world" has a red border and red text color</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><br /> <span class="token string">"%chello %cworld"</span><span class="token punctuation">,</span><br /> <span class="token string">"font-style:italic"</span> <span class="token comment">/* styles for "hello" */</span><span class="token punctuation">,</span><br /> <span class="token string">"border:1px solid red;color:red"</span> <span class="token comment">/* styles for "world" */</span><br /><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Here is how it looks like on your browser console:</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/CKNbSd11AX-300.webp 300w, https://tinytip.co/assets/img/CKNbSd11AX-736.webp 736w, https://tinytip.co/assets/img/CKNbSd11AX-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/CKNbSd11AX-300.jpeg 300w, https://tinytip.co/assets/img/CKNbSd11AX-736.jpeg 736w, https://tinytip.co/assets/img/CKNbSd11AX-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Styled color logs in the browser console" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/CKNbSd11AX-300.jpeg" width="1472" height="536" /></picture></p>
Define an array with a min length in TypeScript2021-06-20T00:00:00Zhttps://tinytip.co/tips/ts-array-min-length/<p>You can create an array type with a min length in TypeScript by using the rest syntax.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token comment">// Type requires at least one element</span><br /><span class="token keyword">type</span> <span class="token class-name">NonEmptyArray<span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span></span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token constant">T</span><span class="token punctuation">,</span> <span class="token operator">...</span><span class="token constant">T</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Type requires at least three elements</span><br /><span class="token keyword">type</span> <span class="token class-name">ThreeOreMoreArray</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token constant">T</span><span class="token punctuation">,</span> <span class="token constant">T</span><span class="token punctuation">,</span> <span class="token constant">T</span><span class="token punctuation">,</span> <span class="token operator">...</span><span class="token constant">T</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p>You can now use the type and TypeScript ensures that the array meets the minimum length:</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">function</span> <span class="token function">example</span><span class="token punctuation">(</span>items<span class="token operator">:</span> NonEmptyArray<span class="token operator"><</span><span class="token builtin">string</span><span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /><br /><span class="token comment">// Error: Source has 0 element(s) but target requires 1.</span><br /><span class="token function">example</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Works</span><br /><span class="token function">example</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">"one"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token function">example</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">"one"</span><span class="token punctuation">,</span> <span class="token string">"two"</span><span class="token punctuation">,</span> <span class="token string">"three"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
TypeScript supports arrays with the rest syntax at the beginning2021-06-20T00:00:00Zhttps://tinytip.co/tips/ts-rest-array/<p>A rest parameter in a JavaScript function must be the last parameter of the list:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Does not work</span><br /><span class="token keyword">function</span> <span class="token function">example</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>arg<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /><br /><span class="token comment">// Works</span><br /><span class="token keyword">function</span> <span class="token function">example</span><span class="token punctuation">(</span><span class="token parameter">value<span class="token punctuation">,</span> <span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></code></pre>
<p>However, you can use the rest syntax for an array type in TypeScript at any position.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token comment">// Expect a list of strings and one number as last parameter</span><br /><span class="token keyword">function</span> <span class="token function">example</span><span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token builtin">number</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /><br /><span class="token comment">// It can also be in the middle of an array</span><br /><span class="token keyword">type</span> <span class="token class-name">Example</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token builtin">boolean</span><span class="token punctuation">,</span> <span class="token operator">...</span><span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token builtin">number</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
Reuse the last git commit message in VS Code2021-06-27T00:00:00Zhttps://tinytip.co/tips/vscode-source-control-last-commit-msg/<p>When you add a new git commit in VS Code you can press <code>Arrow Up</code> in the commit message input to get the previous commit message. Press it several times to get older commit messages.</p>
<p><img src="https://tinytip.co/assets/img/vscode-source-control-last-commit-msg.gif" alt="Demo of how to get the previous commit message in VS Code" /></p>
<p>Note: this only works for changes committed with the source control panel in VS Code. It will not show commits from external tools like SourceTree or the terminal.</p>
Edit any website in design mode2021-07-03T00:00:00Zhttps://tinytip.co/tips/js-designmode/<p>The <em>design mode</em> lets you edit the content of any website directly inline in a WYSIWYG-like fashion. The modifications are locally only but still useful if you
want to test something. Keyboard shortcuts like <code>Ctrl+B</code> for bold are supported.</p>
<p>The design mode can be enabled with one line of JavaScript:</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Enable</span><br />document<span class="token punctuation">.</span>designMode <span class="token operator">=</span> <span class="token string">"on"</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Disable</span><br />document<span class="token punctuation">.</span>designMode <span class="token operator">=</span> <span class="token string">"off"</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Toggle</span><br />document<span class="token punctuation">.</span>designMode <span class="token operator">=</span> document<span class="token punctuation">.</span>designMode <span class="token operator">==</span> <span class="token string">"on"</span> <span class="token operator">?</span> <span class="token string">"off"</span> <span class="token operator">:</span> <span class="token string">"on"</span><span class="token punctuation">;</span></code></pre>
Unsubscribe multiple RxJS subscriptions with Subscription.add()2021-07-03T00:00:00Zhttps://tinytip.co/tips/rxjs-subscription-add/<p>The <code>Subscription</code> class in <a href="https://rxjs.dev/">RxJS</a> has an <code>add()</code> method that let's you add subscriptions. All added subscriptions will be unsubscribed when you call <code>unsubscribe()</code> on the root subscription.</p>
<p>This lets you clean up multiple subscriptions with one command.</p>
<!-- prettier-ignore -->
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Create a new subscription</span><br /><span class="token keyword">const</span> subscription <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Subscription</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Subscribe to some observables</span><br /><span class="token comment">// and add them to the subscription</span><br />subscription<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>one$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />subscription<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>two$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />subscription<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>three$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// During clean up</span><br /><span class="token comment">// This unsubscribes the subscription of one$, two$ and three$</span><br />subscription<span class="token punctuation">.</span><span class="token function">unsubscribe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
Enable Screencast Mode in VS Code2021-07-03T00:00:00Zhttps://tinytip.co/tips/vscode-screencast-mode/<p>Visual Studio Code has an integrated Screencast Mode. This can be useful when sharing your screen
or making videos. Press <code>Ctrl+Shift+P</code> (or <code>Cmd+ShiftP</code> on macOS) to open the command palette, search for "Screencast" and select the <code>Developer: Toggle Screencast Mode</code> command.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/DWPuxxOEVZ-300.webp 300w, https://tinytip.co/assets/img/DWPuxxOEVZ-736.webp 736w, https://tinytip.co/assets/img/DWPuxxOEVZ-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/DWPuxxOEVZ-300.jpeg 300w, https://tinytip.co/assets/img/DWPuxxOEVZ-736.jpeg 736w, https://tinytip.co/assets/img/DWPuxxOEVZ-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Toggle Screencast Mode in VS Code" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/DWPuxxOEVZ-300.jpeg" width="1472" height="985" /></picture></p>
<p>Screencast Mode shows whenever you click with the mouse (a red circle appears) or press a key.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/IVgFc-3eAA-300.webp 300w, https://tinytip.co/assets/img/IVgFc-3eAA-736.webp 736w, https://tinytip.co/assets/img/IVgFc-3eAA-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/IVgFc-3eAA-300.jpeg 300w, https://tinytip.co/assets/img/IVgFc-3eAA-736.jpeg 736w, https://tinytip.co/assets/img/IVgFc-3eAA-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Toggle Screencast Mode in VS Code" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/IVgFc-3eAA-300.jpeg" width="1472" height="985" /></picture></p>
<p>The appearance of these elements can be customized in the settings.
If you want to show only keyboard shortcuts and not all keys, you can configure the following property:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><br /> <span class="token property">"screencastMode.onlyKeyboardShortcuts"</span><span class="token operator">:</span> <span class="token boolean">true</span><br /><span class="token punctuation">}</span></code></pre>
Enable smooth scrolling with scroll-behavior in CSS2021-07-28T00:00:00Zhttps://tinytip.co/tips/css-smooth-scrolling/<p>You can change the scroll behavior of your page (or an element) with the
<code>scroll-behavior</code> property. Using <code>smooth</code> will enable animated scrolling when
the user clicks on an anchor link on your page. Normal scrolling by the user is not affected by this property.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">html</span> <span class="token punctuation">{</span><br /> <span class="token property">scroll-behavior</span><span class="token punctuation">:</span> smooth<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
Check if a string is a valid enum value in TypeScript2021-07-29T00:00:00Zhttps://tinytip.co/tips/typescript-enum-validation/<p>Let's say you have an enum <code>Animal</code> and a string value and you want to check if the value is an animal.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">enum</span> Animal <span class="token punctuation">{</span><br /> Cat <span class="token operator">=</span> <span class="token string">"cat"</span><span class="token punctuation">,</span><br /> Dog <span class="token operator">=</span> <span class="token string">"dog"</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><br /><br /><span class="token keyword">const</span> someInputValue <span class="token operator">=</span> <span class="token string">"cat"</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// TS compiler will show an error,</span><br /><span class="token comment">// because "cat" is not assignable to Animal.</span><br /><span class="token comment">// We need to check if `someInputValue` is an animal.</span><br /><span class="token function">someFunctionThatExpectsAnAnimal</span><span class="token punctuation">(</span>someInputValue<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>TypeScript supports type guards and type predicates that lets you do this. The function <code>isAnimal</code> accepts a string value and returns a boolean whether the value is a valid animal or not.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">function</span> <span class="token function">isAnimal</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> value <span class="token keyword">is</span> Animal <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> Object<span class="token punctuation">.</span><span class="token generic-function"><span class="token function">values</span><span class="token generic class-name"><span class="token operator"><</span><span class="token builtin">string</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>Animal<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>If the function returns <code>true</code>, TypeScript knows that the value is an <code>Animal</code> and infers that type inside the <code>if</code> statement. You don't need to write <code>as Animal</code>.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isAnimal</span><span class="token punctuation">(</span>someInputValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// TypeScript knows that `someInputValue` is of type `Animal`</span><br /> <span class="token function">someFunctionThatExpectsAnAnimal</span><span class="token punctuation">(</span>someInputValue<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
Create a string type in a specific format in TypeScript2021-07-29T00:00:00Zhttps://tinytip.co/tips/typescript-template-string-types/<p>TypeScript supports template string types that lets you create string types in a specific format. Here are a few examples:</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">Locale</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>string<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>string<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> locale<span class="token operator">:</span> Locale <span class="token operator">=</span> <span class="token string">"en-US"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">type</span> <span class="token class-name">Url</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>string<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> url<span class="token operator">:</span> Url <span class="token operator">=</span> <span class="token string">"https://tinytip.co"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">type</span> <span class="token class-name">CssCustomProp</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">var(--</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>string<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> cssCustomProp<span class="token operator">:</span> CssCustomProp <span class="token operator">=</span> <span class="token string">"var(--color-primary)"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">type</span> <span class="token class-name">CurrencySymbol</span> <span class="token operator">=</span> <span class="token string">"€"</span> <span class="token operator">|</span> <span class="token string">"$"</span> <span class="token operator">|</span> <span class="token string">"£"</span> <span class="token operator">|</span> <span class="token string">"¥"</span><span class="token punctuation">;</span><br /><span class="token keyword">type</span> <span class="token class-name">AmountWithCurrency</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>CurrencySymbol<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>number<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> bankBalance<span class="token operator">:</span> AmountWithCurrency <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">$ 42</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre>
Function parameters can have default values based on other parameters2021-08-15T00:00:00Zhttps://tinytip.co/tips/js-params-default-values/<p>A function with parameters can have default values that are used when the caller
does not provide a value for that parameter (by omitting the parameter or providing <code>undefined</code>). The default value does not have to be a static value. You can run JavaScript and use previous parameters of that function.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// "timestamp" has a dynamic default value</span><br /><span class="token keyword">function</span> <span class="token function">logMessage</span><span class="token punctuation">(</span><span class="token parameter">message<span class="token punctuation">,</span> timestamp <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /><span class="token punctuation">}</span></code></pre>
<pre class="language-javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">someFunction</span><span class="token punctuation">(</span><br /> value<span class="token punctuation">,</span><br /> max <span class="token operator">=</span> value<span class="token punctuation">.</span>length<span class="token punctuation">,</span><br /> suffix <span class="token operator">=</span> value<span class="token punctuation">.</span>length <span class="token operator">></span> max <span class="token operator">?</span> <span class="token string">"..."</span> <span class="token operator">:</span> <span class="token string">""</span><br /><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /><span class="token punctuation">}</span><br /><br /><span class="token function">someFunction</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span> <span class="token comment">// max = 5, suffix = ""</span><br /><span class="token function">someFunction</span><span class="token punctuation">(</span><span class="token string">"hello"</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment">// max = 2, suffix = "..."</span><br /><span class="token function">someFunction</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">,</span> <span class="token keyword">undefined</span><span class="token punctuation">,</span> <span class="token string">"....."</span><span class="token punctuation">)</span> <span class="token comment">// max = 5, suffix = "....."</span></code></pre>
setTimeout accepts arguments for the function2021-08-15T00:00:00Zhttps://tinytip.co/tips/js-timeout-args/<p>The <code>setTimeout</code> function accepts optional arguments that are passed to the provided function. This way you can pass arguments without wrapping the actual function in another function.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Instead of this...</span><br /><span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">search</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">,</span> <span class="token string">"world"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// ... you can do this</span><br /><span class="token function">setTimeout</span><span class="token punctuation">(</span>search<span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">,</span> <span class="token string">"hello"</span><span class="token punctuation">,</span> <span class="token string">"world"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
Configure default branch name in Git2021-09-04T00:00:00Zhttps://tinytip.co/tips/git-branch-default-name/<p>A newly created Git repo (<code>git init</code>) has a default branch with the name <code>master</code>.
You can configure that name for all new repositories with the following command:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> config <span class="token parameter variable">--global</span> init.defaultBranch main</code></pre>
<p>Now every new Git repository will automatically create a branch <code>main</code> instead of <code>master</code>.</p>
Create an array with the map function of Array.from2021-09-04T00:00:00Zhttps://tinytip.co/tips/js-array-init-with-fn/<p>The <code>Array.from</code> function has a second parameter that lets you map each item to a new value.</p>
<p>The first argument of the map function is the current value or <code>undefined</code> if you don't have an existing list (as in the example below). The second argument is the index.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> items <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">length</span><span class="token operator">:</span> <span class="token number">5</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">value<span class="token punctuation">,</span> idx</span><span class="token punctuation">)</span> <span class="token operator">=></span> idx <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>items<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [1, 2, 3, 4, 5]</span></code></pre>
CSS has a turn unit to rotate elements2021-09-18T00:00:00Zhttps://tinytip.co/tips/css-rotate-turn/<p>The <code>rotate</code> function of the CSS <code>transform</code> property supports the <code>turn</code> unit.
This can be used as an alternative to <code>deg</code>. 360 degrees correspond to 1 turn.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.element</span> <span class="token punctuation">{</span><br /> <span class="token comment">/* Instead of degrees ... */</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span>90deg<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token comment">/* ... you can use turn */</span><br /> <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">rotate</span><span class="token punctuation">(</span>0.25turn<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Let's see it in action:</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/g-Vu_3QtgH-300.webp 300w, https://tinytip.co/assets/img/g-Vu_3QtgH-736.webp 736w, https://tinytip.co/assets/img/g-Vu_3QtgH-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/g-Vu_3QtgH-300.jpeg 300w, https://tinytip.co/assets/img/g-Vu_3QtgH-736.jpeg 736w, https://tinytip.co/assets/img/g-Vu_3QtgH-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Demo of rotated elements in CSS" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/g-Vu_3QtgH-300.jpeg" width="1472" height="335" /></picture></p>
Alpine.js accepts a custom prefix for directives2021-09-21T00:00:00Zhttps://tinytip.co/tips/alpine-prefix/<p>Alpine.js uses the <code>x-</code> prefix for directives by default (e.g. <code>x-if</code>).
This prefix can be customized using <code>Alpine.prefix()</code>.</p>
<pre class="language-js"><code class="language-js">Alpine<span class="token punctuation">.</span><span class="token function">prefix</span><span class="token punctuation">(</span><span class="token string">"xyz-"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Define your custom prefix</span><br />Alpine<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- Use your custom prefix for all directives --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span> <span class="token attr-name">xyz-if</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name"><span class="token namespace">xyz-bind:</span>href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user.profileUrl<span class="token punctuation">"</span></span> <span class="token attr-name">xyz-text</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>user.name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span></code></pre>
<p>This can be useful to prevent clashes when integrating Alpine into existing apps / markup or to get valid HTML markup that passes the <a href="https://validator.w3.org/">W3C validator</a> by using <code>data-x-</code> as prefix.</p>
The CSS list-style property affects screen readers2021-10-09T00:00:00Zhttps://tinytip.co/tips/a11y-html-list-role/<p>If you have a <code>ul</code> element in your HTML and you set <code>list-style: none</code> via CSS (via inline styles, a style tag or an external stylesheet),
your list will <strong>not</strong> be announced as a list anymore with VoiceOver + Safari on macOS.</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- VoiceOver + Safari will not announce this as a list --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">list-style</span><span class="token punctuation">:</span>none</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre>
<p>Add the <code>role</code> attribute to the <code>ul</code> element to fix this behavior.</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- VoiceOver + Safari will now announce the list --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>list<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">list-style</span><span class="token punctuation">:</span>none</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre>
Style Angular Components based on their context2021-10-09T00:00:00Zhttps://tinytip.co/tips/angular-host-context/<p>The Angular <code>:host-context()</code> selector allows you to style your component based on some conditions outside the component - for example based on a class set on the body element - without the need to set view encapsulation to <code>none</code>.</p>
<p>The selector will look for a matching element in any ancestor of your component up to the document root.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:host-context(.dark-theme) .my-component</span> <span class="token punctuation">{</span><br /> <span class="token comment">/* Styles are applied when there is a <br /> "dark-theme" class on any ancestor */</span><br /><span class="token punctuation">}</span></code></pre>
<p>This is not limited to CSS class selectors but works with any valid CSS selector.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:host-context([theme="dark"]) .my-component</span> <span class="token punctuation">{</span><br /> <span class="token comment">/* Styles are applied when there is an ancestor<br /> that has an attribute theme="dark" */</span><br /><span class="token punctuation">}</span></code></pre>
How to use Array.map() with objects2021-10-09T00:00:00Zhttps://tinytip.co/tips/js-object-from-entries/<p>The <code>Array.map()</code> function allows to to map each value of an array to a new value.
If you want to map an object - its keys, values or both - you can use <code>Object.entries()</code> and <code>Object.fromEntries()</code> to convert the object to an array and back to an object.</p>
<p>The <code>Object.entries()</code> function expects an object and returns an array with key-value pairs in the form of an array <code>[key, value]</code>. Then you can use <code>Array.map()</code> to map the keys and/or values.</p>
<p>The transformed array can be converted back to an object by using <code>Object.fromEntries()</code>.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// 1. Create an object</span><br /><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token literal-property property">one</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token literal-property property">two</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token literal-property property">three</span><span class="token operator">:</span> <span class="token number">3</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// 2. Convert the object to an array of key-value pairs</span><br /><span class="token keyword">const</span> entries <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">entries</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// [ ["one", 1], ["two", 2], ["three", 3] ]</span><br /><br /><span class="token comment">// 3. Map the array to new keys or values</span><br /><span class="token keyword">const</span> transformed <span class="token operator">=</span> entries<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">[</span>key<span class="token punctuation">,</span> value<span class="token punctuation">]</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// Change the value to a string and add leading zeros</span><br /> <span class="token keyword">return</span> <span class="token punctuation">[</span>key<span class="token punctuation">,</span> value<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">padStart</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token string">"0"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// 4. Convert the transformed array back to an object</span><br /><span class="token keyword">const</span> finalResult <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">fromEntries</span><span class="token punctuation">(</span>transformed<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// { one: "001", two: "002", three: "003" }</span></code></pre>
Angular HttpClient accepts query params as object2021-11-17T00:00:00Zhttps://tinytip.co/tips/angular-http-params/<p>When making an HTTP request with query params in Angular using the <code>HttpClient</code> you don't need to compose the URL by yourself. Instead, you can pass the params as an object or an <code>HttpParams</code> instance.</p>
<pre class="language-js"><code class="language-js"> <span class="token comment">// Instead of passing query params as part of the URL...</span><br /><span class="token keyword">function</span> <span class="token function">fetchSomeData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>httpClient<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/my/endpoint?id=2'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// ... you can pass them as object</span><br /><span class="token keyword">function</span> <span class="token function">fetchSomeData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">id</span><span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>httpClient<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/my/endpoint'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> params <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// ... or HttpParams</span><br /><span class="token keyword">function</span> <span class="token function">fetchSomeData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> params <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HttpParams</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'id'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>httpClient<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/my/endpoint'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> params <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
Map an RxJS stream to a static value with the mapTo operator2021-11-17T00:00:00Zhttps://tinytip.co/tips/rxjs-mapto/<p>The RxJS operator <code>map</code> can be used to map the stream value to a new value.
However, if you want to map to a static value that does not depend on the stream value,
you can use the <code>mapTo</code> operator. This operator accepts the value directly and you don't need to create an additional function.</p>
<pre class="language-javascript"><code class="language-javascript"><span class="token comment">// Use `map` for dynamic values</span><br />stream$<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">user</span><span class="token punctuation">)</span> <span class="token operator">=></span> user<span class="token punctuation">.</span>isAdmin<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Use `mapTo` for static values</span><br />stream$<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">mapTo</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>Note</strong>: the <code>mapTo</code> operator has been deprecated in RxJS 7 and will be removed in RxJS 8. It's better to use <code>map</code> with a function that returns the static value.</p>
Move VS Code Side Bar to the right2021-11-17T00:00:00Zhttps://tinytip.co/tips/vscode-sidebar-position/<p>Visual Studio Code shows the side bar on the left side by default.
However, you can move it to the right if you want. Just right-click on the side bar and choose "Move Side Bar Right".</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/-MEiD1Fnf7-300.webp 300w, https://tinytip.co/assets/img/-MEiD1Fnf7-736.webp 736w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/-MEiD1Fnf7-300.jpeg 300w, https://tinytip.co/assets/img/-MEiD1Fnf7-736.jpeg 736w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Change the side bar position via context action" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/-MEiD1Fnf7-300.jpeg" width="736" height="663" /></picture></p>
<p>When collapsing / expanding the side bar your code does not jump anymore when the side bar is on the right side.
This helps a lot if you toggle the side bar very often.</p>
Observe values in Browser DevTools with Live Expressions2021-12-19T00:00:00Zhttps://tinytip.co/tips/devtools-live-expression/<p><em>Live Expressions</em> allow you to observe values in Browser DevTools.
You can enter a JavaScript expression and it will automatically show the latest value.
This can be useful to see how a value changes over time or to monitor the focused element (<code>document.activeElement</code>) to see if focus handling is working properly.</p>
<p>Open the DevTools, navigate to the "Console" Tab and click the eye icon to add a new Live Expression.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/HwcO_gUnnH-300.webp 300w, https://tinytip.co/assets/img/HwcO_gUnnH-736.webp 736w, https://tinytip.co/assets/img/HwcO_gUnnH-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/HwcO_gUnnH-300.jpeg 300w, https://tinytip.co/assets/img/HwcO_gUnnH-736.jpeg 736w, https://tinytip.co/assets/img/HwcO_gUnnH-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Add live expression in DevTools" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/HwcO_gUnnH-300.jpeg" width="1472" height="423" /></picture></p>
Extract types in TypeScript2022-01-17T00:00:00Zhttps://tinytip.co/tips/ts-extract-types/<p>The <code>infer</code> keyword in Typescript makes it possible to extract types. This can be used to extract function parameters, generics and more.</p>
<!-- prettier-ignore -->
<pre class="language-typescript"><code class="language-typescript"><span class="token comment">// Given the following types ...</span><br /><span class="token keyword">export</span> <span class="token keyword">interface</span> <span class="token class-name">Stream<span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span></span> <span class="token punctuation">{</span> <span class="token function-variable function">next</span><span class="token operator">:</span> <span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">void</span> <span class="token punctuation">}</span><br /><span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name">SpecificStream</span> <span class="token operator">=</span> Stream<span class="token operator"><</span><span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">></span><span class="token punctuation">;</span><br /><br /><span class="token comment">// ... you can extract T into a type</span><br /><span class="token class-name"><span class="token keyword">export</span></span> <span class="token keyword">type</span> <span class="token class-name">ValueOfStream<span class="token operator"><</span><span class="token constant">S</span><span class="token operator">></span></span> <span class="token operator">=</span> <span class="token constant">S</span> <span class="token keyword">extends</span> <span class="token class-name">Stream<span class="token operator"><</span><span class="token keyword">infer</span> <span class="token constant">T</span><span class="token operator">></span></span> <span class="token operator">?</span> <span class="token constant">T</span> <span class="token operator">:</span> <span class="token builtin">never</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// ... and use like this</span><br /><span class="token keyword">function</span> <span class="token function">emitValue</span><span class="token punctuation">(</span><br /> stream<span class="token operator">:</span> SpecificStream<span class="token punctuation">,</span><br /> value<span class="token operator">:</span> ValueOfStream<span class="token operator"><</span>SpecificStream<span class="token operator">></span> <span class="token comment">// Extract T from Stream</span><br /><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></code></pre>
<p>TypeScript provides some built-in types like <code>Parameters</code> and <code>ReturnType</code>.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token comment">// Given this type ...</span><br /><span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name">SomeFn</span> <span class="token operator">=</span> <span class="token punctuation">(</span>first<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">,</span> second<span class="token operator">:</span> <span class="token builtin">boolean</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// ... you can extract parameters</span><br /><span class="token keyword">export</span> <span class="token keyword">type</span> <span class="token class-name">SecondParam</span> <span class="token operator">=</span> Parameters<span class="token operator"><</span>SomeFn<span class="token operator">></span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// ... and the return type</span><br /><span class="token class-name"><span class="token keyword">export</span></span> <span class="token keyword">type</span> <span class="token class-name">ReturnTypeOfSomeFn</span> <span class="token operator">=</span> ReturnType<span class="token operator"><</span>SomeFn<span class="token operator">></span><span class="token punctuation">;</span></code></pre>
Keep the separators when splitting a string in JavaScript2022-01-28T00:00:00Zhttps://tinytip.co/tips/js-split-keep-separator/<p>The <code>split()</code> function in JavaScript splits a string into an array by a separator and <strong>removes the separator</strong>:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Split by "-"</span><br /><span class="token string">"hello-from-javascript"</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"-"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Result: ["hello", "from", "javascript"]</span><br /><br /><span class="token comment">// Split by "-" or "_"</span><br /><span class="token string">"hello-from_javascript"</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">-|_</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Result: ["hello", "from", "javascript"]</span></code></pre>
<p>Use a RegEx group <code>(...)</code> if you want to <strong>keep the separator</strong> in the array:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Split by "-" or "_"</span><br /><span class="token string">"hello-from_javascript"</span><span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">(-|_)</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Result: ["hello", "-", "from", "_", "javascript"]</span></code></pre>
Data binding to aria attributes in Angular2022-02-25T00:00:00Zhttps://tinytip.co/tips/angular-attribute-binding/<p>Data Binding in Angular Templates binds to properties not attributes. As <code>aria-*</code> attributes are not properties, they cannot be bound to. If you want to bind to aria attributes, you need to use the <code>[attr.aria-*]</code> syntax.</p>
<pre class="language-html"><code class="language-html"><span class="token comment"><!-- Does NOT work --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">[aria-hidden]</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>isHidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- ... --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><br /><span class="token comment"><!-- Works --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">[attr.aria-hidden]</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>isHidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- ... --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
Exclude certain types in TypeScript2022-02-25T00:00:00Zhttps://tinytip.co/tips/ts-exclude-type/<p>The <code>Exclude</code> type in TypeScript is a way to exclude certain types from a union.</p>
<p>Let's say you use a third-party package that exports a function with an optional parameter. The parameter uses an inline type which is not exported:</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">fetch</span><span class="token punctuation">(</span>sortBy<span class="token operator">?</span><span class="token operator">:</span> <span class="token string">"name"</span> <span class="token operator">|</span> <span class="token string">"date"</span> <span class="token operator">|</span> <span class="token string">"rating"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></code></pre>
<p>You now want to extract the type of <code>sortBy</code> but exclude <code>undefined</code> from the union (<code>undefined</code> is allowed because the param is optional).</p>
<p>You can use <code>Parameters<T></code> to get the parameters of the function and <code>Exclude<T></code> to exclude <code>undefined</code>:</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">SortBy</span> <span class="token operator">=</span> Exclude<span class="token operator"><</span>Parameters<span class="token operator"><</span><span class="token keyword">typeof</span> fetch<span class="token operator">></span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">undefined</span><span class="token operator">></span><span class="token punctuation">;</span><br /><span class="token comment">// Results in: type SortBy = "name" | "date" | "rating"</span></code></pre>
CSS calc() requires unit2022-02-26T00:00:00Zhttps://tinytip.co/tips/css-calc-unit-required/<p>Most CSS properties require a unit, for example <code>padding: 10px</code>. If you use <code>0</code> you can omit the unit, like <code>padding: 0</code>.</p>
<p>An exception is the <code>calc()</code> function, which always requires a unit, even for <code>0</code>.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.example-class</span> <span class="token punctuation">{</span><br /> <span class="token property">padding</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token comment">/* works */</span><br /><br /> <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>100vh - 0<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* does NOT work */</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>100vh - 0px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* works */</span><br /><span class="token punctuation">}</span></code></pre>
<p>That is mainly important if you use CSS custom properties (aka variables) with a default value of <code>0</code> inside <code>calc()</code>:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.example-class</span> <span class="token punctuation">{</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>100vh - <span class="token function">var</span><span class="token punctuation">(</span>--header-height<span class="token punctuation">,</span> 0<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* does NOT work */</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>100vh - <span class="token function">var</span><span class="token punctuation">(</span>--header-height<span class="token punctuation">,</span> 0px<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* works */</span><br /><span class="token punctuation">}</span></code></pre>
Angular Outputs can be RxJS Observables2022-02-27T00:00:00Zhttps://tinytip.co/tips/angular-output-observable/<p>Angular uses the <code>@Output</code> decorator and the <code>EventEmitter</code> class to emit events to the parent component. But you can use RxJS streams instead.</p>
<p>The <code>EventEmitter</code> class is actually a wrapper around the RxJs Subject class. If you have an existing Subject or Observable that you want to use as an output, you can directly use it with the <code>@Output</code> decorator.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">SearchComponent</span> <span class="token punctuation">{</span><br /> <span class="token comment">// With Angular EventEmitter</span><br /> <span class="token decorator"><span class="token at operator">@</span><span class="token function">Output</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br /> search <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">EventEmitter<span class="token operator"><</span><span class="token builtin">string</span><span class="token operator">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token comment">// With RxJs Subject / Observable</span><br /> <span class="token decorator"><span class="token at operator">@</span><span class="token function">Output</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br /> search <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>form<span class="token punctuation">.</span>valueChanges<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><br /> <span class="token function">debounceTime</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token operator">=></span> value<span class="token punctuation">.</span>term<span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token function">distinctUntilChanged</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
CSS content-visibility hides the content of an element2022-02-28T00:00:00Zhttps://tinytip.co/tips/css-content-visibility/<p>There are several ways to hide an element in CSS. <code>display: none</code> completely hides the element from view. <code>visibility: hidden</code> hides the element from view, but the element still occupies space in the layout.</p>
<p>The <code>content-visibility</code> property allows you to hide the content of an element, but not the element itself. Some styling like background and border will still be visible.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.element</span> <span class="token punctuation">{</span><br /> <span class="token property">content-visibility</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>See <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility">MDN Web Docs</a> for more information and Browser support.</p>
Create clearer tests by nesting describe()2022-03-01T00:00:00Zhttps://tinytip.co/tips/testing-nested-describe/<p>Testing Frameworks like Vitest, Jest and Jasmine provide a <code>describe()</code> function. It is useful to group your tests into logical groups. The function can be nested to create a hierarchy of tests and make the tests more readable.</p>
<p>In Angular for example, you will have the following spec file when creating a new component:</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">"AccordionComponent"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should create"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Instead of adding a lot of <code>it()</code> calls with long descriptions you can create multiple <code>describe()</code> blocks.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">"AccordionComponent"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">"initial state is expanded"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// Mock data, test utils, etc. for this describe() block</span><br /> <span class="token keyword">const</span> initiallyExpanded <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should render the accordion title"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should render the accordion content"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should mark the accordion as expanded"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should collapse the accordion when clicking on the title"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">"initial state is collapsed"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should render the accordion title"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should not render the accordion content"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should mark the accordion as collapsed"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">"should expand the accordion when clicking on the title"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Jasmine shows all <code>describe()</code> blocks in the output and nests them in a tree structure.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/cHvMOfyv8q-300.webp 300w, https://tinytip.co/assets/img/cHvMOfyv8q-736.webp 736w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/cHvMOfyv8q-300.jpeg 300w, https://tinytip.co/assets/img/cHvMOfyv8q-736.jpeg 736w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Jasmine shows all nested describe blocks" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/cHvMOfyv8q-300.jpeg" width="736" height="317" /></picture></p>
Use npm ci for a clean installation of your dependencies2022-03-02T00:00:00Zhttps://tinytip.co/tips/npm-clean-install/<p>You already now the <code>npm install</code> command, right? It installs your dependencies defined in your <code>package.json</code> and <code>package-lock.json</code>. It will reuse existing packages in your <code>node_modules</code> folder and may update the <code>package-lock.json</code> file to match the actual installed versions. This is fine for development, but it is not what you want on your build or testing server.</p>
<p>The <code>npm ci</code> command does a clean install of your dependencies.
It removes the <code>node_modules</code> folder and re-installs the dependencies.
It will make sure that the <code>package-lock.json</code> is up to date and will exit with an error if it is not.
And will never update the <code>package.json</code> or <code>package-lock.json</code>.</p>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># On your machine</span><br /><span class="token function">npm</span> <span class="token function">install</span><br /><br /><span class="token comment"># On your build or testing server</span><br /><span class="token function">npm</span> ci</code></pre>
<p>See the <a href="https://docs.npmjs.com/cli/v8/commands/npm-ci">npm documentation</a> for more information.</p>
How to get the event target inside Shadow DOM2022-03-03T00:00:00Zhttps://tinytip.co/tips/js-event-composed-path/<p>The event object in JavaScript has a <code>target</code> property which is the actual element that triggered the event. The <code>currentTarget</code> property is the element that the event listener is attached to.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span>Click Me<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
<!-- prettier-ignore -->
<pre class="language-javascript"><code class="language-javascript">document<br /> <span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"container"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"click"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"target"</span><span class="token punctuation">,</span> event<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// => button</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"currentTarget"</span><span class="token punctuation">,</span> event<span class="token punctuation">.</span>currentTarget<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// => div</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This works different when using Shadow DOM. When the event was triggered inside an element with Shadow DOM,
the <code>target</code> property points the Shadow DOM element, not the element that triggered the event:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- Web Component with Shadow DOM --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>my-button</span><span class="token punctuation">></span></span>Click Me<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>my-button</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
<!-- prettier-ignore -->
<pre class="language-javascript"><code class="language-javascript">document<br /> <span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"container"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"click"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"target"</span><span class="token punctuation">,</span> event<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// => my-button</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"currentTarget"</span><span class="token punctuation">,</span> event<span class="token punctuation">.</span>currentTarget<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// => div</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>While this is good in terms of encapsulation, there are use cases where you need the actual target.
In these cases you can use the <code>composedPath</code> method to get the actual target:</p>
<!-- prettier-ignore -->
<pre class="language-javascript"><code class="language-javascript">document<br /> <span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"container"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"click"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"path"</span><span class="token punctuation">,</span> event<span class="token punctuation">.</span><span class="token function">composedPath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// => [slot, button, document-fragment, my-button,</span><br /> <span class="token comment">// div#container, body, html, document, Window]</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The method returns all the elements that are in the path of the event. The first element is the one that triggered the event.</p>
<p><strong>Note</strong>: this works only if the Shadow DOM uses encapsulation mode <code>open</code>.</p>
Customize the PDF viewer when embedding a PDF2022-03-04T00:00:00Zhttps://tinytip.co/tips/html-pdf-params/<p>If you want to embed a PDF document on your website you can use an iFrame.
The browser will automatically render a PDF viewer.</p>
<p>Google Chrome, Firefox and Safari accept some parameters to customize the viewer.
Add the parameters as part of the url fragment (after the <code>#</code>). Multiple parameters can be separated by <code>&</code>.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>iframe</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/path/to/document.pdf#toolbar=0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>iframe</span><span class="token punctuation">></span></span></code></pre>
<p>The following parameters are supported:</p>
<div class="table-wrapper">
<table><thead>
<tr>
<th>Parameter</th>
<th>Value</th>
<th>Description</th>
<th>Support</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>toolbar</code></td>
<td><code>1</code>, <code>0</code></td>
<td>Show or hide the toolbar</td>
<td>Chrome</td>
</tr>
<tr>
<td><code>view</code></td>
<td><code>FitV</code>, <code>FitH</code>, <code>Fit</code></td>
<td>Change the zoom level to fit (vertical, horizontal or both)</td>
<td>Chrome</td>
</tr>
<tr>
<td><code>zoom</code></td>
<td><code>number</code></td>
<td>Set a specific zoom level in % (example: 300)</td>
<td>Chrome, FF</td>
</tr>
<tr>
<td><code>page</code></td>
<td><code>number</code></td>
<td>Set initial position to a specific page (example: 2)</td>
<td>Chrome, FF, Safari</td>
</tr>
<tr>
<td><code>nameddest</code></td>
<td><code>string</code></td>
<td>Set initial position to a named destination (like a heading)</td>
<td>Chrome</td>
</tr>
</tbody>
</table>
</div>Run the same test with different data in Jest2022-03-15T00:00:00Zhttps://tinytip.co/tips/jest-test-each/<p>When you write a test in Jest and you want to run it with different data, you can use the <code>test.each</code> function.
The function accepts a data table, which is an array of arrays with the arguments that are passed to the actual test function.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> table <span class="token operator">=</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">[</span><span class="token string">"one"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> <span class="token punctuation">[</span><span class="token string">"two"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> <span class="token punctuation">[</span><span class="token string">"three"</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br />test<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span>table<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token string">"converts %s to %d"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">str<span class="token punctuation">,</span> expected</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// Will be called 3 times with "one", "two", "three"</span><br /> <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token function">convertToNumber</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token function">expect</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span>expected<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The title of the test can inject parameters with <code>printf</code> formatting (like <code>%s</code> for a string and <code>%d</code> for a number).</p>
<p>Read more about this in the <a href="https://jestjs.io/docs/api#testeachtablename-fn-timeout">Jest documentation</a>.</p>
React function component without children in TypeScript2022-03-26T00:00:00Zhttps://tinytip.co/tips/react-vfc/<p><strong>Update</strong>: Beginning with React 18 you don't need the <code>VFC</code> or <code>VoidFunctionComponent</code> interfaces anymore. The <code>children</code> property has been removed from the <code>FC</code> and <code>FunctionComponent</code> interfaces.</p>
<p>If you create a function component in React using TypeScript, there's the <code>FC</code> or <code>FunctionComponent</code> interface that you can use to define the type of your component. The interface automatically adds the <code>children</code> property to let the parent component pass child elements to your component.</p>
<p>If your component does not accept children, you can use the <code>VCF</code> or <code>VoidFunctionComponent</code> interface instead. It does not add the <code>children</code> property.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token constant">FC</span><span class="token punctuation">,</span> <span class="token constant">VFC</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">export</span> <span class="token keyword">interface</span> <span class="token class-name">Props</span> <span class="token punctuation">{</span><br /> msg<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token keyword">export</span> <span class="token keyword">const</span> MyCompWithChildren<span class="token operator">:</span> <span class="token constant">FC</span><span class="token operator"><</span>Props<span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">(</span>props<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token operator"><</span>div<span class="token operator">></span><span class="token operator">...</span><span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">export</span> <span class="token keyword">const</span> MyCompWithoutChildren<span class="token operator">:</span> <span class="token constant">VFC</span><span class="token operator"><</span>Props<span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">(</span>props<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token operator"><</span>div<span class="token operator">></span><span class="token operator">...</span><span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
Named lines in CSS grid2022-04-20T00:00:00Zhttps://tinytip.co/tips/css-grid-line-name/<p>When creating a CSS grid with <code>grid-template-columns</code> you can give your grid lines a name using the square brackets syntax <code>[name]</code>. Child elements can be positioned using this name.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.grid</span> <span class="token punctuation">{</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span><br /> <span class="token comment">/* Lines named "firstline", "secondline" and "thirdline" */</span><br /> <span class="token comment">/* Last line has no name */</span><br /> <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> [firstline] 1fr [secondline] 1fr [thirdline] 1fr<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.child</span> <span class="token punctuation">{</span><br /> <span class="token comment">/* Use the line name to set the position */</span><br /> <span class="token property">grid-column</span><span class="token punctuation">:</span> secondline<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>A line can have multiple names by separating them with a space:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.grid</span> <span class="token punctuation">{</span><br /> <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> [someline] 1fr [somename anothername thirdname] 1fr<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>And using <code>-start</code> and <code>-end</code> suffixes you can let a line name span over multiple columns.
In the example below <code>left</code> spans over the first two columns, <code>center</code> is used for the column in the middle and <code>right</code> spans over the last two columns.</p>
<!-- prettier-ignore -->
<pre class="language-css"><code class="language-css"><span class="token selector">.grid</span> <span class="token punctuation">{</span><br /> <span class="token property">grid-template-columns</span><span class="token punctuation">:</span><br /> [left-start] 1fr<br /> [right-start center] 2fr <br /> [left-end] 1fr [right-end]<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.cell-left</span> <span class="token punctuation">{</span> <span class="token property">grid-column</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/* 1fr + 2fr */</span><br /><span class="token selector">.cell-center</span> <span class="token punctuation">{</span> <span class="token property">grid-column</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/* 2fr */</span><br /><span class="token selector">.cell-right</span> <span class="token punctuation">{</span> <span class="token property">grid-column</span><span class="token punctuation">:</span> right<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/* 2fr + 1fr */</span></code></pre>
<p>And here is how this looks like:</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/n-kArtNro0-300.webp 300w, https://tinytip.co/assets/img/n-kArtNro0-736.webp 736w, https://tinytip.co/assets/img/n-kArtNro0-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/n-kArtNro0-300.jpeg 300w, https://tinytip.co/assets/img/n-kArtNro0-736.jpeg 736w, https://tinytip.co/assets/img/n-kArtNro0-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Visualization of the CSS grid with named columns example." loading="lazy" decoding="async" src="https://tinytip.co/assets/img/n-kArtNro0-300.jpeg" width="1472" height="965" /></picture></p>
<p>Your child elements don't need to know the exact number of columns anymore and can instead use the line name.
And if your grid is responsive and changes the number of columns dynamically, your child elements will still be positioned correctly without an additional media query to update <code>grid-column</code>.</p>
Eleventy supports Nunjucks globals2022-04-21T00:00:00Zhttps://tinytip.co/tips/eleventy-njk-globals/<p>Eleventy v1.0.0 (and above) supports Nunjucks globals.
This lets you register a global value or function that is available
in all Nunjucks templates.</p>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">(</span>eleventyConfig<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Register two globals, a static value and a function</span><br /> eleventyConfig<span class="token punctuation">.</span><span class="token function">addNunjucksGlobal</span><span class="token punctuation">(</span><span class="token string">"message"</span><span class="token punctuation">,</span> <span class="token string">"Hello World"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> eleventyConfig<span class="token punctuation">.</span><span class="token function">addNunjucksGlobal</span><span class="token punctuation">(</span><span class="token string">"greeting"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Hello </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Now you can use <code>{{ message }}</code> and <code>{{ greeting('John') }}</code> in your Nunjucks templates.</p>
<p>A more useful example is a global function that generates a unique id. You may need this if you want to connect a label with its input or for <code>aria-labelledby</code> and <code>aria-describedby</code>. Here I use the <a href="https://www.npmjs.com/package/nanoid">nanoid package</a> to generate the id:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">{</span> nanoid <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"nanoid"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> eleventyConfig<span class="token punctuation">.</span><span class="token function">addNunjucksGlobal</span><span class="token punctuation">(</span><span class="token string">"nanoid"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">nanoid</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Now you can create a new unique id, assign it to a local variable and use it to connect two HTML elements:</p>
<pre class="language-liquid"><code class="language-liquid"><span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> set id <span class="token operator">=</span> nanoid<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token delimiter punctuation">%}</span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>article</span> <span class="token attr-name">aria-labelledby</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> id <span class="token delimiter punctuation">}}</span></span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> id <span class="token delimiter punctuation">}}</span></span><span class="token punctuation">"</span></span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>article</span><span class="token punctuation">></span></span></code></pre>
<p>In the example above we connect the <code>h2</code> with the <code>article</code> element using <code>aria-labelledby</code>.</p>
Inject the unique app id of your Angular app2022-05-31T00:00:00Zhttps://tinytip.co/tips/angular-app-id/<p>Angular generates a unique id for your app which is available via <code>APP_ID</code> injection token. This is useful if you are in a micro-frontend with multiple Angular apps on the same page and you need a unique value.</p>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token constant">APP_ID</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"@angular/core"</span><span class="token punctuation">;</span><br /><br /><span class="token decorator"><span class="token at operator">@</span><span class="token function">Component</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><br /><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">MyComponent</span> <span class="token punctuation">{</span><br /> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token decorator"><span class="token at operator">@</span><span class="token function">Inject</span></span><span class="token punctuation">(</span><span class="token constant">APP_ID</span><span class="token punctuation">)</span> <span class="token keyword">private</span> appId<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"App id:"</span><span class="token punctuation">,</span> appId<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Example: "pvu"</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>Angular uses the app id for prefixing your CSS selectors when using <code>ViewEncapsulation.Emulated</code>.
You can define your own id by providing the token as a provider in your app module:</p>
<pre class="language-ts"><code class="language-ts"><span class="highlight-line"><span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token constant">APP_ID</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"@angular/core"</span><span class="token punctuation">;</span></span><br /><span class="highlight-line"></span><br /><span class="highlight-line"><span class="token decorator"><span class="token at operator">@</span><span class="token function">NgModule</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token comment">// ...</span></span><br /><span class="highlight-line"> providers<span class="token operator">:</span> <span class="token punctuation">[</span></span><br /><mark class="highlight-line highlight-line-active"> <span class="token punctuation">{</span></mark><br /><mark class="highlight-line highlight-line-active"> provide<span class="token operator">:</span> <span class="token constant">APP_ID</span><span class="token punctuation">,</span></mark><br /><mark class="highlight-line highlight-line-active"> useValue<span class="token operator">:</span> <span class="token string">"42"</span><span class="token punctuation">,</span></mark><br /><mark class="highlight-line highlight-line-active"> <span class="token punctuation">}</span><span class="token punctuation">,</span></mark><br /><span class="highlight-line"> <span class="token punctuation">]</span><span class="token punctuation">,</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span><span class="token punctuation">)</span></span><br /><span class="highlight-line"><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">AppModule</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span></code></pre>
Switch to the previous git branch with git switch2022-05-31T00:00:00Zhttps://tinytip.co/tips/git-switch-prev-branch/<p>After switching to another branch, you can use the <code>git switch -</code> command to switch back to the previous branch without having to reenter the name:</p>
<pre class="language-bash"><code class="language-bash"><span class="token comment"># Feature branch is active</span><br />$ <span class="token function">git</span> branch --show-current<br />feature/some-feature<br /><br /><span class="token comment"># Switch to another branch</span><br />$ <span class="token function">git</span> switch main<br /><br /><span class="token comment"># Do some work ...</span><br /><br /><span class="token comment"># Switch back to "feature/some-feature"</span><br />$ <span class="token function">git</span> switch -</code></pre>
Type-safe factory deps in Angular with inject()2022-06-05T00:00:00Zhttps://tinytip.co/tips/angular-inject-factory-providers/<p>A factory function provider in Angular can have dependencies using the <code>deps</code> property.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="highlight-line"><span class="token decorator"><span class="token at operator">@</span><span class="token function">NgModule</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span></span><br /><span class="highlight-line"> providers<span class="token operator">:</span> <span class="token punctuation">[</span></span><br /><span class="highlight-line"> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> provide<span class="token operator">:</span> <span class="token constant">SOME_INJECTION_TOKEN</span><span class="token punctuation">,</span></span><br /><mark class="highlight-line highlight-line-active"> deps<span class="token operator">:</span> <span class="token punctuation">[</span>MyService<span class="token punctuation">]</span><span class="token punctuation">,</span></mark><br /><mark class="highlight-line highlight-line-active"> <span class="token function-variable function">useFactory</span><span class="token operator">:</span> <span class="token punctuation">(</span>myService<span class="token operator">:</span> myService<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span></mark><br /><span class="highlight-line"> <span class="token keyword">return</span> myService<span class="token punctuation">.</span><span class="token function">someMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br /><span class="highlight-line"> <span class="token punctuation">}</span><span class="token punctuation">,</span></span><br /><span class="highlight-line"> <span class="token punctuation">}</span><span class="token punctuation">,</span></span><br /><span class="highlight-line"> <span class="token punctuation">]</span><span class="token punctuation">,</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span><span class="token punctuation">)</span></span><br /><span class="highlight-line"><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">MyModule</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span></code></pre>
<p>The problem is that you need to write the dependencies twice: once for the <code>deps</code> property and once as arguments of the <code>useFactory</code> function. Thanks to the new <code>inject()</code> function in Angular 14 there is now a better way to inject dependencies.</p>
<p>Call the <code>inject()</code> function and pass your dependency (here <code>MyService</code>) as argument.
It will provide you the dependency and the return value is type-safe.</p>
<pre class="language-typescript"><code class="language-typescript"><span class="token keyword">import</span> <span class="token punctuation">{</span> inject <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"@angular/core"</span><span class="token punctuation">;</span><br /><br /><span class="token decorator"><span class="token at operator">@</span><span class="token function">NgModule</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> providers<span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><br /> provide<span class="token operator">:</span> <span class="token constant">SOME_INJECTION_TOKEN</span><span class="token punctuation">,</span><br /> <span class="token function-variable function">useFactory</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> myService <span class="token operator">=</span> <span class="token function">inject</span><span class="token punctuation">(</span>MyService<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> myService<span class="token punctuation">.</span><span class="token function">someMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token comment">// Or as a one-liner:</span><br /> <span class="token comment">// return inject(MyService).someMethod();</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">]</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><br /><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">MyModule</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></code></pre>
Create collections from folders in Eleventy2022-06-23T00:00:00Zhttps://tinytip.co/tips/eleventy-collection-by-glob/<p>If you want to create a collection from a folder in your Eleventy project, like a collection of blog posts in the <em>posts</em> folder, you could manually add a <em>post</em> tag to every post. But there is an easier way.</p>
<p>The Collection API in Eleventy lets you filter your pages by glob patterns:</p>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> eleventyConfig<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">"posts"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">collectionApi</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> collectionApi<span class="token punctuation">.</span><span class="token function">getFilteredByGlob</span><span class="token punctuation">(</span><span class="token string">"posts/*.md"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>This will create a collection "posts" that contains all the markdown files in the <code>posts</code> folder.</p>
Use @at-root in SCSS to break out of nesting2022-06-23T00:00:00Zhttps://tinytip.co/tips/scss-at-root/<p>In SCSS, selectors can be deeply nested. In some situations you may want to break out of the current selector hierarchy and emit some styles at the root of the document. SCSS provides the <code>@at-root</code> rule for this use case:</p>
<pre class="language-scss"><code class="language-scss"><span class="highlight-line"><span class="token comment">/* styles.scss */</span></span><br /><span class="highlight-line"><span class="token keyword">@mixin</span> <span class="token function">some-mixin</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token property">color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span></span><br /><mark class="highlight-line highlight-line-active"></mark><br /><span class="highlight-line"> <span class="token atrule"><span class="token rule">@at-root</span> body</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token property">background</span><span class="token punctuation">:</span> lightgray<span class="token punctuation">;</span></span><br /><span class="highlight-line"> <span class="token punctuation">}</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span></span><br /><span class="highlight-line"></span><br /><span class="highlight-line"><span class="token selector">.some-class </span><span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token keyword">@include</span> <span class="token function">some-mixin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>This will move <code>body</code> out of the parent selector:</p>
<pre class="language-css"><code class="language-css"><span class="highlight-line"><span class="token comment">/* styles.css */</span></span><br /><span class="highlight-line"><span class="token selector">.some-class</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token property">color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span></span><br /><mark class="highlight-line highlight-line-active"></mark><br /><span class="highlight-line"><span class="token selector">body</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token property">background-color</span><span class="token punctuation">:</span> lightgray<span class="token punctuation">;</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
Import Markdown files in your Storybook MDX docs2022-06-23T00:00:00Zhttps://tinytip.co/tips/storybook-import-markdown/<p>Storybook allows you to import existing Markdown files your MDX docs.
You just need configure the <code>transcludeMarkdown</code> option in your storybook config:</p>
<pre class="language-js"><code class="language-js"><span class="highlight-line"><span class="token comment">// .storybook/main.js</span></span><br /><span class="highlight-line">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span></span><br /><span class="highlight-line"> <span class="token literal-property property">addons</span><span class="token operator">:</span> <span class="token punctuation">[</span></span><br /><mark class="highlight-line highlight-line-active"> <span class="token punctuation">{</span></mark><br /><mark class="highlight-line highlight-line-active"> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">"@storybook/addon-docs"</span><span class="token punctuation">,</span></mark><br /><mark class="highlight-line highlight-line-active"> <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">transcludeMarkdown</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">,</span></mark><br /><mark class="highlight-line highlight-line-active"> <span class="token punctuation">}</span><span class="token punctuation">,</span></mark><br /><span class="highlight-line"> <span class="token punctuation">]</span><span class="token punctuation">,</span></span><br /><span class="highlight-line"> <span class="token comment">// ...</span></span><br /><span class="highlight-line"><span class="token punctuation">}</span><span class="token punctuation">;</span></span></code></pre>
<p>Then you can import your Markdown file in your MDX file and render it as a component:</p>
<pre class="language-md"><code class="language-md">import Example from "./Example.md";<br /><br /><span class="token title important"><span class="token punctuation">#</span> Hello World</span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Example</span> <span class="token punctuation">/></span></span></code></pre>
RxJS combineLatest() accepts a selector function2022-07-12T00:00:00Zhttps://tinytip.co/tips/rxjs-combinelatest-selector/<p>The RxJS function <code>combineLatest()</code> accepts a selector function as last parameter.
This selector function receives the latest value of each observable as argument and can be used to return a new value that will be emitted.</p>
<!-- prettier-ignore -->
<pre class="language-javascript"><code class="language-javascript"><span class="token function">combineLatest</span><span class="token punctuation">(</span><br /> <span class="token comment">// Array of observables</span><br /> <span class="token punctuation">[</span>stream1$<span class="token punctuation">,</span> stream2$<span class="token punctuation">,</span> stream3$<span class="token punctuation">]</span><span class="token punctuation">,</span><br /><br /> <span class="token comment">// Selector function</span><br /> <span class="token punctuation">(</span><span class="token parameter">val1<span class="token punctuation">,</span> val2<span class="token punctuation">,</span> val3</span><span class="token punctuation">)</span> <span class="token operator">=></span> val1 <span class="token operator">+</span> val2 <span class="token operator">+</span> val3 <span class="token comment">// Return value will be emitted</span><br /><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
VoiceOver reads the title of external SVGs even if the alt text is empty2022-09-22T00:00:00Zhttps://tinytip.co/tips/a11y-voiceover-svg-title/<p>For accessibility reasons every image on a page should have an <code>alt</code> attribute with a description of the image or, for decorative images,
with an empty value. Images with an empty alt text will be ignored by screen readers.</p>
<p>However, there is one exception. If the <code>src</code> attribute points to an SVG file that has a <code>title</code> tag,
VoiceOver (on macOS and iOS) will read the title and not ignore the image.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>circle.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
<pre class="language-xml"><code class="language-xml"><span class="token comment"><!-- /circle.svg --></span><br /><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">svg</span> <span class="token name">PUBLIC</span> <span class="token string">"-//W3C//DTD SVG 1.1//EN"</span> <span class="token string">"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>svg</span> <span class="token attr-name">viewBox</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>0 0 20 10<span class="token punctuation">"</span></span> <span class="token attr-name">xmlns</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://www.w3.org/2000/svg<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>circle</span> <span class="token attr-name">cx</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5<span class="token punctuation">"</span></span> <span class="token attr-name">cy</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5<span class="token punctuation">"</span></span> <span class="token attr-name">r</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- SVG image with a title tag --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Circle<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>circle</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>svg</span><span class="token punctuation">></span></span></code></pre>
<p>In the example above VoiceOver will read "<em>Circle, image</em>", while other screen readers like NVDA will ignore the image.</p>
<p>SVG files generated via design tools like Sketch often include a title.
The title may be useless (like a description of a decorative icon) or even absolute nonsense (like an auto-generated UUID) and could also be in the wrong language, resulting in a confusing experience for screen reader users.</p>
<p>Either make sure that your images don't include a <code>title</code> tag or use the <code>aria-hidden</code> attribute to hide the image:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>circle.svg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token attr-name">aria-hidden</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
Let VoiceOver on iOS read a split element as a single element with the text role2022-09-22T00:00:00Zhttps://tinytip.co/tips/a11y-voiceover-text-role/<p>VoiceOver on iOS reads each element individually when a user swipes across the screen.
If an element like a link is composed of several span elements, VoiceOver will not read the entire link text but only the text of the active span element (the one that the user has swiped on). Buttons are an exception - VoiceOver will read all child elements at once.</p>
<p>For cases where you want VoiceOver to read the whole text at once you can use the unofficial role <code>text</code>
which causes VoiceOver to read the split element as one element. Note that this role is not an official role
but just used by VoiceOver. In addition, the role should not be placed on the <code>a</code> tag directly but on a child element
because it would overwrite the implicit <code>link</code> role of the <code>a</code> tag.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://tinytip.co<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- Let VoiceOver on iOS read the entire link text at once --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>tinytip<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>material-icons<span class="token punctuation">"</span></span> <span class="token attr-name">aria-label</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>(external)<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>open_in_new<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
Search & replace with RegEx groups in VS Code2022-09-22T00:00:00Zhttps://tinytip.co/tips/vscode-search-regex-groups/<p>The search & replace feature in VS Code cannot just search for static strings but accepts RegEx patterns.
Just click on the <code>.*</code> icon in the search input to enable RegEx search.</p>
<p>For the replace pattern you can reference a RegEx group by using "$" and the index of the group.
<code>$0</code> references the entire match, <code>$1</code> references the first group, <code>$2</code> the second group and so on.</p>
<p>Let's make an example: The search pattern <code>Hello (\S+)</code> will find strings like "Hello John".
The group <code>(\S+)</code> captures the name (here "John") which can be referenced in the replace pattern using <code>$1</code>.
With the replace pattern <code>Hi $1!</code> we'll get the following results:</p>
<pre class="language-diff"><code class="language-diff"><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line"> Hello John<br /></span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> Hi John!<br /></span></span><br /><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line"> Hello Jane<br /></span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> Hi Jane!</span></span></code></pre>
Empty Cache and Hard Reload in Chrome2022-10-27T00:00:00Zhttps://tinytip.co/tips/chrome-hard-reload/<p>We all know cache invalidation is hard. If you experience some cache problems while working on a web project in Chrome you can empty the cache and do a hard reload. Just open the DevTools, right click (or long press) on the reload icon in the toolbar and choose "Empty Cache and Hard Reload":</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/TfdLYwtrd_-300.webp 300w, https://tinytip.co/assets/img/TfdLYwtrd_-736.webp 736w, https://tinytip.co/assets/img/TfdLYwtrd_-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/TfdLYwtrd_-300.jpeg 300w, https://tinytip.co/assets/img/TfdLYwtrd_-736.jpeg 736w, https://tinytip.co/assets/img/TfdLYwtrd_-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Empty cache and Hard Reload in Chrome" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/TfdLYwtrd_-300.jpeg" width="1472" height="1193" /></picture></p>
Find the gitignore rule that excludes a file from git2022-10-27T00:00:00Zhttps://tinytip.co/tips/git-check-ignore-rule/<p>When a file is ignored by git you can use the <code>check-ignore</code> command which shows you why the file is ignored. This is useful if you have multiple <code>.gitignore</code> files or some complex patterns in your rules.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">git</span> check-ignore <span class="token parameter variable">-v</span> path/to/a/file.png</code></pre>
Create QR codes in Chrome to send URLs to your smartphone2023-01-19T00:00:00Zhttps://tinytip.co/tips/chrome-qr-code/<p>If you want to open a website on your smartphone, i.e. to test it on a mobile device, you can use the sharing feature of Chrome to create a QR code that you can scan with your smartphone. Click on the share icon in the address bar and select "Create QR Code". Then scan the QR code with the camera app of your smartphone to open the website.</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/0_O9agQOil-300.webp 300w, https://tinytip.co/assets/img/0_O9agQOil-736.webp 736w, https://tinytip.co/assets/img/0_O9agQOil-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/0_O9agQOil-300.jpeg 300w, https://tinytip.co/assets/img/0_O9agQOil-736.jpeg 736w, https://tinytip.co/assets/img/0_O9agQOil-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="Generate QR code in Chrome" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/0_O9agQOil-300.jpeg" width="1472" height="1204" /></picture></p>
Find previous commands in the terminal2023-01-19T00:00:00Zhttps://tinytip.co/tips/terminal-search-commands/<p>When you want to rerun a previously executed command in the terminal, you can use the up and down arrow keys to navigate through the history of commands. If you want to search for a specific command, press <code>Ctrl + R</code> and start typing. The terminal will search through the history and show you the latest matching command. Press <code>Ctrl + R</code> again to search for older commands.</p>
Custom hooks should return named tuples and not use "as const"2023-03-19T00:00:00Zhttps://tinytip.co/tips/react-hook-tuple/<p>When you create a custom hook in React that returns a tuple, like <code>setState</code> does, you must tell TypeScript that you are returning a tuple and not just an array of arbitrary length. For example, the following code will not work:</p>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">usePromise</span><span class="token generic class-name"><span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span></span></span><span class="token punctuation">(</span><span class="token function-variable function">fn</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token builtin">Promise</span><span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token keyword">return</span> <span class="token punctuation">[</span>value<span class="token punctuation">,</span> isReady<span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>TypeScript will tell you that the return type of the hook is <code>(T | boolean)[]</code>. To make the return value type-safe, you can use <code>as const</code>:</p>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">usePromise</span><span class="token generic class-name"><span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span></span></span><span class="token punctuation">(</span><span class="token function-variable function">fn</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token builtin">Promise</span><span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token keyword">return</span> <span class="token punctuation">[</span>value<span class="token punctuation">,</span> isReady<span class="token punctuation">]</span> <span class="token keyword">as</span> <span class="token keyword">const</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>The return type is now <code>readonly [T, boolean]</code>. However, as a consumer of the hook you don't know what these values mean. What's that <code>boolean</code> value? Does it indicate if the promise is ready or if it failed? You can solve this by explicitly defining the return value and giving the tuple items a name:</p>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">usePromise</span><span class="token generic class-name"><span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span></span></span><span class="token punctuation">(</span><span class="token function-variable function">fn</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token builtin">Promise</span><span class="token operator"><</span><span class="token constant">T</span><span class="token operator">></span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token punctuation">[</span>value<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">,</span> isReady<span class="token operator">:</span> <span class="token builtin">boolean</span><span class="token punctuation">]</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token keyword">return</span> <span class="token punctuation">[</span>value<span class="token punctuation">,</span> isReady<span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>This way, the return type is <code>[value: T, isReady: boolean]</code> and the consumer of the hook knows what the values mean.</p>
Get IANA timezone of user2023-06-27T00:00:00Zhttps://tinytip.co/tips/js-timezone/<p>If you ever have to work with timezones in JavaScript, you can use <code>Intl.DateTimeFormat</code> to get the IANA timezone of the user:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> timeZone <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Intl<span class="token punctuation">.</span>DateTimeFormat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">resolvedOptions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>timeZone<span class="token punctuation">;</span><br /><span class="token comment">// Result: "Europe/Zurich"</span></code></pre>
Scope your CSS imports with meta.load-css in Sass2023-06-27T00:00:00Zhttps://tinytip.co/tips/scss-load-css/<p>In contrast to the old <code>@import</code> rule to import SCSS files in Sass, the newer <code>@use</code> rule can only be used at the top level of a file,
before any other statements. Using it inside a CSS selector is not allowed. For example:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.dark-theme </span><span class="token punctuation">{</span><br /> <span class="token comment">// Works</span><br /> <span class="token keyword">@import</span> <span class="token string">"./dark-theme.scss"</span><span class="token punctuation">;</span><br /><br /> <span class="token comment">// Does NOT work</span><br /> <span class="token keyword">@use</span> <span class="token string">"./dark-theme.scss"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>But there is still a way for scoped imports.
The <a href="https://sass-lang.com/documentation/modules/meta#load-css"><code>meta.load-css</code></a> function allows you to
import a SCSS file inside a CSS selector and scope it to that selector:</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@use</span> <span class="token string">"sass:meta"</span><span class="token punctuation">;</span><br /><br /><span class="token selector">.dark-theme </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> meta.<span class="token function">load-css</span><span class="token punctuation">(</span><span class="token string">"./dark-theme.scss"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Unlike <code>@import</code>, <code>meta.load-css</code> does not affect the parent selector <code>&</code> in the imported file.
Given the following file:</p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// dark-theme.scss</span><br /><span class="token selector">button </span><span class="token punctuation">{</span><br /> <span class="token selector"><span class="token parent important">&</span> + <span class="token parent important">&</span> </span><span class="token punctuation">{</span><br /> <span class="token property">margin-inline-start</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>Importing it with <code>@import</code> would result in a CSS selector that is technically valid but likely not what you want:</p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// Using @import results in:</span><br /><span class="token selector">.dark-theme button + .dark-theme button </span><span class="token punctuation">{</span><br /> <span class="token property">margin-inline-start</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Using <code>meta.load-css</code> however does not break the parent selector:</p>
<pre class="language-scss"><code class="language-scss"><span class="token comment">// Using meta.load-css results in:</span><br /><span class="token selector">.dark-theme button + button </span><span class="token punctuation">{</span><br /> <span class="token property">margin-inline-start</span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
Query selectors are applied to the whole document, unless you use :scope2023-07-03T00:00:00Zhttps://tinytip.co/tips/js-query-selector-scope/<p>Here's a quiz for you: Given the HTML below, what element will be returned by the <code>querySelector()</code> call?
Note that the <code>.wrapper</code> is outside the <code>.main</code> element.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wrapper<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>main<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>content<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> main <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">".main"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> content <span class="token operator">=</span> main<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">".wrapper .content"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// What's the result???</span></code></pre>
<p>Don't cheat! Think about it for a second.</p>
<hr />
<p>If you call <code>querySelector()</code> or <code>querySelectorAll()</code> on an element, you will only get elements within that element.
However, the query itself will be applied to the whole document. So the above code will return the <code><div class="content"></div></code> node.</p>
<p>You can include the <code>:scope</code> pseudo-class to apply the query to the element itself:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> main <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">".main"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> content <span class="token operator">=</span> main<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">":scope .wrapper .content"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Result: null</span></code></pre>
<p>This is also useful to query direct children of an element:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> main <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">".main"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> content <span class="token operator">=</span> main<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">":scope > .child"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// --> Does not include nested .child elements</span></code></pre>
Show DOM nodes in React DevTools2023-10-14T00:00:00Zhttps://tinytip.co/tips/react-devtools-nodes/<p>The <a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi">React Developer Tools</a> extension for your browser allows you to inspect
your React application and see the component tree. By default, the components tree
only renders your React components but not the DOM nodes. However, you can change
the default filter and show DOM nodes as well.</p>
<p>Follow these steps to show DOM nodes in the components tree:</p>
<p><picture><source type="image/webp" srcset="https://tinytip.co/assets/img/ump5DqzT3d-300.webp 300w, https://tinytip.co/assets/img/ump5DqzT3d-736.webp 736w, https://tinytip.co/assets/img/ump5DqzT3d-1472.webp 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><source type="image/jpeg" srcset="https://tinytip.co/assets/img/ump5DqzT3d-300.jpeg 300w, https://tinytip.co/assets/img/ump5DqzT3d-736.jpeg 736w, https://tinytip.co/assets/img/ump5DqzT3d-1472.jpeg 1472w" sizes="(min-width: 768px) 50vw, 100vw" /><img alt="" loading="lazy" decoding="async" src="https://tinytip.co/assets/img/ump5DqzT3d-300.jpeg" width="1472" height="376" /></picture></p>
<ol>
<li>Navigate the React <em>Components</em> tab in the DevTools</li>
<li>Click on the settings icon in the top right corner of the tree panel</li>
<li>Navigate to the <em>Components</em> tab in the settings overlay</li>
<li>Disable the toggle in the <em>Hide components where...</em> section.</li>
</ol>
Replace any with generics, not with unknown (in many cases)2024-02-25T00:00:00Zhttps://tinytip.co/tips/ts-replace-any/<p>You sure know that <code>any</code> in TypeScript is bad and should be avoided. But what should you replace it with?</p>
<p><strong>When the type is unknown throughout the application</strong>: If the type is unknown in the entire application, such as when receiving data from an untrusted third-party API, the <code>unknown</code> type is your best choice. It's the type-safe counterpart of <code>any</code> and informs TypeScript that the type is unknown until you validate it at runtime. You can validate the type using methods like <code>Array.isArray()</code> or the <code>typeof</code> operator:</p>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">unknown</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token builtin">Array</span><span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// We know it's an array</span><br /> <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Number of items: "</span> <span class="token operator">+</span> value<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">"string"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// We know it's a string</span><br /> <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>value<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p><strong>When the type is unknown in a specific context</strong>: Sometimes, your type might be unknown in one part of the application (where you don't care about the type) but known in another part. If you try to replace <code>any</code> with <code>unknown</code> in this case, you will likely encounter errors.</p>
<!-- prettier-ignore -->
<pre class="language-ts"><code class="language-ts"><span class="token keyword">const</span> addValidationFn <span class="token operator">=</span> <span class="token punctuation">(</span>fn<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">unknown</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token builtin">boolean</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// => Doesn't work, you will get: Type 'unknown' is not assignable to type 'number'</span><br /><span class="token function">addValidationFn</span><span class="token punctuation">(</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>In this case, TypeScript is correct. Inside <code>addValidationFn</code>, you could call the provided function with any value because you've specified that the type is unknown, and any value is assignable to <code>unknown</code>. Therefore, providing a function that expects a number is not valid.</p>
<p>In such scenarios, you should use generics:</p>
<!-- prettier-ignore -->
<pre class="language-ts"><code class="language-ts"><span class="token keyword">const</span> addValidationFn <span class="token operator">=</span> <span class="token operator"><</span><span class="token constant">V</span><span class="token punctuation">,</span><span class="token operator">></span><span class="token punctuation">(</span>fn<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token constant">V</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token builtin">boolean</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// => This works</span><br /><span class="token function">addValidationFn</span><span class="token punctuation">(</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Generics allow you to capture the type information while maintaining type safety. In the above example, <code>V</code> is a placeholder for any type, and it will be determined when <code>addValidationFn</code> is called.</p>