<?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: Susan Potter</title>
    <description>The latest articles on DEV Community by Susan Potter (@mbbx6spp).</description>
    <link>https://dev.to/mbbx6spp</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%2F606231%2F0a794bd8-17ae-4ea0-923b-0fec3be21e07.jpeg</url>
      <title>DEV Community: Susan Potter</title>
      <link>https://dev.to/mbbx6spp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mbbx6spp"/>
    <language>en</language>
    <item>
      <title>TypeScript's keyof operator and possible uses (Refreshed post, June 2023)</title>
      <dc:creator>Susan Potter</dc:creator>
      <pubDate>Tue, 27 Jun 2023 13:35:00 +0000</pubDate>
      <link>https://dev.to/mbbx6spp/typescripts-keyof-operator-and-possible-uses-refreshed-post-june-2023-1ea2</link>
      <guid>https://dev.to/mbbx6spp/typescripts-keyof-operator-and-possible-uses-refreshed-post-june-2023-1ea2</guid>
      <description>&lt;p&gt;In this article, I'll take you on a journey through the world of TypeScript's &lt;code&gt;keyof&lt;/code&gt; operator and its uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type-safe function parameters
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;keyof&lt;/code&gt; is a nifty operator that lets you dive into the heart of an object type, extracting and manipulating its keys with ease. Imagine dynamically accessing and working with specific properties, performing operations, and crafting utility functions tailored the types properties for added type safety. Say goodbye to boilerplate code for each type and embrace the freedom to create a more generic and reusable 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;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&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;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;obj&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;john@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Below we access the `name` and `age` properties&lt;/span&gt;
&lt;span class="c1"&gt;// programmatically from the keys of the type definition&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: "John"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: 91&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The above runs and typechecks just fine but let's try to pass in the name of a property that does not exist on the Person 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;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;emailAddress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Expected type error:&lt;/span&gt;
&lt;span class="c1"&gt;// Argument of type '"emailAddress"' is not assignable&lt;/span&gt;
&lt;span class="c1"&gt;// to parameter of type 'keyof Person'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, we return to the well with the correct property to retrieve and able to move past the type error:&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: "john@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Type-based return types
&lt;/h2&gt;

&lt;p&gt;TypeScript's &lt;code&gt;keyof&lt;/code&gt; operator can unlock the secret to type property-based return types.&lt;/p&gt;

&lt;p&gt;By combining it with indexed access types (&lt;code&gt;[]&lt;/code&gt;), you can create functions that strictly accept or return values based on the keys of an object. No more accidental typos or invalid arguments slipping through the cracks! Whether you're dealing with dynamic configurations or APIs that demand specific property names, keyof has got your back.&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;Configuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;apiUrl&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;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Configuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getConfiguration&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;keyof&lt;/span&gt; &lt;span class="nx"&gt;Configuration&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;key&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="nx"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&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;key&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;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apiKey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Type-safe parameter usage&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: abc123&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timeout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Type-safe return type&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: 5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key/Type Paired arguments
&lt;/h2&gt;

&lt;p&gt;Brace yourself for an exhilarating journey where static analysis takes the stage. With keyof, the compiler becomes your vigilant guardian, meticulously validating your code to catch any mishaps related to property names and other parameters derived from the prpoerty name. Imagine catching those errors early in the development process, paving the way for rock-solid combinator libraries.&lt;/p&gt;

&lt;p&gt;Assume we define a Product type with id, name, and price properties with different associated 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="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;USD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;EUR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;JPY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CurrencyAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&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="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CurrencyAmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&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="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&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;Product&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&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;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CurrencyAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;1&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;Premium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;price&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;Dissecting the TypeScript function &lt;code&gt;updateProduct&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The function &lt;code&gt;updateProduct&lt;/code&gt; is declared with the &lt;code&gt;const&lt;/code&gt; keyword. It takes three parameters: &lt;code&gt;product&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;, and &lt;code&gt;value&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The product parameter is of type &lt;code&gt;Product&lt;/code&gt;, which suggests that it expects an object of type &lt;code&gt;Product&lt;/code&gt; as an argument.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; parameter is of type &lt;code&gt;keyof Product&lt;/code&gt;. Here, &lt;code&gt;keyof Product&lt;/code&gt; represents a union type consisting of all the keys (property names) of the &lt;code&gt;Product&lt;/code&gt; type. It means that key can only accept a valid key from the &lt;code&gt;Product&lt;/code&gt; object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The value parameter is of type &lt;code&gt;Product[keyof Product]&lt;/code&gt;. It represents the type of the value corresponding to the key in the &lt;code&gt;Product&lt;/code&gt; object. This ensures that the value parameter matches the type of the property indicated by the key parameter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The return type of the &lt;code&gt;updateProduct&lt;/code&gt; function is &lt;code&gt;Product&lt;/code&gt;, indicating that it will return an object of type &lt;code&gt;Product&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the function body, a new object is created using the spread operator (&lt;code&gt;...product&lt;/code&gt;) to copy all the properties of the &lt;code&gt;product&lt;/code&gt; parameter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; parameter is used as a property name inside square brackets (&lt;code&gt;[key]&lt;/code&gt;) to dynamically access the property in the new object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The value parameter is assigned to the property indicated by the &lt;code&gt;key&lt;/code&gt;, effectively updating the corresponding property value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The updated object is returned as the result of the function.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, the &lt;code&gt;updateProduct&lt;/code&gt; function takes an object of type Product, a valid property name from Product, and a value matching the type of the indicated property. It will create an object with the updated property value and returns it.&lt;/p&gt;

&lt;p&gt;Let's try using the &lt;code&gt;updateProduct&lt;/code&gt; to change valid properties with values that have types in the property types of Product:&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;// Below updates the property dynamically restricted to just&lt;/span&gt;
&lt;span class="c1"&gt;// the type of the keys in the type&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;returnedProd1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;Professional&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnedProd1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: "Professional"&lt;/span&gt;

