<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Prithpal Sooriya</title>
    <description>The latest articles on DEV Community by Prithpal Sooriya (@prithpalsooriya).</description>
    <link>https://dev.to/prithpalsooriya</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%2F71292%2Faf2bbd4e-a0cb-4e01-b26a-c7fda2b01db8.png</url>
      <title>DEV Community: Prithpal Sooriya</title>
      <link>https://dev.to/prithpalsooriya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prithpalsooriya"/>
    <language>en</language>
    <item>
      <title>Advanced TypeScript - typing JSON/Resource files.</title>
      <dc:creator>Prithpal Sooriya</dc:creator>
      <pubDate>Sat, 11 Sep 2021 22:11:16 +0000</pubDate>
      <link>https://dev.to/prithpalsooriya/advanced-typescript-typing-json-resource-files-4h62</link>
      <guid>https://dev.to/prithpalsooriya/advanced-typescript-typing-json-resource-files-4h62</guid>
      <description>&lt;p&gt;By setting &lt;code&gt;resolveJsonModule&lt;/code&gt; in your &lt;code&gt;tsconfig&lt;/code&gt; to true, TypeScript will attempt to get the type/shape of the JSON for you.&lt;/p&gt;

&lt;p&gt;We can use this to provide better type safety and auto complete for functions that use the JSON files.&lt;/p&gt;

&lt;p&gt;For example typing i18n/resource. Either for custom solutions, library wrappers, or for libraries themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using existing/static imports.
&lt;/h2&gt;

&lt;p&gt;Static imports are the usual imports you see at the top of the file.&lt;/p&gt;

&lt;p&gt;If we are already statically importing our JSON resource, we can use &lt;code&gt;typeof&lt;/code&gt; &amp;amp; &lt;code&gt;keyof&lt;/code&gt; to get its type and keys.&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="nx"&gt;Resources&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./resource.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ResourceKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Resources&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Index to keys path if complex.&lt;/span&gt;
&lt;span class="c1"&gt;// type ResourceKeys = keyof typeof Resources['path']['to']['key']&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;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResourceKeys&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Dynacmic Imports
&lt;/h2&gt;

&lt;p&gt;If we are worried about the import cost, then we can use dynamic imports for our actual code &amp;amp; type imports for the TypeScript types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Type only import.&lt;/span&gt;
&lt;span class="c1"&gt;// Stripped when transpiled&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Resources&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./resource.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ResourceKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Resources&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Dynamic import&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./resource.json&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResourceKeys&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your version of TypeScript does not support typed imports, then we can extract out the types to separate file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ResourceTypes.ts&lt;/span&gt;
&lt;span class="cm"&gt;/*
  Import is only used for type (no JS code).
  This file only contains types.
  &amp;gt; Will get transpiled to an empty file
  &amp;gt; Will be tree shaken out of bundle.
*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Resources&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./resource.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ResourceKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Resources&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Declaration Files
&lt;/h2&gt;

&lt;p&gt;Finally we could modify/use declaration files. This is great if you are using a library E.g. &lt;a href="https://react.i18next.com/latest/typescript"&gt;i18next docs&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;We have successfully used this to provide auto-complete &amp;amp; type safety. We have even spotted missing or misspelled keys!&lt;/p&gt;

&lt;p&gt;One caveat is that we had to restart our TS server if our resources were modified or new keys were added. I think this was due to our large resources, or maybe due to caching done on the TS server?&lt;br&gt;&lt;br&gt;
But a relatively small price to get this type safety.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>json</category>
      <category>internationalisation</category>
      <category>i18n</category>
    </item>
    <item>
      <title>How to Type React DefaultProps</title>
      <dc:creator>Prithpal Sooriya</dc:creator>
      <pubDate>Thu, 22 Jul 2021 07:58:47 +0000</pubDate>
      <link>https://dev.to/prithpalsooriya/how-to-type-react-defaultprops-ji6</link>
      <guid>https://dev.to/prithpalsooriya/how-to-type-react-defaultprops-ji6</guid>
      <description>&lt;h2&gt;
  
  
  Situation/Background
&lt;/h2&gt;

&lt;p&gt;We have inherited an old complex class-based component that took an array of items and rendered them.&lt;br&gt;
It had a similar structure to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ListProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;filterPredicate&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;onSelect&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;onMultiSelect&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;createKey&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ... a lot of props&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListProps&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;static&lt;/span&gt; &lt;span class="na"&gt;defaultProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListProps&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="c1"&gt;// defaults for most props except `items`&lt;/span&gt;
    &lt;span class="c1"&gt;// because we want it will always be required right??&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;This component was treated as an atomic component and, since it has stuck around for ~3 years, a lot of other components have used it to build their UI's.&lt;/p&gt;

&lt;p&gt;This component did not lack tests, it was quite thoroughly tested. Again the test structure looked similar to this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ListProps&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;./ListComponent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ListProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="cm"&gt;/*...*/&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// Then some enzyme tests using props&lt;/span&gt;
&lt;span class="c1"&gt;// NOTE that all tests were strictly typed &amp;amp; used the exported ListProps type to create the test props&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Back to the present
&lt;/h2&gt;

