<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mirco Kraenz</title>
    <description>The latest articles on Forem by Mirco Kraenz (@typescriptteatime).</description>
    <link>https://forem.com/typescriptteatime</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F629669%2Fd47c7929-a696-4f09-bd3a-192023f57cbd.jpeg</url>
      <title>Forem: Mirco Kraenz</title>
      <link>https://forem.com/typescriptteatime</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/typescriptteatime"/>
    <language>en</language>
    <item>
      <title>Run Storybook with NX Expo and React Native Paper</title>
      <dc:creator>Mirco Kraenz</dc:creator>
      <pubDate>Tue, 17 Dec 2024 21:06:38 +0000</pubDate>
      <link>https://forem.com/typescriptteatime/run-storybook-with-nx-expo-and-react-native-paper-4l8l</link>
      <guid>https://forem.com/typescriptteatime/run-storybook-with-nx-expo-and-react-native-paper-4l8l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;tl;dr:&lt;/strong&gt; Add &lt;a href="https://www.npmjs.com/package/vite-plugin-react-native-web" rel="noopener noreferrer"&gt;vite-plugin-react-native-web&lt;/a&gt; to your storybook config in &lt;code&gt;{projectRoot}/.storybook/main.ts&lt;/code&gt; and you should be good to go. Scroll to end for the full config.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After several days of finally getting this running, while stumbling onto &lt;a href="https://github.com/nrwl/nx/issues/17580#issuecomment-2110399323" rel="noopener noreferrer"&gt;this NX issue&lt;/a&gt; several times, I thought I might as well share my solution, and an approach of how to debug if things go haywire (which they did - a lot).&lt;/p&gt;

&lt;p&gt;I am assuming you have a working NX workspace with an Expo project and React Native Paper installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add Storybook&lt;/li&gt;
&lt;li&gt;Make DOM elements in Storybook work&lt;/li&gt;
&lt;li&gt;Make React Native elements in Storybook work&lt;/li&gt;
&lt;li&gt;Make React Native Paper elements in Storybook work&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Add Storybook
&lt;/h2&gt;

&lt;p&gt;Tested under version&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;@nx/expo@&lt;/span&gt;&lt;span class="mf"&gt;20.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;yarn@&lt;/span&gt;&lt;span class="mf"&gt;1.22&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;node@&lt;/span&gt;&lt;span class="mf"&gt;22.11&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;22.04&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's get started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn nx add @nx/storybook
yarn nx g @nx/react:storybook-configuration PROJECT_NAME
&lt;span class="c"&gt;# I answered all questions with the default selection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, this installed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"@nx/storybook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20.1.4"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@nx/vite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20.1.4"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@nx/web"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20.1.4"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@storybook/addon-essentials"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.2.8"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@storybook/addon-interactions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.2.8"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@storybook/core-server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.2.8"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@storybook/jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.2.3"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@storybook/react-vite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.2.8"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@storybook/test-runner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.13.0"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@storybook/testing-library"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.2.2"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@vitejs/plugin-react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.2.0"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"storybook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.2.8"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5.0.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on your components it should generate at least one &lt;code&gt;*.stories.tsx&lt;/code&gt; file, in my case &lt;code&gt;App.stories.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you start this and it renders perfectly for you. Congratz. You don't need to read further. If you're anything like me, then it doesn't render and here's how I debugged it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make DOM elements in Storybook work
&lt;/h2&gt;

&lt;p&gt;I check that at least the most basic setup works by editing &lt;code&gt;App.stories.tsx&lt;/code&gt; and replace the file contents with the most limited I can think of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;within&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/testing-library&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;XComp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hi&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;XComp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;yarn nx storybook PROJECT_NAME&lt;/code&gt; should open the browser and you should see the text 'Hi'.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7dhx1x843y33bnpkj3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7dhx1x843y33bnpkj3g.png" alt="Image" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Make React Native elements in Storybook work
&lt;/h2&gt;