&lt;span class="c1"&gt;// Yo, inflation is still a thing so increase the price&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CurrencyAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;USD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&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="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;returnedProd2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newPrice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnedProd2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: {&lt;/span&gt;
&lt;span class="c1"&gt;//  "currency": 0,&lt;/span&gt;
&lt;span class="c1"&gt;//  "amount": 12&lt;/span&gt;
&lt;span class="c1"&gt;//}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above you'll notice we get the expected behavior where the values of the property update as expected. Yet we all know the happy path is not the most interesting, so what happens when we try to update the product value altering a property that doesn't exist in the Product 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="c1"&gt;// Failure mode where key given doesn't match underlying type&lt;/span&gt;
&lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Type error: Property 'quantity' does not exist in type&lt;/span&gt;
&lt;span class="c1"&gt;// 'keyof Product'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A type error. Music to my ears.&lt;/p&gt;

&lt;p&gt;Now we will try the case where the value parameter given doesn't match the type of any of the underlying type's property 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;// Failure mode where value doesn't match underlying&lt;/span&gt;
&lt;span class="c1"&gt;// property type&lt;/span&gt;
&lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Type error: Argument of type 'boolean' is not assignable&lt;/span&gt;
&lt;span class="c1"&gt;// to parameter of type 'string | number | CurrencyAmount'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect another type error.&lt;/p&gt;

&lt;h2&gt;
  
  
  A use case I'm Partial to!
&lt;/h2&gt;