&lt;p&gt;Some new logic was added to one of these components that inherited the List component.&lt;/p&gt;

&lt;p&gt;Everything was working as expected until we hit our &lt;strong&gt;&lt;em&gt;favourite&lt;/em&gt;&lt;/strong&gt; runtime error:&lt;br&gt;
&lt;code&gt;Cannot read property 'length' of undefined&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But why?? Everything was strictly typed, how did this fall through?&lt;/p&gt;

&lt;p&gt;It turned out this new logic could potentially return an undefined list of items (&lt;code&gt;string[] | undefined&lt;/code&gt;). But TypeScript should have picked this up when we used it as a prop for our List component, so why did we not get any errors about this?&lt;/p&gt;
&lt;h2&gt;
  
  
  Default Props and Merged Props.
&lt;/h2&gt;

&lt;p&gt;The type &lt;code&gt;ListProps&lt;/code&gt; for our component is NOT the true &amp;amp; final prop types when we are instantiating the new JSX List element. It merges the props we provide it at the start (the &lt;code&gt;extends React.Component&amp;lt;ListProps&amp;gt;&lt;/code&gt;) with the &lt;code&gt;typeof defaultProps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here it is in the &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ca8eefc03c4553f3bda93b4ab33a3e504f18cfb4/types/react/v16/index.d.ts#L3027"&gt;DefinitelyTyped repo&lt;/a&gt; (see &lt;code&gt;Defaultize&lt;/code&gt; type), but a simplified version is shown below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// simplified version of the DefinitelyTyped - Defaultize utility&lt;/span&gt;
&lt;span class="c1"&gt;// Under the hood, the merge takes:&lt;/span&gt;
&lt;span class="c1"&gt;// - the default props (and makes them all optional),&lt;/span&gt;
&lt;span class="c1"&gt;// - and the remaining original props&lt;/span&gt;
&lt;span class="nx"&gt;MergeProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DefaultProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DefaultProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
  &lt;span class="nx"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;DefaultProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So what is the type of our default props? Thats right we strictly made it &lt;code&gt;Partial&lt;/code&gt;!&lt;br&gt;
So plugging this in the &lt;code&gt;MergeProps&lt;/code&gt; utility, we can see it makes all of our props optional.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FinalProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MergeProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// this returns string | undefined! Proof that our items have become optional!&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FinalProps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Proof Identity - the above merged props is the same as Partial of all props.&lt;/span&gt;
&lt;span class="c1"&gt;// A = B -&amp;gt; true&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Identity1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FinalProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// B = A -&amp;gt; true&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Identity2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;FinalProps&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// (A = B) &amp;amp; (B = A) -&amp;gt; true! It is identical.&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;IdentityProof&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Identity1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Identity2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So our final props are optional/&lt;code&gt;Partial&lt;/code&gt;. You can even see the incorrect typings via IntelliSense:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n1l92-wz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/PartialDefaultPropTypes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n1l92-wz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/PartialDefaultPropTypes.png" alt="JSX Component where props have become partial"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is also the reason why we didn't see this in our tests - we were relying too much on our exported &lt;code&gt;ListProps&lt;/code&gt; type, when in actuality we should have tested with this merged type to cover these missed test cases!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whats worse is that this pattern was used in a lot of other legacy class components&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
What are we going to do 😬😬😬?&lt;/p&gt;
&lt;h2&gt;
  
  
  Fixing our Default Props!
&lt;/h2&gt;

&lt;p&gt;We want our &lt;code&gt;defaultProps&lt;/code&gt; to be strictly typed, it follows our developer standards &amp;amp; we want to have that wonderful IntelliSense, type safety &amp;amp; ability to easily refactor our props.&lt;/p&gt;

&lt;p&gt;After some reading, one of the recommended ways of typing it is to split out our Large interface into smaller interfaces &amp;amp; merge them:&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;RawProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;DefaultProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;onSelect&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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="k"&gt;void&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;defaultProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DefaultProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* yay Typesafety, IntelliSense &amp;amp; Refactoring */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However this wasn't really feasible for this old component - it already had a huge list of props &amp;amp; decoupling would have taken quite a lot of time (especially for all the other legacy components).&lt;/p&gt;

&lt;p&gt;Instead we can &lt;code&gt;Pick&lt;/code&gt; our default props, and using a utility, we can correctly infer our &lt;code&gt;Pick&lt;/code&gt; type (instead of manually writing a large &lt;code&gt;Pick&lt;/code&gt;) &amp;amp; still have our wonderful IntelliSense/Type Safety/Ability to Refactor.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// implicit pick utility&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buildImplicitPick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;props&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;defaultListProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buildImplicitPick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;defaultProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultListProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="cm"&gt;/* yay Typesafety, IntelliSense &amp;amp; Refactoring */&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;TypeScript is super powerful and can resolve most mistakes that could appear are runtime right as your are typing - a very small feedback loop!&lt;br&gt;
&lt;strong&gt;However bad types &amp;amp; relying too much on strict, predefined types can blindside us/introduce type holes where we lose our type safety.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It was understandable why this happened on these legacy components, since it was also our first time using TypeScript.&lt;br&gt;
In the future we can mitigate the above by spending time to ensure that the type we get/want to use is correct &amp;amp; even introduce type tests to validate our types.&lt;/p&gt;