&lt;p&gt;Next up is including something from React Native.&lt;/p&gt;

&lt;p&gt;So I change the component definition in &lt;code&gt;App.stories.tsx&lt;/code&gt; to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hi&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This already starts to fail.&lt;br&gt;
The webapp displays an error &lt;code&gt;Failed to fetch dynamically imported module: http://localhost:35021/src/app/App.stories.tsx&lt;/code&gt; while the console shows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✘ [ERROR] Unexpected "typeof"

    ../../node_modules/react-native/index.js:14:7:
      14 │ import typeof ActionSheetIOS from './Libraries/ActionSheetIOS/ActionSheetIOS';
         ╵        ~~~~~~

9:15:52 PM [vite] error while updating dependencies:
Error: Build failed with 1 error:
../../node_modules/react-native/index.js:14:7: ERROR: Unexpected "typeof"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is still 'easy' to fix. Because we're rendering for the web, we should use react-native-web instead of react-native. Obviously, I don't want to hardcode the import to &lt;code&gt;react-native-web&lt;/code&gt; as that would not be beneficial for my component library for expo mobile dev. We can however leverage resolve.aliases to import from &lt;code&gt;react-native-web&lt;/code&gt; whenever our code says &lt;code&gt;import ... from 'react-native'&lt;/code&gt;. (I assume this is what happens under the hood in Expo depending on your target platform. Maybe you can teach me or link to some references in the comments. I'd appreciate it!).&lt;/p&gt;

&lt;p&gt;Anyway, to resolve the correct import, we go into &lt;code&gt;{projectRoot}/.storybook/main.ts&lt;/code&gt; and replace the config by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../src/app/**/*.@(mdx|stories.@(js|jsx|ts|tsx))&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/addon-essentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/addon-interactions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/react-vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;viteFinal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;mergeConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;nxViteTsPaths&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native-web&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing again by rerunning &lt;code&gt;yarn nx storybook PROJECT_NAME&lt;/code&gt; should now render the text 'Hi' again. Nice!&lt;/p&gt;

&lt;p&gt;So now we have storybook, we can theoretically use regular DOM elements, but more importantly we can use React Native components. A good point to stage and commit our changes. Then it's up to the next level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make React Native Paper elements in Storybook work
&lt;/h2&gt;

&lt;p&gt;In my case, I am building on top of React Native Paper, so the natural next step is to change &lt;code&gt;MyComponent&lt;/code&gt; to include&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PaperProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native-paper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaperProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hi&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;PaperProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This again will fail to render, and the console shows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✘ [ERROR] Expected "from" but found "{"

    ../../node_modules/react-native-vector-icons/lib/NativeRNVectorIcons.js:3:12:
      3 │ import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport';
        │             ^
        ╵             from

✘ [ERROR] The JSX syntax extension is not currently enabled

    ../../node_modules/react-native-vector-icons/lib/icon-button.js:116:8:
      116 │         &amp;lt;TouchableHighlight
          ╵         ^

  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able
  to parse JSX syntax. You can use "loader: { '.js': 'jsx' }" to do that.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that these files are not plain javascript files but include Flow types, and also JSX files.&lt;/p&gt;

&lt;p&gt;While the error tells us to customize our loader to treat every js file as jsx, that won't solve the problem with the Flow types in TurboModule. At this point we could probably dive deeper to strip the flow types. But what if we simply solve both problems at once, and the problem of resolving the right import from earlier, too?&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://www.npmjs.com/package/vite-plugin-react-native-web" rel="noopener noreferrer"&gt;vite-plugin-react-native-web&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;We install it by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; vite-plugin-react-native-web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then we go back to &lt;code&gt;{projectRoot}/.storybook/main.ts&lt;/code&gt; and replace the config by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/react-vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nxViteTsPaths&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nx/vite/plugins/nx-tsconfig-paths.plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mergeConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;reactNativeWeb&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite-plugin-react-native-web&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StorybookConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../src/app/**/*.@(mdx|stories.@(js|jsx|ts|tsx))&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/addon-essentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/addon-interactions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/react-vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;viteFinal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;mergeConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;nxViteTsPaths&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;reactNativeWeb&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Notice that we also got rid of the &lt;code&gt;resolve.alias&lt;/code&gt; part. This is because &lt;code&gt;vite-plugin-react-native-web&lt;/code&gt; will take care of that for us.&lt;/p&gt;

&lt;p&gt;Now we can rerun &lt;code&gt;yarn nx storybook PROJECT_NAME&lt;/code&gt; and the text 'Hi' should render again. (If you don't get an error but a blank canvas inside storybook, then the theme is probably off. Try switching to dark/light theme in the storybook UI and the text should become visible.)&lt;/p&gt;

&lt;p&gt;And that's it! We now have a working storybook setup with React Native Paper components.&lt;/p&gt;

&lt;p&gt;Kudos go to the maintainers of &lt;code&gt;vite-plugin-react-native-web&lt;/code&gt; for making this possible.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>storybook</category>
      <category>nx</category>
      <category>expo</category>
    </item>
    <item>
      <title>TypeScript's `as` keyword might not be what you think</title>
      <dc:creator>Mirco Kraenz</dc:creator>
      <pubDate>Mon, 10 Oct 2022 11:22:00 +0000</pubDate>
      <link>https://forem.com/typescriptteatime/typescripts-as-keyword-might-not-be-what-you-think-2bpo</link>
      <guid>https://forem.com/typescriptteatime/typescripts-as-keyword-might-not-be-what-you-think-2bpo</guid>
      <description>&lt;p&gt;I've done a lot of interviews on the interviewer-side a little while ago and one thing surprised me:&lt;br&gt;
Many developers get the concept of &lt;code&gt;as string&lt;/code&gt; in TypeScript wrong; thinking they are safe now that they use it - but really aren't. 😕&lt;br&gt;
So what does &lt;code&gt;as string&lt;/code&gt; or more generally &lt;code&gt;as MyType&lt;/code&gt; actually do? And how do I fill the gap it leaves?&lt;/p&gt;
&lt;h1&gt;
  
  
  tl;dr
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;as&lt;/code&gt; keyword only changes &lt;em&gt;compile&lt;/em&gt;-time behavior. You essentially tell the compiler to stop complaining. Runtime behavior stays unchanged. If you need runtime safety, use techniques like polymorphism, &lt;code&gt;in&lt;/code&gt; type guards, &lt;code&gt;typeof&lt;/code&gt; type guards, &lt;code&gt;instanceof&lt;/code&gt; type guards, or user-defined type guards, or assertion functions.&lt;/p&gt;
&lt;h1&gt;
  
  
  Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;tl;dr&lt;/li&gt;
&lt;li&gt;Contents&lt;/li&gt;
&lt;li&gt;What &lt;code&gt;as string&lt;/code&gt; actually does&lt;/li&gt;
&lt;li&gt;Buggy Example&lt;/li&gt;
&lt;li&gt;Polymorphism&lt;/li&gt;
&lt;li&gt;
Type Guards

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;in&lt;/code&gt; Type Guard&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;instanceof&lt;/code&gt; Type Guard&lt;/li&gt;
&lt;li&gt;User-Defined Type Guard&lt;/li&gt;
&lt;li&gt;TypeScript trusts us in writing proper User-Defined Type Guards&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What about &lt;code&gt;&amp;lt;MyType&amp;gt;&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;What about the new &lt;code&gt;satisfies&lt;/code&gt; keyword?&lt;/li&gt;
&lt;li&gt;Closing&lt;/li&gt;
&lt;li&gt;Recommended Reading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  What &lt;code&gt;as string&lt;/code&gt; actually does
&lt;/h1&gt;

&lt;p&gt;Or: &lt;em&gt;Type Assertion&lt;/em&gt; vs &lt;em&gt;Type Casting&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Many developers know Type Casting from languages like Java. You have a &lt;code&gt;double&lt;/code&gt; and want to turn it into an &lt;code&gt;int&lt;/code&gt;, so you do &lt;code&gt;int myInt = (int) myDouble;&lt;/code&gt;. In Java this is fine and actually changes the behavior &lt;em&gt;at runtime&lt;/em&gt;. But here's the thing: &lt;strong&gt;TypeScript doesn't!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead, TypeScript's &lt;code&gt;as MyType&lt;/code&gt; only changes &lt;em&gt;compile time&lt;/em&gt; behavior. It's like saying to the compiler "Compiler, believe me. This is a &lt;code&gt;MyType&lt;/code&gt;. So stop complaining." Nothing has changed for the resulting JavaScript code after compiling. In other words, we're still completely vulnerable at &lt;em&gt;runtime&lt;/em&gt;. That's why TypeScript actually uses the term &lt;em&gt;Type Assertion&lt;/em&gt; intead of &lt;em&gt;Type Casting&lt;/em&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Buggy Example
&lt;/h1&gt;

&lt;p&gt;Let's look at an example where things go wrong. The code will result in a &lt;code&gt;addLemon is not a function&lt;/code&gt; runtime error. You can try by hitting the "Run" button inside the&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgCoTsg3gKGcuAE0IBkIBbAexAAoBKALmQDdLhCBuHAXx1EliIUAYUowYEFLnxFCAZQCuAczhR6TVuy68cMBSARhg1AsQCiADzBQ4NABaUwAIQjNocJRCbpMAH2Si4pJ02HjIAPThyABGyshQEAAOlFBgyKAIlOSgSmH2ji5uNp4EAM5oGHQAdLJkVLR02jg4mSClaYhgCnAANj0AnoESXgFiw8gAvKEyxIoqUEz0kwB80-jIraWUPRBVPZRKNABEAILEEITIpcqqR41h3AA0PFyylta2nd19g2PBHEA"&gt;Interactive TypeScript Playground here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// bug report incoming&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotBeverage&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Added sugar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's walk through this code. We define interfaces &lt;code&gt;Tea&lt;/code&gt; and &lt;code&gt;Coffee&lt;/code&gt; with different methods on them. Next, we incidentally grab ourselves a Coffee (what a grave mistake), and pass it to the &lt;code&gt;addExtra&lt;/code&gt; function. This function however &lt;strong&gt;misuses&lt;/strong&gt; &lt;code&gt;as Tea&lt;/code&gt;, essentially assuming/asserting everything we pass to the function is always tea. The result is a runtime error saying &lt;code&gt;TypeError: hotBeverage.addLemon is not a function&lt;/code&gt;. Making it into production might easily cost us a few thousand bucks to fix and a lot of customer frustration because they can't drink their morning coffee. At least your customers can still drink &lt;code&gt;Tea&lt;/code&gt;. 😉&lt;/p&gt;

&lt;p&gt;Admittedly, this example seems slightly artificial but there are enough examples in the real world where similar things happen.&lt;/p&gt;

&lt;h1&gt;
  
  
  Polymorphism
&lt;/h1&gt;

&lt;p&gt;Depending on what you want from a business perspective, the solution might be using &lt;em&gt;Type Guards&lt;/em&gt;. Another approach for the above is using polymorphism.&lt;/p&gt;

&lt;p&gt;Wikipedia's intro sentence for &lt;a href="https://en.wikipedia.org/wiki/Polymorphism_(computer_science)"&gt;Polymorphism&lt;/a&gt; is&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In programming languages and type theory, polymorphism is the provision of a single interface to entities of different types [...]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is, instead of having an &lt;code&gt;addExtra&lt;/code&gt; function, we might change the code into the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/FASwdgLgpgTgZgQwMZQAQBUoNQb2K1BAEyIAooAPCGBALlQGdrwBzASnoDcB7EIgbmABfUJFiIUqAMLc4cKGjwFiZStTqNmYdl14DhwYEm5gmhJBACuCADY2AnjLkL6T+WgC8ufIRL1yVDT0TDCsbKgeAHzeBATGptw2UAB0NtwspAAGKlBEqAAkOGo0QplsPkIANMKCyFa2Dm4KySqkAEQMliwIMG1s-EA"&gt;Interactive TypeScript Playground here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`added &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sugar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also allows adding different things into our tea and coffee. In case, we want to restrict what can be added into the coffee, we can use TypeScript's &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types"&gt;Literal Types&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sugar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sugar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// still works&lt;/span&gt;
&lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// compile error: '"lemon"' is not assignable to parameter of type '"sugar"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Type Guards
&lt;/h1&gt;

&lt;p&gt;Type Guards are similar to &lt;code&gt;as&lt;/code&gt; in terms of changing the compile type but additionally add a &lt;em&gt;runtime check&lt;/em&gt;! Note however that since oftentimes we're writing the type guard ourselves, there is still some risk of getting it wrong. So be careful and add unit tests when using more advanced type guards. Let's get started with the most common type guard. The following list is not exhaustive but each one I showcase fixes our problem-case above.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;in&lt;/code&gt; Type Guard
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgCoTsg3gKGcuAE0IBkIBbAexAAoBKALmQDdLhCBuHAXx1EliIUAYUowYEFLnxFCAZQCuAczhR6TVuy68cMBSARhg1AsQCiADzBQ4NABaUwAIQjNocJRCbpMAH2Si4pJ02HjIwDDINABEsmRUINHhIMgOzq7uniHS+KmOLm42ngB0cRTU9BzIAPTVaHLIIKpQlADuAM7IhG0pYHYoYACeAA4DlGgYYdzIEAA27VJh+GkFmRClxIoqanRVtfWNzW2d3a29-chDo5fjgRIQUzw4OAjU7WAEhgpws7ODd5ImACUABeUIyTbKVRMejIEEAPnBuVeIHalFm61mlCUMVkEEIyHaUKg0V2UwANDwuDhZJZrLZEGBvr9-mJ7rsanVZJ0idtkK1gH1KAoPnAQIMZlAWlB2kA"&gt;Interactive TypeScript Playground here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;addLemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TS narrows down the type to Tea&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TS narrows down the type to Coffee&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;added sugar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// adds sugar without any errors&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;in&lt;/code&gt; keyword in JavaScript and TypeScript checks whether a property exists on an object. In the above example, we use it to check whether the &lt;code&gt;addLemon&lt;/code&gt; property exists on the &lt;code&gt;hotBeverage&lt;/code&gt; object &lt;em&gt;at compile time and at runtime&lt;/em&gt;. If it does, TypeScript know it's a &lt;code&gt;Tea&lt;/code&gt; because the other option &lt;code&gt;Coffee&lt;/code&gt; does not have an &lt;code&gt;addLemon&lt;/code&gt; property. On the other hand, if the object does not have an &lt;code&gt;addLemon&lt;/code&gt; property it must be &lt;code&gt;Coffee&lt;/code&gt;. Unlike &lt;code&gt;as&lt;/code&gt;, since &lt;code&gt;in&lt;/code&gt; is a JavaScript keyword it acts at runtime, too.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;instanceof&lt;/code&gt; Type Guard
&lt;/h2&gt;

&lt;p&gt;This type guard is only usable if &lt;code&gt;Tea&lt;/code&gt; or &lt;code&gt;Coffee&lt;/code&gt; are classes. In the above case, they are only interfaces. Let's pretend for a moment that Tea is a class anyway. In this case, we can use the &lt;code&gt;instanceof&lt;/code&gt; type guard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/MYGwhgzhAEAqCmZoG8BQ1pgCZYDLwFsB7AOwAoBKFAX1VtQEsSAXeAJwDMxh5oBhIhw7xeaDNiwBlAK4BzMG0oAuaADciDLAG46qVB2klgzBqUw4AogA9mbMGQAWRZgCF4q9mFnwVCJAB9+QWF4KjFoAHoI6CYIZjAjeEFoZgBPAAdeWWkFLHQYjmhHZzcPO28YkjiEnmS-MPyMJ1d3T28AOgl8YnIKLUjo2EloEgU2IgB3GCxJkhSHXjTMlKI4RHzqaHgQCFFG6GbStvhOnBl5RT6BuGHRtnGp6BmJueYFlIzF1YEhEQ3dVDAUhxTDGHIgECpH4hFTQkTQAC8KHyEnOChUlERAD5kRgMECqkQQCcQERZGQAEQSeBYaAQOQKCl9DYAGjoOlQEmstns3GY4MhcNC-Si5iwMHpF2gEwYbyI0mYmBIqS29yIbAgQA"&gt;Interactive TypeScript Playground here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// instanceof type guard&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotBeverage&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TS narrows down the type to Tea&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TS narrows down the type to Coffee&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;added sugar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// adds sugar without any errors&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  User-Defined Type Guard
&lt;/h2&gt;

&lt;p&gt;User-Defined Type Guards allow us to go beyond what TypeScript can infer from &lt;code&gt;instanceof&lt;/code&gt; and &lt;code&gt;in&lt;/code&gt; type guards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgCoTsg3gKGcuAE0IBkIBbAexAAoBKALmQDdLhCBuHAXx1EliIUAYUowYEFLnxFCAZQCuAczhR6TVuy68cAel3IECgM5hK5ZGACeABxRKFqwjhgKQCMMGrJgx9HBoADyZ-ZAAfZFFxSUZkQJ9jNAxsPGR9SwALaBRVFHI4ECtkAHc4K0SzEqhgSEzfADpkAEkQOsSEOGMIABpm5HgAGwHkACNEAGtLSkyUAANQWctbe0coQnrU4BhkGgAiWTIqEF2fVviAMnOluzE4+oOKbwBeF+Rd13dPal26FPx8KAQMAKKCtMBQBQQLj4XgAoEg1qDLraHAuNweLytWQAUUC4ICGUoYAAQhBmNA4EoICFkhEohIIL9pD5tjRfP4aISSWSKVS6EzUvguaTyVBKRB7sRDtR6Bw0gZUHJkCBVFBKMVEoR1WCstcUJV-KluMgIAMun9-sKeWKqZL5MpVLL5WglSqoGqNcgtcUdfrllNImIGUaeKiENRTAQPI4hlZ6ZImPGUE8LbJFCooEx6MgngA+C34cMgYyUAYSgaUJQ0ADksgghGQxgdUGrdCN3R4XBwOLxYpoiGBcFjSbocvSskSTYzJRqhIUYAIhRN7soUGMQA"&gt;Interactive TS Playground here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// custom type guard&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isTea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;addLemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addLemon&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isTea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TS narrows down the type to Tea&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hotBeverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// TS narrows down the type to Coffee&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;addSugar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;added sugar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;addExtra&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actuallyCoffee&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// adds sugar without any errors&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The type guard &lt;code&gt;isTea&lt;/code&gt; is a function that receives a single parameter, returns a boolean, and is marked with &lt;code&gt;x is Tea&lt;/code&gt;. More generally, it's marked with &lt;code&gt;myParameter is MyType&lt;/code&gt;. TypeScript will use it to narrow down the type in the &lt;code&gt;if-statement&lt;/code&gt; of &lt;code&gt;addExtra&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript trusts us in writing proper User-Defined Type Guards
&lt;/h2&gt;

&lt;p&gt;The fact that TypeScript trusts us in implementing a proper user-defined type guard can be shown easily.&lt;br&gt;
Take a look at the following, obviously wrong type guard. TypeScript believes in our abilities and won't budge - the executed JavaScript will.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/MYGwhgzhAEAqCmZoG8BQ1pgCZYDLwFsB7AOwAoBKFAX1VtQDMBXE4AFwEtToOIEwyADwBc0FgGsSRAO4kKowTxj8U6aACd4bJupLQ26pvADcdVKmCkIbaAHN1HAF6OQATwBCiddAC8NUxwM0GS8-GT2Ti4eXhRUaBgA9Al2WjDwgvDATGzwWGoRzm6eYOoAdNh4hKSUxtBJ0FLQlgQADhwg8NDw6upE6gA00ABG2ZgaLJwEnd296nRAA"&gt;Interactive TypeScript Playground here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isTea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;grizzlyBear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isTea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grizzlyBear&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// gets executed&lt;/span&gt;
  &lt;span class="nx"&gt;grizzlyBear&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addLemon&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// no compile error, but a runtime error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simply says everything is &lt;code&gt;Tea&lt;/code&gt;. Even though it would be a nice world to live in, that's not how it works in real life. 🙂&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What about &lt;code&gt;&amp;lt;MyType&amp;gt;&lt;/code&gt;?
&lt;/h1&gt;

&lt;p&gt;You might have seen Type Assertions in the form &lt;code&gt;const tea = &amp;lt;Tea&amp;gt;{color: 'green'}&lt;/code&gt; before. This is the same as &lt;code&gt;as Tea&lt;/code&gt;. So again, it doesn't change any runtime behavior, leaving ourselves open for bad surprises.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;MyType&amp;gt;&lt;/code&gt; syntax has been deprecated because it becomes confusing in the context of &lt;code&gt;.jsx&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt; files as you might encounter using React. Both use the same syntax. Thus, TypeScript recommends always using &lt;code&gt;as MyType&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TypeScript recommends always using &lt;code&gt;as MyType&lt;/code&gt; instead of &lt;code&gt;&amp;lt;MyType&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To clarify, take a look at this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;beverage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;;
return &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;beverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have a &lt;em&gt;component&lt;/em&gt; named &lt;code&gt;Tea&lt;/code&gt; but also a variable &lt;code&gt;beverage&lt;/code&gt; with a type assertion of &lt;em&gt;type&lt;/em&gt; &lt;code&gt;Tea&lt;/code&gt;. If you are confused now, that's intended. 🙃 With &lt;code&gt;as Tea&lt;/code&gt; it's slightly easier to identify whether we talk about a component or a type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;beverage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Tea&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tea&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;beverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Tea&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What about the new &lt;code&gt;satisfies&lt;/code&gt; keyword?
&lt;/h1&gt;

&lt;p&gt;The upcoming &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-9-beta/#hamilton"&gt;TypeScript 4.9&lt;/a&gt; brings in the new keyword &lt;code&gt;satisfies&lt;/code&gt;. Functionally, it acts very similar to &lt;code&gt;as&lt;/code&gt; with the additional benefit of not broadening the type to something more generic. For us, the important lesson here is that &lt;code&gt;satisfies&lt;/code&gt; leaves us &lt;em&gt;just as open to runtime errors&lt;/em&gt; as &lt;code&gt;as&lt;/code&gt; does. So be careful!&lt;/p&gt;

&lt;h1&gt;
  
  
  Closing
&lt;/h1&gt;

&lt;p&gt;Wanna learn more about TypeScript? Then hit subscribe on the blog, and join me on &lt;a href="https://www.twitch.tv/typescriptteatime"&gt;Twitch TypeScriptTeatime&lt;/a&gt;! Looking forward to see you!&lt;/p&gt;

&lt;h1&gt;
  
  
  Recommended Reading
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://basarat.gitbook.io/typescript/type-system/type-assertion"&gt;basarat's TypeScript book - Type Assertions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types"&gt;TypeScript docs - Type Guards&lt;/a&gt; (deprecated page but there's no official replacement about Type Guards at time of writing)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#instanceof-type-guards"&gt;TypeScript docs - instanceof Type Guards&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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