&lt;p&gt;However, what if we try to update the id property of the &lt;code&gt;product&lt;/code&gt; value to a string?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;returnedProd3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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;hello world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnedProd3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: 1&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnedProd3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: {&lt;/span&gt;
&lt;span class="c1"&gt;//  "id": 1,&lt;/span&gt;
&lt;span class="c1"&gt;//  "name": "Professional",&lt;/span&gt;
&lt;span class="c1"&gt;//  "price": {&lt;/span&gt;
&lt;span class="c1"&gt;//    "currency": 0,&lt;/span&gt;
&lt;span class="c1"&gt;//    "amount": 12&lt;/span&gt;
&lt;span class="c1"&gt;//  }&lt;/span&gt;
&lt;span class="c1"&gt;//}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not ideal since it doesn't result in a type error. However, the behavior retains some weak notion of order by ignoring the invalid update to the id property with a string value instead of its expected type number.&lt;/p&gt;

&lt;p&gt;Of course, if you are familiar with the &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; type you will know that it offers a more ergonomic way for application developers to provide a partial object with well-typed key-value pairs corresponding to the &lt;code&gt;T&lt;/code&gt; type for full coverage. Let's redefine the &lt;code&gt;updateProduct&lt;/code&gt; function as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateProduct2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;updates&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;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="p"&gt;):&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;updates&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Using the new &lt;code&gt;updateProduct&lt;/code&gt; function definition that leverages &lt;code&gt;Partial&amp;lt;Product&amp;gt;&lt;/code&gt; offers consumers improved developer ergonomics in multiple ways by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accepting multiple property values to update in one operation&lt;/li&gt;
&lt;li&gt;improving type safety
&lt;/li&gt;
&lt;/ul&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;returnedProd4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;updateProduct2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&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;Professional&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newPrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnedProd4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: {&lt;/span&gt;
&lt;span class="c1"&gt;//  "id": 1,&lt;/span&gt;
&lt;span class="c1"&gt;//  "name": "Professional",&lt;/span&gt;
&lt;span class="c1"&gt;//  "price": {&lt;/span&gt;
&lt;span class="c1"&gt;//    "currency": 0,&lt;/span&gt;
&lt;span class="c1"&gt;//    "amount": 12&lt;/span&gt;
&lt;span class="c1"&gt;//  }&lt;/span&gt;
&lt;span class="c1"&gt;//}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Expected output: {&lt;/span&gt;
&lt;span class="c1"&gt;//  "id": 1,&lt;/span&gt;
&lt;span class="c1"&gt;//  "name": "Premium",&lt;/span&gt;
&lt;span class="c1"&gt;//  "price": {&lt;/span&gt;
&lt;span class="c1"&gt;//    "currency": 0,&lt;/span&gt;
&lt;span class="c1"&gt;//    "amount": 10&lt;/span&gt;
&lt;span class="c1"&gt;//  }&lt;/span&gt;
&lt;span class="c1"&gt;//}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above you see that we passed in two properties to be updated in the returned object.&lt;/p&gt;

&lt;p&gt;Now we will kick the tires on the type-safety of the new definition:&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;returnedProd5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;updateProduct2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&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="s2"&gt;foobar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnedProd5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Type error: Type 'string' is not assignable&lt;/span&gt;
&lt;span class="c1"&gt;// to type 'number'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we get a type error. Success!&lt;/p&gt;

&lt;p&gt;Under the hook, &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; is still using the &lt;code&gt;keyof&lt;/code&gt; indexed type query operator using something like the following definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Partial&amp;lt;T&amp;gt; = {
  [P in keyof T]?: T[P];
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For people newer to TypeScript I'll break down the type definition above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The type &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; is defined. It represents a new type that takes a generic parameter &lt;code&gt;T&lt;/code&gt;, which can be any object type.&lt;/li&gt;
&lt;li&gt;Inside the curly braces &lt;code&gt;{}&lt;/code&gt;, we have a key-value pair syntax that defines the structure of the &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[P in keyof T]&lt;/code&gt; is a mapped type that iterates over each key &lt;code&gt;P&lt;/code&gt; in the keys of the &lt;code&gt;T&lt;/code&gt; type. &lt;code&gt;keyof T&lt;/code&gt; is a utility type in TypeScript that retrieves all the keys of the type &lt;code&gt;T&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;?&lt;/code&gt; postfix modifier indicates that the property is optional. It means that each property of the resulting type &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; may or may not exist in the original type &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;T[P]&lt;/code&gt; is the type of the property with the key &lt;code&gt;P&lt;/code&gt; in the original type &lt;code&gt;T&lt;/code&gt;. It ensures that the value assigned to each property in &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; is of the same type as the corresponding property in &lt;code&gt;T&lt;/code&gt;. This is the key reason why we get better type-safety with the definition of &lt;code&gt;updateProduct2&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;By using this type definition, the &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; type allows you to create a new type that shares the same keys as the original type &lt;code&gt;T&lt;/code&gt;, but with all properties marked as optional. This is useful when you want to express that some properties of an object can be assigned undefined or omitted altogether.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;, you hold the key to create a brand new type that mirrors the original, but with the freedom to omit or assign undefined to any property. It's like having a personalized toolkit for crafting the perfect object. Say goodbye to rigid structures and embrace the art of possibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;June 2023
: Coming soon I will walk through step by step how to use common types in TypeScript that leverage keyof.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Conjuring TypeScript's Magic with Mapped Types</title>
      <dc:creator>Susan Potter</dc:creator>
      <pubDate>Fri, 23 Jun 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/mbbx6spp/conjuring-typescripts-magic-with-mapped-types-166c</link>
      <guid>https://dev.to/mbbx6spp/conjuring-typescripts-magic-with-mapped-types-166c</guid>
      <description>&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt; TypeScript: The Savvy Sidekick of JavaScript
&lt;/li&gt;
&lt;li&gt; Why Mapped Types Matter
&lt;/li&gt;
&lt;li&gt; Mapped Types Syntax and Basic Plumbing

&lt;ol&gt;
&lt;li&gt; The Enchanting Syntax: Casting the Spell
&lt;/li&gt;
&lt;li&gt; The Components of Mapped Types: Unmasking the Wizards
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt; A Deeper Dive!

&lt;ol&gt;
&lt;li&gt; Modifying Property Modifiers: Bending the Rules of Nature
&lt;/li&gt;
&lt;li&gt; Transforming Property Types: A Symphony of Type Transformations
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt; Tips, Tricks, and Best Practices: Unleashing the Magic Safely

&lt;ol&gt;
&lt;li&gt; Tips for Working with Mapped Types: Navigating the Magical Realm
&lt;/li&gt;
&lt;li&gt; Best Practices and Guidelines: Taming the Magic for Large-Scale Projects
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt; Wrapping it up
&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;In this article, we’ll take a whirlwind tour through the fascinating world of TypeScript and its type system. Hold onto your hats and get ready to unleash the power of mapped types!&lt;/p&gt;

&lt;p&gt;&lt;a id="org8be568b"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript: The Savvy Sidekick of JavaScript
&lt;/h2&gt;

&lt;p&gt;Buckle up, folks! TypeScript swoops in like a suave sidekick, adding an extra layer of pizzazz to the world of JavaScript. With TypeScript, you get to catch those pesky bugs before they even think about causing chaos in your code.&lt;/p&gt;

&lt;p&gt;It’s time to introduce you to the heroes of our story: mapped types! These are the true sorcerers of TypeScript especially when used in conjunction with &lt;a href="https://www.susanpotter.net/software/typescripts-keyof-operator-and-possible-uses/" rel="noopener noreferrer"&gt;keyof&lt;/a&gt; and &lt;a href="https://www.susanpotter.net/software/using-conditional-types-in-typescript/" rel="noopener noreferrer"&gt;conditional types&lt;/a&gt;. They wield the power to transform and shape types with a flick of their magical wands. Mapped types allow you to redefine existing types, making them dance to your tune.&lt;/p&gt;

&lt;p&gt;&lt;a id="org1c09845"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Mapped Types Matter: The Plot Thickens
&lt;/h2&gt;

&lt;p&gt;Mapped types give you the power to streamline your code, enhance its clarity, and catch those sneaky bugs before they wreak havoc. They enable you to write robust, maintainable code that makes your fellow developers nod in gratitude (when used just right).&lt;/p&gt;

&lt;p&gt;To illustrate the utility of mapped types we will show how to &lt;strong&gt;use&lt;/strong&gt; a mapped type commonly used in TypeScript already: &lt;code&gt;Pick&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let us start with the trusted &lt;code&gt;Person&lt;/code&gt; type example developers overuse ad nauseam to show what it does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;address&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;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes we only want to pass a subset of the &lt;code&gt;Person&lt;/code&gt; type’s properties values to functions. In JavaScript we either pass the entire object value regardless or we pass the properties one-by-one as separate arguments.&lt;/p&gt;

&lt;p&gt;In TypeScript we can compute a new type that plucks (or “picks”) a specific subset of properties names to collate in one type definition.&lt;/p&gt;

&lt;p&gt;In the example below we pluck (or “pick”) the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; properties from the &lt;code&gt;Person&lt;/code&gt; type defined above.&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;// Behold, the power of Pick!&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PersonBasicInfo&lt;/span&gt; &lt;span class="o"&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;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;'&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;The type computed by &lt;code&gt;Pick&amp;lt;Person, 'name' | 'age'&amp;gt;&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the power of &lt;code&gt;Pick&lt;/code&gt; we summoned the &lt;code&gt;PersonBasicInfo&lt;/code&gt; type containing only the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; properties.&lt;/p&gt;

&lt;p&gt;&lt;a id="orgabf9569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapped Types Syntax and Basic Plumbing
&lt;/h2&gt;

&lt;p&gt;It’s time to decode the incantations and unravel the key components that make mapped types spellbinding.&lt;/p&gt;

&lt;p&gt;&lt;a id="orgc104ca2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Enchanting Syntax: Casting the Spell
&lt;/h3&gt;

&lt;p&gt;We define mapped types using angle brackets &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt; and curly braces &lt;code&gt;{ }&lt;/code&gt;. Let’s demystify the basic syntax step-by-step:&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;MappedType&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;Property&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;ExistingType&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;NewProperty&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;MappedType&lt;/code&gt;&lt;br&gt;
: This is the name you give to your created mapped type. It can be any valid type name you choose.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[Property in ExistingType]&lt;/code&gt;&lt;br&gt;
: This is the magical syntax incantation that sets up your mapped type. &lt;code&gt;Property&lt;/code&gt; represents each property in the existing type that you want to manipulate. &lt;code&gt;ExistingType&lt;/code&gt; is the original type from which you’re deriving the mapped type.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NewProperty&lt;/code&gt;&lt;br&gt;
: This is where your creativity comes into play. You define the transformed version of each property in the mapped type.&lt;/p&gt;

&lt;p&gt;&lt;a id="org221051a"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Components of Mapped Types: Unmasking the Wizards
&lt;/h3&gt;

&lt;p&gt;&lt;a id="org36be86c"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Property: The Building Block of Magic
&lt;/h4&gt;

&lt;p&gt;In this example, we’ll transform the properties of an existing type, &lt;code&gt;Person&lt;/code&gt;, into optional properties using mapped 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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;OptionalPerson&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;Property&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;Person&lt;/span&gt;&lt;span class="p"&gt;]?:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Person&lt;/code&gt;&lt;br&gt;
: Our existing type with properties &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, and &lt;code&gt;address&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OptionalPerson&lt;/code&gt;&lt;br&gt;
: The name of our mapped type. We use the &lt;code&gt;keyof&lt;/code&gt; operator to iterate over each property in &lt;code&gt;Person&lt;/code&gt; and create optional properties in &lt;code&gt;OptionalPerson&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting type looks like the following:&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;OptionalPerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples of valid constructions of this type include:&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;// Note: Shakespeare doesn't have an email&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shakespeare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OptionalPerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;William Shakespeare&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stratford-upon-Avon, England&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// After dying Shakespeare's address changed&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deathChanges&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OptionalPerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Church of the Holy Trinity, Stratford-upon-Avon&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedShakespeare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OptionalPerson&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;shakespeare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;deathChanges&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="org8ac3f95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ExistingType: The Source of Power
&lt;/h4&gt;

&lt;p&gt;Let’s explore another example that transforms the property types of an existing type:&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PersonWithOptionalProps&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;Property&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;Person&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Person&lt;/code&gt;&lt;br&gt;
: Our existing type with properties &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PersonWithOptionalProps&lt;/code&gt;&lt;br&gt;
: Our mapped type that retains the same properties as &lt;code&gt;Person&lt;/code&gt;, but with transformed property types. We use the &lt;code&gt;keyof&lt;/code&gt; operator to iterate over each property in &lt;code&gt;Person&lt;/code&gt; and create a union type with &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You might be wondering what is the difference between &lt;code&gt;OptionalPerson&lt;/code&gt; and &lt;code&gt;PersonWithOptionalProps&lt;/code&gt;? Let’s look at the computed type definition:&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;PersonWithOptionalProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the property names do not have the &lt;code&gt;?&lt;/code&gt; suffix. What does this mean in pracitce? Let’s try to set the type to the object literal set to the &lt;code&gt;shakespeare&lt;/code&gt; constant above:&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;shakespeare2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PersonWithOptionalProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;William Shakespeare&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stratford-upon-Avon, England&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// Errors see message below&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we get an error! Let’s take a look:&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="nx"&gt;Property&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;missing&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;
             &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{ name: string;
                age: number;
                address: string;
              }&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;but&lt;/span&gt; &lt;span class="nx"&gt;required&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PersonWithOptionalProps&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;So what this is saying is that we do need to set the missing &lt;code&gt;email&lt;/code&gt; property. To model our requirements, we can set it to &lt;code&gt;undefined&lt;/code&gt; to denote that &lt;code&gt;shakespeare2&lt;/code&gt; has no &lt;code&gt;email&lt;/code&gt; property value.&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;shakespeare2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PersonWithOptionalProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;William Shakespeare&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stratford-upon-Avon, England&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above now typechecks and the original error applies to any missing property. We needed to explicitly set the missing properties from &lt;code&gt;Person&lt;/code&gt; to &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id="org9565c03"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Modifying Properties: Infusing Your Magic
&lt;/h4&gt;

&lt;p&gt;Let’s delve into an example where we omit the modifiers of properties:&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;ReadonlyPerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;address&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;readonly&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MutablePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Property&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;ReadonlyPerson&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyPerson&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Person&lt;/code&gt;&lt;br&gt;
: Our existing type with properties &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MutablePerson&lt;/code&gt;&lt;br&gt;
: Our mapped type that mirrors the properties of &lt;code&gt;Person&lt;/code&gt;, but removes the &lt;code&gt;readonly&lt;/code&gt; modifier. We use the &lt;code&gt;-readonly&lt;/code&gt; syntax to update the property modifiers within the mapped type.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MutablePerson&lt;/code&gt; computes to:&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;MutablePerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;address&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;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;code&gt;readonly&lt;/code&gt;, mom!&lt;/p&gt;

&lt;p&gt;&lt;a id="orgb35c322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding Properties
&lt;/h4&gt;

&lt;p&gt;Let’s explore one last example to showcase the versatility of mapped 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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Cylinder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CalculateVolume&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Property&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;T&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="nx"&gt;Property&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;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;volume&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateCylinderVolume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;cylinder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cylinder&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;CalculateVolume&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Cylinder&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;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cylinder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cylinder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;cylinder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;volume&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Circle&lt;/code&gt;&lt;br&gt;
: Our existing type representing a circle with a &lt;code&gt;radius&lt;/code&gt; property.&lt;br&gt;
&lt;code&gt;Cylinder&lt;/code&gt;&lt;br&gt;
: Another existing type representing a cylinder with &lt;code&gt;radius&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; properties.&lt;br&gt;
&lt;code&gt;CalculateVolume&amp;lt;T&amp;gt;&lt;/code&gt;&lt;br&gt;
: Our mapped type that extends any existing type &lt;code&gt;T&lt;/code&gt;. It retains the properties of &lt;code&gt;T&lt;/code&gt; and adds a new &lt;code&gt;volume&lt;/code&gt; property of type &lt;code&gt;number&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;calculateCylinderVolume&lt;/code&gt;&lt;br&gt;
: A function that takes a &lt;code&gt;Cylinder&lt;/code&gt; object, calculates its volume, and returns a &lt;code&gt;CalculateVolume&amp;lt;Cylinder&amp;gt;&lt;/code&gt; object with the original properties of &lt;code&gt;Cylinder&lt;/code&gt; and the newly added &lt;code&gt;volume&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;With these examples, you’ve witnessed the magic of mapped types. We have manipulated properties, modified modifiers, transformed property types and added new properties.&lt;/p&gt;

&lt;p&gt;&lt;a id="org0a577c9"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  A Deeper Dive!
&lt;/h2&gt;

&lt;p&gt;In this section, we explore the mechanics of property transformation and mapped types to reshape our types with a dash of enchantment.&lt;/p&gt;

&lt;p&gt;&lt;a id="org355e500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Modifying Property Modifiers: Bending the Rules of Nature
&lt;/h3&gt;

&lt;p&gt;&lt;a id="orgd24479d"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Making Properties Optional: Partial type
&lt;/h4&gt;

&lt;p&gt;Imagine a world where properties have the freedom to choose their destiny, where they can be present or absent at their whim. Enter the wondrous &lt;code&gt;Partial&lt;/code&gt; type! Let’s demystify the derivation of &lt;code&gt;Partial&lt;/code&gt; from first principles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;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;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Property&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;T&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="nx"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;&lt;br&gt;
: computes a new type that mirrors the original type &lt;code&gt;T&lt;/code&gt;, but grants properties the ability to become optional using the &lt;code&gt;?&lt;/code&gt; modifier. It’s like giving properties a ticket to the land of freedom.&lt;/p&gt;

&lt;p&gt;Let’s witness the power of &lt;code&gt;Partial&lt;/code&gt; in action:&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;Wizard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;spells&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PartialWizard&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;Wizard&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;wizard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PartialWizard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// Property "name" and "spells" become optional&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PartialWizard&lt;/code&gt;&lt;br&gt;
: Our transformed type derived from &lt;code&gt;Wizard&lt;/code&gt; using the &lt;code&gt;Partial&lt;/code&gt; mapped type. Now, properties like &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;spells&lt;/code&gt; have the choice to be present or absent, granting flexibility and easing our coding journey.&lt;/p&gt;

&lt;p&gt;&lt;a id="org95b8c79"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Making Properties Read-Only: &lt;code&gt;Readonly&lt;/code&gt; type
&lt;/h4&gt;

&lt;p&gt;In the land of code, where properties roam free, some properties prefer to stand tall and unchangeable, like statues of wisdom. Enter the majestic &lt;code&gt;Readonly&lt;/code&gt; type, which bestows the power of immutability upon properties. Let’s unlock the secrets of &lt;code&gt;Readonly&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Readonly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Property&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;T&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="nx"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Readonly&amp;lt;T&amp;gt;&lt;/code&gt;&lt;br&gt;
: The alchemical mixture that creates a new type with the same properties as the original &lt;code&gt;T&lt;/code&gt;, but marked as &lt;code&gt;readonly&lt;/code&gt;. It’s like encasing properties in an unbreakable spell, ensuring they remain untouchable.&lt;/p&gt;

&lt;p&gt;Behold the might of &lt;code&gt;Readonly&lt;/code&gt; in action:&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;Potion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;potion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Potion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elixir of Eternal Youth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ingredients&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;Unicorn tears&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;Moonlight essence&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;potion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Forbidden Potion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Works&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;potion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// prints "Forbidden Potion"&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyPotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Readonly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Potion&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;ropotion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyPotion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elixir of Eternal Youth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ingredients&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;Unicorn tears&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;Moonlight essence&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;ropotion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Forbidden Potion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Error! Property "name" is read-only&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ReadonlyPotion&lt;/code&gt;&lt;br&gt;
: Our transformed type created from &lt;code&gt;Potion&lt;/code&gt; using the &lt;code&gt;Readonly&lt;/code&gt; mapped type. Now, properties are guarded against any attempts to change them. This ensures their immutability and preserves their original value.&lt;/p&gt;

&lt;p&gt;&lt;a id="org53d2b5b"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Excluding Properties: &lt;code&gt;Exclude&lt;/code&gt; type
&lt;/h4&gt;

&lt;p&gt;Sometimes we need to separate the chosen from the unwanted, to exclude certain elements from our type sorcery. Enter the extraordinary &lt;code&gt;Exclude&lt;/code&gt; type, capable of removing specific types from a union. Let’s uncover the essence of &lt;code&gt;Exclude&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Exclude&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;U&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;U&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;never&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Exclude&amp;lt;T, U&amp;gt;&lt;/code&gt;&lt;br&gt;
: The spell that removes types present in U from the union of types T. Like a forcefield that shields our types from unwanted members.&lt;/p&gt;

&lt;p&gt;Let’s witness the might of &lt;code&gt;Exclude&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fire&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Water&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Air&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Earth&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;ExcludedElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Exclude&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Elements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fire&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Air&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExcludedElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Water&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Success! Excludes "Fire" and "Air"&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;forbiddenElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExcludedElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fire&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Error! "Fire" is excluded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ExcludedElements&lt;/code&gt;&lt;br&gt;
: Our transformed type, derived from Elements using the Exclude mapped type. With the power of Exclude, we’ve excluded the elements “Fire” and “Air” from our new type, allowing only “Water” and “Earth” to remain.&lt;/p&gt;

&lt;p&gt;&lt;a id="org7357742"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Transforming Property Types: A Symphony of Type Transformations
&lt;/h3&gt;

&lt;p&gt;&lt;a id="orgbfe1aee"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Modifying Property Types: Pick and Record types
&lt;/h4&gt;

&lt;p&gt;Picture a symphony where notes dance and melodies intertwine. In the world of TypeScript, we have the harmonious &lt;code&gt;Pick&lt;/code&gt; and &lt;code&gt;Record&lt;/code&gt; types. They pluck or transform property types. Let’s explore their utility:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Pick&amp;lt;T, K&amp;gt;&lt;/code&gt;&lt;br&gt;
: computes a new type selecting specific properties &lt;code&gt;K&lt;/code&gt; from the original type &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Record&amp;lt;K, T&amp;gt;&lt;/code&gt;&lt;br&gt;
: computes a new type by mapping each property key &lt;code&gt;K&lt;/code&gt; to a corresponding property type &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s review some examples of &lt;code&gt;Pick&lt;/code&gt; and &lt;code&gt;Record&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Song&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;artist&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;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SongTitle&lt;/span&gt; &lt;span class="o"&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;Song&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SongDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;artist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Only "title" property is allowed&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;songTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SongTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In the End&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// Only "title" and "artist" properties are allowed&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;songDetails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SongDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bohemian Rhapsody&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Queen&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;SongTitle&lt;br&gt;
: Our transformed type derived from &lt;code&gt;Song&lt;/code&gt; using the &lt;code&gt;Pick&lt;/code&gt; mapped type. It selects only the &lt;code&gt;title&lt;/code&gt; property, allowing us to focus on the song title.&lt;/p&gt;

&lt;p&gt;SongDetails&lt;br&gt;
: Our transformed type derived from the key &lt;code&gt;"title" | "artist"&lt;/code&gt; and the type &lt;code&gt;string&lt;/code&gt; using the &lt;code&gt;Record&lt;/code&gt; mapped type. It maps each property key to the type &lt;code&gt;string&lt;/code&gt;, creating a type that captures the song &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;artist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id="org9c2c68a"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Replacing Property Types: Mapped Types with conditional types
&lt;/h4&gt;

&lt;p&gt;Now, we explore how mapped types can work with conditional types to transform property types:&lt;/p&gt;

&lt;p&gt;Conditional Types&lt;br&gt;
: A type-level capability to adapt based on conditions. I wrote about &lt;a href="https://www.susanpotter.net/software/using-conditional-types-in-typescript/" rel="noopener noreferrer"&gt;conditional types&lt;/a&gt; in a previous post, illustrating good and bad examples.&lt;/p&gt;

&lt;p&gt;Let’s observe conditional transformations with code examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bird&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;Treats&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="nx"&gt;Pet&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;catTreats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Treats&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cat&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Salmon Treats&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;Catnip&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Array of strings&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dogTreats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Treats&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dog&lt;/span&gt;&lt;span class="dl"&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Number&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;birdTreats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Treats&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bird&lt;/span&gt;&lt;span class="dl"&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="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Treats&amp;lt;T&amp;gt;&lt;/code&gt;&lt;br&gt;
: Our transformed type, where the property type varies based on the condition in the conditional type. The resulting type adapts to the pet’s type from the input, offering an array of strings for a cat, a number for a dog, and a boolean for a bird.&lt;/p&gt;

&lt;p&gt;Above we observed the powers of Pick, Record, and the fusion of mapped types with conditional types. Using these TypeScript capabilities, we can reduce boilerplate and express the problem domain more directly.&lt;/p&gt;

&lt;p&gt;So, grab your wands, summon your creativity, and let the transformation of properties and property types begin! But be judicuous.&lt;/p&gt;

&lt;p&gt;&lt;a id="org7c21d12"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips, Tricks, and Best Practices: Unleashing the Magic Safely
&lt;/h2&gt;

&lt;p&gt;&lt;a id="org85ed905"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips for Working with Mapped Types: Navigating the Magical Realm
&lt;/h3&gt;

&lt;p&gt;As we traverse mapped types, it’s essential to keep a few tips and tricks up our sleeves.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consider performance implications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Mind the size and complexity of your types.&lt;/li&gt;
&lt;li&gt;  Large mappings can lead to longer compile times and increased memory usage.&lt;/li&gt;
&lt;li&gt;  Strike a balance between expressiveness and performance for optimal code execution.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Beware of limitations and pitfalls:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Mapped types cannot create new properties that don’t exist in the original type.&lt;/li&gt;
&lt;li&gt;  Complex mappings or recursive transformations may result in convoluted and hard-to-read code.&lt;/li&gt;
&lt;li&gt;  Stay vigilant and explore alternative strategies when faced with these challenges.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Master complex mappings and type inference challenges:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Embrace utility types like &lt;code&gt;keyof&lt;/code&gt; and conditional types.&lt;/li&gt;
&lt;li&gt;  Harness their power to navigate intricate mappings and overcome type inference hurdles.&lt;/li&gt;
&lt;li&gt;  Experiment, iterate, and tap into the &lt;a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html" rel="noopener noreferrer"&gt;vast resources of the TypeScript documentation&lt;/a&gt; and developer communities.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;With these suggestions, you can leverage TypeScript’s mapped types while avoiding common pitfalls.&lt;/p&gt;

&lt;p&gt;&lt;a id="orgedc7685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices and Guidelines: Taming the Magic for Large-Scale Projects
&lt;/h3&gt;

&lt;p&gt;To tame the magic of mapped types in large projects, follow these best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Organize and maintain mapped types:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Group related types together.&lt;/li&gt;
&lt;li&gt;  Create dedicated type files.&lt;/li&gt;
&lt;li&gt;  Provide clear documentation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This fosters maintainability and enables effective use by fellow wizards.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Ensure type safety and compatibility:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Use type guards and strict null checks.&lt;/li&gt;
&lt;li&gt;  Perform thorough testing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Validate the safety and compatibility of your mapped types. Integrate comprehensive yet meaningful tests to check their usage is as expected.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Leverage mapped types for clarity and maintainability:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Create reusable abstractions.&lt;/li&gt;
&lt;li&gt;  Enforce consistent patterns.&lt;/li&gt;
&lt;li&gt;  Reduce duplication.&lt;/li&gt;
&lt;li&gt;  Avoid reinventing mapped types already provided by TypeScript.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Harness mapped types to enhance code readability and simplify maintenance tasks.&lt;/p&gt;

&lt;p&gt;&lt;a id="orgb294c29"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping it up
&lt;/h2&gt;

&lt;p&gt;Throughout this article we embarked on a wild ride through the enchanted land of mapped types in TypeScript. We’ve seen their transformative abilities, from modifying property modifiers to reshaping property types. We’ve explored tips, tricks, and better practices for mapped types.&lt;/p&gt;

&lt;p&gt;Unleash your imagination and continue exploring the enormous possibilities that mapped types offer. Yet avoid reinventing constructs as TypeScript already defines utility types for common uses.&lt;/p&gt;

&lt;p&gt;Wield the magic of mapped types with care, always striving for clarity, maintainability, and type safety but do not overuse. Your future teammates will thank you later.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>types</category>
    </item>
    <item>
      <title>Using Conditional Types in TypeScript</title>
      <dc:creator>Susan Potter</dc:creator>
      <pubDate>Wed, 31 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/mbbx6spp/using-conditional-types-in-typescript-4m6o</link>
      <guid>https://dev.to/mbbx6spp/using-conditional-types-in-typescript-4m6o</guid>
      <description>&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt; A High-Level Understanding
&lt;/li&gt;
&lt;li&gt; When to use Conditional Types
&lt;/li&gt;
&lt;li&gt; But wait, we didn’t use &lt;code&gt;UpdateObject&amp;lt;T, U&amp;gt;&lt;/code&gt; anywhere
&lt;/li&gt;
&lt;li&gt; Embrace the Power of Conditional Types but only when you really need to! :)
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Welcome, fellow developer. Today we embark on a [hopefully] helpful journey into the world of conditional types via TypeScript! I hope to impress upon you how we can levereage conditional types to offer improved type safety especially in cases where the type of an associated piece of data can be computed from the type of the original data that is polymorphic in nature.&lt;/p&gt;

&lt;p&gt;&lt;a id="org48ad424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A High-Level Understanding
&lt;/h2&gt;

&lt;p&gt;Conditional types are like shape-shifters, capable of dynamically transforming and adapting types based on varying conditions. They bestow upon the developer the gift of creating flexible type mappings without compromising on how well-typed our definitions are, thus empowering our code with expressiveness and resilience.&lt;/p&gt;

&lt;p&gt;In this introductory section I will show the mechanics of how to describe conditional types in TypeScript itself even if the examples are trivial and not useful so that I am not distracted explaining the syntax in more useful and involved examples later on.&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;option&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://cdn.skypack.dev/fp-ts?dts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I am just importing the &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; parameterized type from my trusted friend &lt;code&gt;fp-ts&lt;/code&gt;,&lt;br&gt;
a library I tend to use in TypeScript codebases when I am able. If you are unfamiliar with this type think of this as an alternative way of encoding a nullable value in a more type safe way.&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;NumberValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;minValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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;span class="nl"&gt;maxValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StringValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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;span class="nl"&gt;maxLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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;span class="nl"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NoopValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start of by defining the type &lt;code&gt;NumberValidator&lt;/code&gt;, which represents a validator for numeric values, and the &lt;code&gt;StringValidator&lt;/code&gt; type, which is a validator for string values. Both types have specific properties that define their validation rules.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;NumberValidator&lt;/code&gt; type has &lt;code&gt;minValue&lt;/code&gt; and &lt;code&gt;maxValue&lt;/code&gt; properties, each wrapped in an &lt;code&gt;Option&amp;lt;number&amp;gt;&lt;/code&gt; type from &lt;code&gt;fp-ts&lt;/code&gt;. These options can hold either a number value or no value at all.&lt;/p&gt;

&lt;p&gt;the &lt;code&gt;StringValidator&lt;/code&gt; type has &lt;code&gt;minLength&lt;/code&gt;, &lt;code&gt;maxLength&lt;/code&gt;, &lt;code&gt;contains&lt;/code&gt;, and &lt;code&gt;matches&lt;/code&gt; properties, all wrapped in &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; types. These options allow us to define constraints such as minimum and maximum lengths, required patterns, and more.&lt;/p&gt;

&lt;p&gt;We also have a &lt;code&gt;NoopValidator&lt;/code&gt; type, which represents a validator that doesn’t perform any specific validations. It’s essentially an empty object, signaling that no validation rules are applicable.&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;slugValidator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Validator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;maxLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;\-]&lt;/span&gt;&lt;span class="sr"&gt;+$/&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;none&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;titleValidator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Validator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;maxLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// age validator for purchasing alcohol in any sane country&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ageValidator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Validator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;minValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;maxValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;149&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;Next up we define two instances of &lt;code&gt;Validator&amp;lt;string&amp;gt;&lt;/code&gt;: &lt;code&gt;slugValidator&lt;/code&gt; and &lt;code&gt;titleValidator&lt;/code&gt;. These objects use the &lt;code&gt;Validator&lt;/code&gt; type we defined later to determine their structure based on the type argument provided.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;slugValidator&lt;/code&gt; object specifies some validation rules for a string field.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;titleValidator&lt;/code&gt; object, on the other hand, focuses on validating a string field for a title. It requires a minimum length of 1, a maximum length of 64, and doesn’t have any pattern-based constraints.&lt;/p&gt;