&lt;p&gt;Now back to fixing these new TS errors 🙃.&lt;/p&gt;
&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CodeSandbox link to show the problems and solutions mentioned.&lt;br&gt;
&lt;a href="https://codesandbox.io/s/xenodochial-framework-tq7dx?file=/src/App.tsx"&gt;https://codesandbox.io/s/xenodochial-framework-tq7dx?file=/src/App.tsx&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Link to my article that explains the type safe implicit pick utility.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/prithpalsooriya" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L_JJgEJf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--A5UlhIs1--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/71292/af2bbd4e-a0cb-4e01-b26a-c7fda2b01db8.png" alt="prithpalsooriya"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/prithpalsooriya/how-to-create-a-type-safe-implicit-pick-2jpa" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How To Create a Type-Safe Implicit Pick&lt;/h2&gt;
      &lt;h3&gt;Prithpal Sooriya ・ Jun 29 ・ 4 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#developerexperience&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>components</category>
      <category>bugfix</category>
    </item>
    <item>
      <title>How To Create a Type-Safe Implicit Pick</title>
      <dc:creator>Prithpal Sooriya</dc:creator>
      <pubDate>Tue, 29 Jun 2021 21:43:53 +0000</pubDate>
      <link>https://dev.to/prithpalsooriya/how-to-create-a-type-safe-implicit-pick-2jpa</link>
      <guid>https://dev.to/prithpalsooriya/how-to-create-a-type-safe-implicit-pick-2jpa</guid>
      <description>&lt;p&gt;This article discusses the implementation of an implicit pick, the reason for it &amp;amp; what makes it special.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?jsx=0#code/PTDECcFMHMEsHsB2ACAypALgVwA7ILTICiAHgIYC2OANpMgJKIaTgBmZAxnWYgCbIckAZywVYiaMlZZEHDAkQA6AFDjmbTnQAK4eLyxzkAb2XJksXgC5kQjOHHQA3KeQ57Xa4lEAjFs7OIlJDWtvYS-si8kEIc9jjySCF2DhFkWBgAFvDgSWFOLrxkzNYAIkWQERzl0NkAnrkpygC+ylEc1GRQAsIYNvAUkKjJEgDCwqIOAGIycgrWABShDRIAlMgAvAB8yABu8BbOIKCQfFBwSMrKR2cKxORUtMjwrMhanfJk1FcAVN+m38gAOp0ISQOiZIrITJ0HDvWCfZCQe40bjUajwADuQmQWGxGHgrngOCwHWYUIydFYsEg1F42IxdAxPF6rF0FFeun0chUyABAAlMZAdixzC8GcgmUwoQTOFwhHiKU9vAArSByAA0EpBYPJkOhrl0OGxZGxtlgaKe8QUnx5ANQBPE5PgoIEJuiyHm2VdoPpFJQ4slvVCsDkIowtRw0RWmoDzNeIYA1gBCf7AZSCRC2Vxwz6kSgo6xvcAfagAHh0egMGG262M5isyAARABGRuawIDayNgBCUDIvEbyCaznDkdeOeoeYekAAKhG6LXR5Bntni-DJ8jaI5kCA6xYAPzLaDtoKHmzDY-IRTXpo7tDyC1kcdrz7lzlVzbKJfPktTlEVnA5zHRd5xXWEXw3fNaEUA4d2Ac88mQAAfHE+EgKlEEgXhLl3ABBcBoFEE5ehXb8AHJgwkZDUKiDCsLI8xsUQeBehNIRYGgQJvEefFVyCdQnhecjKOgMiVCEfpBgvMZMwmCRplkBJEHmcDf03SBFA7SAVkOMATl4G4LiuMBDJQP9HhXLREx+P5eXjDgE2QOBhWxXFkB4JVVUMDFYEyJ5EGoWpyUpalaXpOgqi6MhvHgdJbSBEEH2oZAMjIYUoXnGwyFYTBak1NJeMEaclI9EYZwAJQAGWQABqNAtFwkYiDWAAydzvHNXygt4qB2DkL15g4VKJEgYAoAoeBhTWNwiSEeLu3SLUUrS8EMlgbFG30GgQyKBRB1IiMHCeLBwANWaCGQZspC9WJIF2qj9SshyPRnVBkEqnheB09y+Eu67Tv1ThsAReAVTVXp5gAKTej6+BWf5kAAWQ4jJemY3pfGQCgDAyQSfsYkRKS9IQKE+WhTrUFg+uiTVvEWqoUExiauhXDz1sJ4AeGY2oeC4f7kA6AiRUpjQ5VtBHKswPFwCC277skNmHhDXz7Mc6RFIUW002-J6EywgDsVrXW30rDUmwsQcUMbNwQ0gS2my0+3GyqZgahlxtNmcDMsxwRNzOCVX9cNQ3jBcCwu1bdUXBtjxkAAVkUAAGKOAiCLtvD7AcU9dV26i7bsyD1mXkDakZC+iNtmhHTLdf9oCFwyyMwL99Tt13Ix6yPTUY4DrwKF8cAT07BCHE1F2YDzkeqJaHWW6gyAAPrjZG+XF5fYc-3NKCNv4JE5QJIGIY8hkkQxHkmYlJUufpy3gYdOM45ThgBQcJM5+kAYJWOBV3XkAANRYOxD+zYbIIxnGtbE6tZgfx8o+NEmIcR4gJHLMkittrfwwIFQO-BQZeV6IAHg3ACR+wjYE55zTJVSulb8Qhsq5RLu1Tq4ZpTIF6kDAaQ0eDQFGuNSa2kzpGninyAA8oCIgf8iDlXMEGMEFAFSQnFOiLMsVToFWQf0FEJV5hlSqrVeqjVmrMJwESEk5RjqnVweDeKpCkBYK4b0V6iJwC6HAEIYAAx5RkC4diWAQk1oSGxDUCUugJDXkUMgOmaMHSIFYNkUmJUMR+gEH2eQD1FQWLkP8MBEDGJPATGQPK4TFr0HJOIRy4oGaRAJL4DAAlAC8G4AOD3Uzph6IU80vB6Bf18rrAB4ArrrBcKWGcmx5hrC2AMgA0oiEgzA+DYj1rUFcQyVLB0LImQZmpxmbBWKshy6zkCbI2J+MwZgZpGi9i02AnSMAVi5NcxMPS+mtNpB09BXT7ksGbCbW5wz77e16Jc15dyHIPOXgC6gytrnvjkN0j58wTBmF3BVAAmgwGcF0tEVWqnVVADUmprF4PAd06MnKwHSm5HgQVVHdGKrcGJp1TnhVdCgXEkAw4NhbJXE57gA4J2Ti4LS6dM6cpzhPGW+dy7F1LuXIQlcmj32-C88FGCYW9KXiBJuLwwUQpVc2Hee4GwiW7tyzwPgWBDwDoakVbt6hT0kDPTKirtXvN6YvTK6rV7mCuTq2+FQ4K2v3pJI+DgT5yWgApaByktXKudc2H198jj6VMq-CA78UCOowarf+gDbgACYLo+T8lSoqGiFApmAL8BGuEGQH0gEmBKyBmIYmWulNBSqf6JieVEU6BbcZFvUbQJSWS6CkzgBwSIPicpQFkAHfUItQQRpXvzfUUCSriGJBgYA4F+IsEyXZcBMIJzuXgViYK3RZIDABgSWE8pzAoAZfQmaOwLCrW4OkNRxUNII0YOoedKTJAq1gclKAXIX0rzceXU91DIzfypGOz0AVuqKiXKaVKwHwmYAZCcKEGICTIfcl0FlX0ml-M7emt5z1+lmEGT8w5EypkzLpMgeZizhkMsLBOaj9DjYzg2VsnZCY9kHLGcc-hQhnDNMzBjLAbSblVmXnTNpZGgUCdk3IH55zJOuETEHU2vRawKdpKpjAcK2UR2FT3awvLs4CqbBnO6WcXDj2teKouQUpV6xlVHOV1cxy6x07c5eS5m4OX81WPVHdw62qNbbE1-czUNrTlFq1k8RJDi-DXbTvAKwcCrK64CK9gt6yy1CjAPq9V7xrUG0Y4wz5hovgoK+IXiu6bjbpR+BlU1AA"&gt;Here is a Typescript Playground with examples&lt;/a&gt; that will be used as a reference. Can also be found via my Github Repo.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Prithpal-Sooriya"&gt;
        Prithpal-Sooriya
      &lt;/a&gt; / &lt;a href="https://github.com/Prithpal-Sooriya/ts-implicit-pick"&gt;
        ts-implicit-pick
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Example of an implicit pick.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Why an implicit Pick? Why not Partial?
&lt;/h2&gt;