&lt;p&gt;Lastly, we encounter an age validator object – &lt;code&gt;ageValidator&lt;/code&gt;. It’s specifically designed to validate numeric values, representing the age of an individual for purchasing alcohol in a sane country (we like sanity!). This validator sets a minimum age of 18 and a maximum age of 149, making sure we don’t encounter any age-related shenanigans.&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;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;unknown&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;Validator&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="nx"&gt;Field&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="kr"&gt;number&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;NumberValidator&lt;/span&gt;
      &lt;span class="p"&gt;:&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;string&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;StringValidator&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NoopValidator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To wrap up the initial example we define a type alias called &lt;code&gt;Field&lt;/code&gt; that can be either a number, a string, or an unknown type. Then, we define the &lt;code&gt;Validator&lt;/code&gt; type, which takes a generic argument &lt;code&gt;T&lt;/code&gt; extending &lt;code&gt;Field&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s where the conditional magic comes into play: using the &lt;code&gt;extends&lt;/code&gt; keyword, we check if &lt;code&gt;T&lt;/code&gt; extends &lt;code&gt;number&lt;/code&gt;. If it does, the type becomes &lt;code&gt;NumberValidator&lt;/code&gt;. If &lt;code&gt;T&lt;/code&gt; extends &lt;code&gt;string&lt;/code&gt;, the type becomes &lt;code&gt;StringValidator&lt;/code&gt;. And if none of the conditions match, we fall back to &lt;code&gt;NoopValidator&lt;/code&gt;. Notice the familiar ternary operator syntax for conditional values in this type expression.&lt;/p&gt;

&lt;p&gt;In essence, these mechanics allow us to dynamically determine the structure and properties of the validator object based on the type we provide. It’s like having different validator configurations tailored to the type of data we’re validating – an incredibly powerful technique!&lt;/p&gt;

&lt;p&gt;&lt;a id="orgf8fb829"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use Conditional Types
&lt;/h2&gt;

&lt;p&gt;Picture this: you’re tasked with updating different types of objects, but here’s the catch—you don’t know which type or fields of the type. This exactly where conditional types come to the rescue, swooping in like a superhero to save the day.&lt;/p&gt;

&lt;p&gt;Yes, perhaps this is a little contrived to show the power of conditional types mixed with &lt;code&gt;keyof&lt;/code&gt; for a more involved example I covered &lt;a href="https://www.susanpotter.net/software/typescripts-keyof-operator-and-possible-uses/" rel="noopener noreferrer"&gt;how to use keyof in TypeScript&lt;/a&gt; in a previous post.&lt;/p&gt;

&lt;p&gt;Now, let me take you on a journey through the magical realm of TypeScript, where we’ll witness firsthand how conditional types can boost your code’s type safety and eliminate those dreadful runtime bugs for a situation like this.&lt;/p&gt;

&lt;p&gt;First things first, what are conditional types? Think of them as intelligent type definitions that adapt based on conditions. They allow us to model complex scenarios, such as handling updates to objects with unknown fields, with elegance and precision.&lt;/p&gt;