&lt;p&gt;Partial is great if you want to create an object with some of the values from a given interface. However when the object is used (via property access or through some consuming type), the object still is a &lt;code&gt;Partial&lt;/code&gt; - as in all properties are optional, even if you have provided a value.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VyJDGUnI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/PartialExample.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VyJDGUnI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/PartialExample.png" alt="Example of Partial" width="880" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In these cases, what we really want is a &lt;code&gt;Pick&lt;/code&gt;ed object - an object with the properties we want "picked" out of the original interface.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Verbosity of Pick
&lt;/h2&gt;

&lt;p&gt;Pick is perfect, it gives us the exact strict type that we want, however (as shown) it is very verbose.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3tfJ2hiq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/PickExample.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3tfJ2hiq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/PickExample.png" alt="Example of Pick" width="880" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For each prop we want, we need to write it for the &lt;code&gt;type&lt;/code&gt; as well as for the object.&lt;br&gt;
For small objects, this might not be much of an issue - however this can become very large the more props we want.&lt;/p&gt;

&lt;p&gt;So now lets design an implicit pick!&lt;/p&gt;
&lt;h2&gt;
  
  
  1st Implicit Pick - Okay, But No IntelliSense 😢
&lt;/h2&gt;

&lt;p&gt;Here is the design of the initial implicit Pick.&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;buildImplicitPickVer1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pickProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buildImplicitPickVer1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;implicitProduct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pickProduct&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;T&amp;gt;() =&amp;gt;&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The is a factory function part that allows you to build a pick on whatever type you provide it.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;K extends keyof T&amp;gt;&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;We have a generic type &lt;code&gt;K&lt;/code&gt; that is constrained to the type given in the factory.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(props: Pick&amp;lt;T, K&amp;gt;): Pick&amp;lt;T, K&amp;gt;&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;this parameter gets inferred as the developer types in the keys of their object.&lt;/li&gt;
&lt;li&gt;Invalid keys will give us an error (since does not match the Generic type)&lt;/li&gt;
&lt;li&gt;Invalid values for the key will give us an error, since it won't match the &lt;code&gt;Pick&lt;/code&gt;ed object values.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly what we want - a type-safe implicit pick! Refactored changes (renaming/removing) on the interface will propagate through to the objects too!&lt;/p&gt;