&lt;p&gt;Imagine you have a function called &lt;code&gt;updateObject&lt;/code&gt; that takes an original object and an updates object. Traditionally, without conditional types, you might write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;updates&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;Sure, it gets the job done, but it’s like playing with fire. It’s untyped, leaving you vulnerable to runtime bugs that may lurk in the shadows. Spelling mistakes, non-existent fields—these errors can easily slip through the cracks, only to haunt you later.&lt;/p&gt;

&lt;p&gt;Also, if you have read my previous post on &lt;a href="https://www.susanpotter.net/software/any-versus-unknown-in-typescript-when-to-use-one-over-the-other/" rel="noopener noreferrer"&gt;the differences between &lt;code&gt;any&lt;/code&gt; versus &lt;code&gt;unknown&lt;/code&gt; in TypeScript&lt;/a&gt; you will know &lt;code&gt;any&lt;/code&gt; typing should only be done as a last resort in TypeScript.&lt;/p&gt;

&lt;p&gt;Fear not, reader! Conditional types are here to save us from this chaos. Let’s dive into the code and see how we can level up our type safety game.&lt;/p&gt;

&lt;p&gt;We’ll start by defining a conditional type called &lt;code&gt;UpdateObject&lt;/code&gt;. Brace yourself for the magic:&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;UpdateObject&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;U&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;T&lt;/span&gt;&lt;span class="p"&gt;]:&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;U&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;U&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="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="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s break the above down. The &lt;code&gt;UpdateObject&lt;/code&gt; type takes two generic parameters, &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;U&lt;/code&gt;, representing the original object and the updates object, respectively. Now, pay close attention to the square brackets &lt;code&gt;[K in keyof T]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This snippet introduces a loop that iterates over each property &lt;code&gt;K&lt;/code&gt; in &lt;code&gt;T&lt;/code&gt;, which is the key type of the original object. But here comes the real beauty—the conditional statement: &lt;code&gt;K extends keyof U ? U[K] : T[K]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This line of code works its magic by checking if &lt;code&gt;K&lt;/code&gt; exists in the keys of &lt;code&gt;U&lt;/code&gt;, our updates object. If it does, TypeScript gracefully assigns the type of &lt;code&gt;U[K]&lt;/code&gt; to the property in the resulting object. However, if the property doesn’t exist in &lt;code&gt;U&lt;/code&gt;, it falls back to the type of &lt;code&gt;T[K]&lt;/code&gt;, ensuring we maintain the original value.&lt;/p&gt;

&lt;p&gt;Now that we have our powerful &lt;code&gt;UpdateObject&lt;/code&gt; type, let’s put it into action by revamping our &lt;code&gt;updateObject&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateObject&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;U&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;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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&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="nx"&gt;updates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;U&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;updates&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;Bear with me, folks—we’re almost there! The &lt;code&gt;updateObject&lt;/code&gt; function now receives two parameters: &lt;code&gt;original&lt;/code&gt;, representing the original object, and &lt;code&gt;updates&lt;/code&gt;, holding our updates object. But what’s this &lt;code&gt;&amp;lt;T, U extends Partial&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; magic?&lt;/p&gt;

&lt;p&gt;Here, we’re using TypeScript’s generic parameters to ensure type safety. &lt;code&gt;T&lt;/code&gt; represents the original object’s type, while &lt;code&gt;U&lt;/code&gt; extends &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;. This ensures that the &lt;code&gt;updates&lt;/code&gt; object can only contain a subset of properties from the original object, avoiding unexpected additions.&lt;/p&gt;

&lt;p&gt;With our revamped function in place, we can now unleash the power of TypeScript’s type system to catch bugs at compile-time, rather than chasing them through the treacherous land of runtime.&lt;/p&gt;

&lt;p&gt;Let’s say we have a &lt;code&gt;Person&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Using our updated function, we can confidently update a &lt;code&gt;Person&lt;/code&gt; object, knowing that TypeScript will guard us against any mishaps:&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;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123 Main St&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;updatedPerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;updateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;456 Elm St&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;Trying to pass a partial object for the &lt;code&gt;updates&lt;/code&gt; with a misspelled attribute will now result in a type error. Like the following:&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;updatedPerson2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nf"&gt;updateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;adress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;232&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 will produce the type error:&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="nx"&gt;Argument&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{ adress: number; }&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;assignable&lt;/span&gt;
      &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;parameter&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Partial&amp;lt;Person&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="nb"&gt;Object&lt;/span&gt; &lt;span class="nx"&gt;literal&lt;/span&gt; &lt;span class="nx"&gt;may&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;specify&lt;/span&gt; &lt;span class="nx"&gt;known&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;but&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;adress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;does&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;exist&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Partial&amp;lt;Person&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="nx"&gt;Did&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;mean&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;write&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;address&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;Boom! With TypeScript’s watchful eye, any misspelled field names or attempts to update non-existent fields will be caught right at compile-time. No more runtime surprises, my friends!&lt;/p&gt;