&lt;p&gt;Well... after some usage I found that it didn't really give a good Developer Experience (DX).&lt;/p&gt;

&lt;p&gt;IntelliSense/auto-complete (via &lt;code&gt;CTRL + SPACE&lt;/code&gt;) doesn't give us any useful information on what props we can use.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7TP2-WgO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/ImplicitPickNoAutoComplete.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7TP2-WgO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/ImplicitPickNoAutoComplete.png" alt="Implicit Pick with no IntelliSense" width="731" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Only once we start typing do we get errors if a key does not match the interface, we aren't able to get a list of all keys that we can use.&lt;/p&gt;

&lt;p&gt;This is because our parameter type in our factory function &lt;code&gt;Pick&amp;lt;T, K&amp;gt;&lt;/code&gt; relies on keys given. Lets fix that!&lt;/p&gt;
&lt;h2&gt;
  
  
  Implicit Pick with Great Dev Experience!
&lt;/h2&gt;

&lt;p&gt;Here is the the solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buildImplicitPick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The small change that made the huge difference is the intersection type &lt;code&gt;Partial&amp;lt;T&amp;gt; &amp;amp; Pick&amp;lt;T, K&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; give us the ability to get back our auto complete for keys.&lt;/li&gt;
&lt;li&gt;Intersecting is with the Pick &lt;code&gt;&amp;amp; Pick&amp;lt;T, K&amp;gt;&lt;/code&gt; ensures that we get the correct type for our key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Intersection above means that we take only the props/types that match in both types given.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type A = { a: number | undefined }
type B = { a: number }
type C = A &amp;amp; B; // will be { a: number } since that is what both types above have.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whats awesome is that we can see the IntelliSense working in real time!&lt;br&gt;
When we &lt;code&gt;CTRL + SPACE&lt;/code&gt; to see what props are available, they are all optional because of the &lt;code&gt;Partial&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LJr7Br1h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/ImplicitPickAutoCompleteKey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LJr7Br1h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/ImplicitPickAutoCompleteKey.png" alt="Implicit Pick With IntelliSense info for the keys" width="495" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But as soon as we select a property to use, it becomes required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;because the Generic &lt;code&gt;K&lt;/code&gt; keys are updated;&lt;/li&gt;
&lt;li&gt;subsequently so is the &lt;code&gt;Pick&amp;lt;T, K&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;and finally the intersection &lt;code&gt;Partial&amp;lt;T&amp;gt; &amp;amp; Pick&amp;lt;T, K&amp;gt;&lt;/code&gt; enforces are type to be required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WkyuNJDU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/ImplicitPickAutoCompleteValue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WkyuNJDU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/Prithpal-Sooriya/ts-implicit-pick/main/images/ImplicitPickAutoCompleteValue.png" alt="Implicit Pick With IntelliSense info for the value" width="316" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Above shows how to write a type-safe, refactor-safe implicit Pick function with useful IntelliSense information.&lt;/p&gt;

&lt;p&gt;The function itself is rather simple, but the main takeaway for me is to try/test out different type implementations to provide better IntelliSense information &amp;amp; better developer experience (DX).&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>productivity</category>
      <category>showdev</category>
      <category>devrel</category>
    </item>
    <item>
      <title>FizzBuzz... but only using TypeScript Types</title>
      <dc:creator>Prithpal Sooriya</dc:creator>
      <pubDate>Sun, 04 Apr 2021 14:57:26 +0000</pubDate>
      <link>https://dev.to/prithpalsooriya/fizzbuzz-but-only-using-typescript-types-4j4</link>
      <guid>https://dev.to/prithpalsooriya/fizzbuzz-but-only-using-typescript-types-4j4</guid>
      <description>&lt;p&gt;Typescript 4.1 has released some awesome new features, including &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html#template-literal-types" rel="noopener noreferrer"&gt;Template Literals&lt;/a&gt; - which enable some really powerful stuff!&lt;/p&gt;

&lt;p&gt;To try it out, I've done the generic FizzBuzz test only using Typescript Types!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Prithpal-Sooriya" rel="noopener noreferrer"&gt;
        Prithpal-Sooriya
      &lt;/a&gt; / &lt;a href="https://github.com/Prithpal-Sooriya/ts-fizz-buzz" rel="noopener noreferrer"&gt;
        ts-fizz-buzz
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The generic Fizz Buzz test built entirely with TypeScript type annotations.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ts-fizz-buzz&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;The generic Fizz Buzz test built entirely with TypeScript type annotations.&lt;br&gt;
This means that is works solely on typescript types - so it is a compile time Fizz Buzz "Solution".&lt;br&gt;
And using VSCode IntelliSense you see the solution without even "running" your code!&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Prithpal-Sooriya/ts-fizz-buzz/images/IntelliSense-Screenshot.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPrithpal-Sooriya%2Fts-fizz-buzz%2Fimages%2FIntelliSense-Screenshot.png" alt="IntelliSense Example"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;See a live demo&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/PQKhCgAIUgxBLAXoyAhArsyAVAngBwFNIBBAOzIHsAXAQ2vkrIGcoJpIB1Ygd1rOqRqlSPlrNmkeGUj9ZAJ3m1cssgBNI8wtXTyWqhUpXUAFvQBcbSNYBKhfABtaAY0KSy6ALYAjQvMlq8ABu8Mzw3g7E3ioAGkIiAAYIyAlWtvZOru5evv6QgSFhEVEqAJrxkADkGMiVaZB2ji5ukB4+fgHBoeGRkNGQcQBkkOXCVcmINYh1HNYAkgBmrTT5XUWRADRCJoQyWjp62-StOX5swODgwMAAxFoA5owyBd3e8A7w1Lg26JHMAHTUSQAWkgAGEmHRpJJTMR5L83MB8FpAs56C10MxCBoxs4ds4ANZSJa0E7teRSSSkibAKa02hYAAUtAJpPgJLJuUpq0KPUIAEorjBsDssQpiLDNAjJDxiJiJSI8YRCRUscR2bJOX5uS91iVNa55FCZG1cv9oBcrsA4JQKcxKJ5iKaOpBZZA0TJ5dtiAARNbhd6fFQ-P4VJUqjWk50U0I816Rf5WyAmajUfDMczXXb-HjwAnwIiBWj-W33YC5-PAP28t4fL4AfXhkUu10gAFZINXXoGvlLNq7iEwHCoyIRsRUHJRKETjk5mIJAo9BMM1cSpIJY6SAAyQW3txOEAAe+Ftgi+REgc2YXb1qFwbYAPNhIEfqLs1NlyQA+SAAXkgCQACQAN7YAAvgkL6Hm+6iSEBwHSAs2oAPKwvIfpLswYEgTuAA+7YQZAAD8QjwsQ5iQAstAOFiADcLbWgATJ2-q1kGfaEFsbpDiOY44iIk7TrIghzgu8BLpAK5jmunzctuWyMVsAAsWwAGy7hSAAc4BHieRpCAQxBXjefJ3oxT5QTBH5avIP7-vB4GQa+75wSBiEoWhGGfFhOGQPhzH4UpfmQOp+GaYRJHUGRkAUVRNGEPRSYAKosLo6pLLJsYnhIfIVPcux+OimoAMwsTWPYqE2cphGQ9zuroWgCJAQQdE8u5LHgRDMM48gFtQ4DnsQCBkJ8hDFdg6COMQ-4ANpQJAW5bMValbAAnFsACMimQBtbabZpCkbQpKmQIxADsS2LZAxXLfNxWqUt62QEp21KXtz0He2R3tidbYXSFV2qctIUPfNqlPWd21ne9Z2fZp32aSdmn-atV2rcDq0PZAq2reAAC6OnHqeBkXsZrGRHexUWc5sE2XZOCWS5cDSKN42TZEM3RnjxGkeg5GUdRdEMTc74PE8wti0wUjqEegIgu6kK0NCzNYFM4KUGonHJpQLUUjr2oAEQAKLHsqb5qAbJMtGMq6SlozC-P1rYirGsZjFonj696NnCS+6jtZoyq6GELUK2QaIwfQbXSCrkyYCgviTjwiatkb-z3OaEwnRM23-HnA2GQ0hCey12BKIGtUAHKnPID4AMpRYztPzr1tXBdGWzPjT1nRnZ83wQ38iEd3rkIWQSEUnY87YaBEVF-OMWQIPDGQAAEoQDhEBSg0VLQ3gty4Z47IHzjB21wzOEwuthEwBcXhC4f0FM1PQUzHdoPHAAKKLwBHhD03YEuhAy5Kw+FXGuD4JjP2wFsDwDgHBbCmN-bEv90Rfk7l+FsMAJgfywDveUGgFh7hqvcXo0YLSEz0meQuUD44vysp+XIWwJjINREVf8ZMawU1wFTbA6DcGIFYagt8f5LzXnJoQO8j4+F92sCwn+f8m7WSinzHmSQkCIBAg-CO0DEFfwUWgwilhrBIIMSIkevNiAkQSFMSCxicBYNjgIq2kACGUT3HIWgihlAB2jJIEAFxWx1z4Pgb2uoAx1kqtKaW2xYxgmoqfJwb5aFYFoGoWg+A3zbxEFFFQgQFgT12IIKqrAd7xIcIk9EKTED0LfjXem1SnxbE4fGSRPCnz8Jabee8HTMGtjKQk34VSNHQKUYwvwDSRl0JgWIkyxQzIdOaeIrhbTpFfkwbpYmO9qkkG8bgB8uyKQWOjDNPG9NgLzRmgAaRiQSQguBKBLEOXjCi5TKnJKmcgA5ihrnc2GL3cAYFLg7zmGQfA6BqCHJ8bNeaV1vrbWBr9FakB-qfXWvNDacLvpbU2sDDaJ1dqbSxhtf6G1PobXRdYRiV1GLwu2oxYGjETqMXeoxLG50FKfUYpS66V1irfWKgi4GxUTrFXevdJa-1iqfWKjypSV0lLfRespRFJ03rKSxkpf6SlPpKR5W2K6bZvptm2m2YGbZfrvTbFjP6Ww2yfTbDy1SgNvqqW2kDNSJ1VLvVUljVS-1VKfXBhseaZ0rpnW+pDLYZ1gZnROtDaNWMzr-VhtGnlmkrrwy2JpbamlgaI2ze9TSWNkbZrhjy1Ga1vqrW2ujNaJ1VrvUxmtFGaLcZ40Sq2TgnwTBOP-MDNW-42zmhNkQZw5sKIzQNtUg2m0FJbGnRo2dz0F1TGXYu5Ay7UULomOutdWw87-AJjvUdZtsTVNETsvZD5QXgshXszBjjgSghwWrVADIUDPooanV+6hpB1QvWMOgdzrqiDMW4Fe69N7akGjCEQe8D7jpPmfW+ZSmA6Pju+r5Xdf09xrno5AQi-6II-URtBojAH6xARXe41dyQPnmtUrDNSZlwIQQIsjb4SOEfA+g+a2BwCYLQ4-agzHam03fsxzj-8KPFyo+XMBtGIGMc+ZMD9TSTjwNgb8djUneMhusAJx9mz9LbNU2J-jYybIGdjtJ0RXTTK4HMnwmzpiUGKI4cs1plNFnzT0+59hsyJFSI6fNWRtnwNWZUVYgCEwtHoafph9TMy3NsK42gUjvGjF+f0QF8xuGYTRWsVMeLImxMpcy3l-+2WTGVbS8QCx0W1HMbsfxxKAyKlDI+cgKY5WrO90veZ5LSy5ncOc50rz3TeETdG6s3plCtk0KG8gKF+zDn9Zrqc85lybkxzuQ8p5igXngkGUkwgTH1OHN+ZJOmgKV7dtMH206BGUD9u469-ckBT3juxJOjdccesfuXd9f7e747rt3auoHO7VNbph5u1d4P4dqYR5AQ9x7C7ffNhdrA-4ceIFWzesFELVt9NuKLQgjwmBAA" rel="nofollow noopener noreferrer"&gt;Playground Link&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Prithpal-Sooriya/ts-fizz-buzz" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;This post is a breakdown/explanation of the types created &amp;amp; used in the Repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outline &amp;amp; Plan.
&lt;/h2&gt;