&lt;p&gt;&lt;a id="org107a656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But wait, we didn’t use &lt;code&gt;UpdateObject&amp;lt;T, U&amp;gt;&lt;/code&gt; anywhere
&lt;/h2&gt;

&lt;p&gt;Good eye, reader. This was pointed out to me after I published a draft for people to review. I realized in the second case the &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; type was all the magic this case needed. No need to get fancy with conditional types.&lt;/p&gt;

&lt;p&gt;So, dear developers, embrace the power of TypeScript and awe inspiring types like &lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt;. Say goodbye to the unpredictable world of runtime bugs, and stride confidently towards a future of reliable and type-safe code.&lt;/p&gt;

&lt;p&gt;&lt;a id="org657ff19"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Embrace the Power of Conditional Types but only when you really need to! :)
&lt;/h2&gt;

&lt;p&gt;Well the moral of this story is that next time I will not sit on a half finished blog post for so long such that I lose all my train of thought on the more “motivating” example to use such that it is essentially an invalid example for what I wished to demonstrate.&lt;/p&gt;

&lt;p&gt;Forgive me, reader and take care until next time where we explore &lt;a href="https://www.susanpotter.net/software/conjuring-typescripts-magic-with-mapped-types/" rel="noopener noreferrer"&gt;mapped types&lt;/a&gt; and even combine it with &lt;strong&gt;conditional types&lt;/strong&gt; that we just explored here.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>types</category>
    </item>
  </channel>
</rss>