&lt;p&gt;FizzBuzz is a basic programming task that is (was?) used in interviews.&lt;br&gt;
For those who've never seen the Fizz Buzz problem here it is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we delve into the solution, I think its worth breaking down the tasks we need to accomplish:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build our Predicate Types. We need a way to see if a number is divisible by 3 or 5.&lt;/li&gt;
&lt;li&gt;Combine our Predicate Types &amp;amp; solve FizzBuzz for a single number.&lt;/li&gt;
&lt;li&gt;Solve FizzBuzz for an array of numbers.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Predicate Types - check the divisibility
&lt;/h2&gt;

&lt;p&gt;We want to check if a number is divisible by 3 or 5, but sadly TypeScript (currently) does not support arithmetic operations - e.g. we can't use a modulus to see if a number is divisible.&lt;/p&gt;

&lt;p&gt;But TS Template Literals now allow us to build some of the &lt;a href="https://en.wikipedia.org/wiki/Divisibility_rule" rel="noopener noreferrer"&gt;divisibility rules&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="c1"&gt;// 5 Divisibility rule, we only need to look at last digit &amp;amp; see if it is a 0 or 5.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;IsDivisibleBy5&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;OtherDigits&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;T extends number&amp;gt;&lt;/code&gt; - This enforces users to only input numbers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;`${T}`&lt;/code&gt; - The back ticks are the new template literal syntax, this allows us to convert the number input into a string.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;`${infer OtherDigits}...`&lt;/code&gt; - the infer acts like a wildcard that is (in this case) a string without the final character.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;`${0 | 5} ? true : false&lt;/code&gt; - checks if the last number is 0 or a 5. It if is, then the Type resolves to &lt;code&gt;true&lt;/code&gt; otherwise &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sadly I couldn't generate the number 3 divisibility rule (since it includes adding each digit, which requires an arithmetic operation), so stuck with a simple union of valid numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Unsure if it is possible to generate a 3 Divisibility rule using current version of Typescript&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Finite3Tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;57&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;63&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;93&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;96&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&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;type&lt;/span&gt; &lt;span class="nx"&gt;IsDivisibleBy3&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Finite3Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fizz Buzz for a single number
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is to remove the number at end of recursive concatenation in FizzBuzz below.&lt;/span&gt;
&lt;span class="c1"&gt;// E.g. Fizz4, Fizz2, ...&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;RemoveTrailingNumber&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Str&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Rest&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Str&lt;/span&gt;

&lt;span class="c1"&gt;// Helper type to abstract the recursion &amp;amp; conversion&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ConcatBuzz&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BuzzPredicate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;RemoveTrailingNumber&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FizzBuzz&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BuzzPredicate&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;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="cm"&gt;/* Fizz Buzz type used for single number */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FizzBuzz&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FizzPredicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IsDivisibleBy3&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;BuzzPredicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IsDivisibleBy5&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;FizzPredicate&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`Fizz&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ConcatBuzz&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BuzzPredicate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;BuzzPredicate&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`Buzz`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nx"&gt;T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea behind it is that it will recursively build the FizzBuzz string. Whenever the &lt;code&gt;Fizz&lt;/code&gt; is found, we can then combine the &lt;code&gt;Buzz&lt;/code&gt; onto it (if found). To prevent the Fizz/Buzz from continuously being concatenated, we set their predicate to &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lets focus on the Main FizzBuzz type, the other types are just helpers to abstract out the recursion &amp;amp; trimming the output.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It takes 3 arguments/generics. &lt;code&gt;T extends number&lt;/code&gt; which is the input; and the Fizz &amp;amp; Buzz Predicates (&lt;code&gt;FizzPredicate&lt;/code&gt; &amp;amp; &lt;code&gt;BuzzPredicate&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If &lt;code&gt;FizzPredicate&lt;/code&gt; is valid, then we start building our string &lt;code&gt;`Fizz${ConcatBuzz&amp;lt;T, BuzzPredicate&amp;gt;}`&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;ConcatBuzz&lt;/code&gt; is just a helper type to abstract away the recursion. It recalls &lt;code&gt;FizzBuzz&lt;/code&gt;, but sets the &lt;code&gt;FizzPredicate&lt;/code&gt; to &lt;code&gt;null&lt;/code&gt;, so the remaining iterations go through the rest of the predicates. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;If &lt;code&gt;BuzzPredicate&lt;/code&gt; is valid, then we just return &lt;code&gt;&lt;code&gt;Buzz&lt;/code&gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally, if none of the predicates are valid then we just return the number.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fizz Buzz for an array
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CalculateFizzBuzz&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FizzBuzz&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IsDivisibleBy3&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IsDivisibleBy5&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FizzBuzzArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Arr&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;Arr&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;CalculateFizzBuzz&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CalculateFizzBuzz&lt;/code&gt; is just a helper type that allows us to simplify &lt;code&gt;FizzBuzzArray&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;Breakdown of &lt;code&gt;FizzBuzzArray&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Arr extends number[]&lt;/code&gt; - enforces that the type must take a number array. This will be our input.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;{ [K in keyof Arr]: ... }&lt;/code&gt; - Arrays can be treated as objects where the keys are the indices. So we can use the &lt;code&gt;keyof&lt;/code&gt; to go through each key/index.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;CalculateFizzBuzz&amp;lt;Arr[K] &amp;amp; number&amp;gt;&lt;/code&gt; - This runs FizzBuzz for this value with the given index. The &lt;code&gt;&amp;amp; number&lt;/code&gt; is the TS intersection type - we can use it to enforce that the given value is a number.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Similarly, we could have used a ternary as well: &lt;code&gt;Arr[K] extends number ? CalculateFizzBuzz&amp;lt;Arr[K]&amp;gt; : never&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Thats it!&lt;br&gt;
Now if we give it an input array, we get the FizzBuzz result out of it!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPrithpal-Sooriya%2Fts-fizz-buzz%2Fblob%2Fmaster%2Fimages%2FIntelliSense-Screenshot.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPrithpal-Sooriya%2Fts-fizz-buzz%2Fblob%2Fmaster%2Fimages%2FIntelliSense-Screenshot.png%3Fraw%3Dtrue" alt="Screenshot of TS FizzBuzz type"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the TS playground in the Github repo for more (&amp;amp; for an extended version of FizzBuzz).&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>types</category>
      <category>fizzbuzz</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
