<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Conrad Holtzhausen</title>
    <description>The latest articles on Forem by Conrad Holtzhausen (@conrad777).</description>
    <link>https://forem.com/conrad777</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%2F100878%2F998bfd0c-41e4-4ee8-8dc0-158d716cdf04.png</url>
      <title>Forem: Conrad Holtzhausen</title>
      <link>https://forem.com/conrad777</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/conrad777"/>
    <language>en</language>
    <item>
      <title>Some funky parts of Typescript</title>
      <dc:creator>Conrad Holtzhausen</dc:creator>
      <pubDate>Tue, 21 Feb 2023 09:24:11 +0000</pubDate>
      <link>https://forem.com/hotjar/some-funky-parts-of-typescript-1bh8</link>
      <guid>https://forem.com/hotjar/some-funky-parts-of-typescript-1bh8</guid>
      <description>&lt;p&gt;And by funky I don’t mean like the smell of chunky milk. I mean funky like the &lt;a href="https://www.youtube.com/watch?v=OAC4ItP0xWM"&gt;sweet music&lt;/a&gt; 💃.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://www.hotjar.com/"&gt;Hotjar&lt;/a&gt;, we have bi-weekly Typescript pair programming sessions where we try and solve a few of the &lt;a href="https://github.com/type-challenges/type-challenges"&gt;type challenges&lt;/a&gt; together. In one session after solving the challenges we set out to, we chose a &lt;a href="https://github.com/type-challenges/type-challenges/blob/main/questions/00020-medium-promise-all/README.md"&gt;random challenge&lt;/a&gt; as a last hurrah and boy was it a doozy.&lt;/p&gt;

&lt;p&gt;So why are you reading this? Well let me tell you what you can expect if you take the red pill with this &lt;strong&gt;TL;DR&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First I will take you down the rabbit hole we went on together in the session until we ran out of time.&lt;/li&gt;
&lt;li&gt;Secondly, I will take you deeper down the same rabbit hole I went on alone the day after.&lt;/li&gt;
&lt;li&gt;I will then finally share the solution that I shamelessly looked at after being thoroughly defeated by the challenge&lt;/li&gt;
&lt;li&gt;The main reason I share all this with you is that it contains some interesting nuggets on how the type system works underneath.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The challenge
&lt;/h3&gt;

&lt;p&gt;As I mentioned already, we chose to do the &lt;a href="https://github.com/type-challenges/type-challenges/blob/main/questions/00020-medium-promise-all/README.md"&gt;Promise.all &lt;/a&gt; challenge. Basically this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Type the function &lt;code&gt;PromiseAll&lt;/code&gt; that accepts an array of PromiseLike objects, the returning value should be &lt;code&gt;Promise&amp;lt;T&amp;gt;&lt;/code&gt; where &lt;code&gt;T&lt;/code&gt; is the resolved result array.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;so:&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;// when passing this array&lt;/span&gt;
&lt;span class="nx"&gt;PromiseAll&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// PromiseAll's return type should be this&lt;/span&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recursion
&lt;/h3&gt;

&lt;p&gt;Our first thought was to recursively go through the passed array and return the awaited value of each for the result. Something like &lt;a href="https://www.typescriptlang.org/play?#code/PQKgBA+l09YJoHsCuAnMBhRATApmACV1X1jKjBGAChqAXATwAd8BBAdwEMBLO3bAAqpEAW24BnXKwA20gEq5xyaXQA8AFTC4AHnwB22cWBKdsiPdIZhOehgG0AugD4wAXjCad+w2Dvc9AGbEHgBi3KjidAA0YAB08f5B6OoKkQ5g1GBgAPy+HDx82BphEXROMfGx+bz8QqISUrKpymopimXpmWAAXL6V1YUaTg4A3LR4AMbSnCRgAch6E3Tc5mB1YpIy0hpaurgGRiZmFlY29s4AFABunNLIir3qAJS96w2qA7XCG43yii1DJxjaigSDkWAedqYTiSIzgiFUajcERMRCoOhgRgsMAAbzAAFEAI7IW4xfHaFhLMAAXzm3zAAHIAAJY3AAWgmAAtbtJ9gBzRTAZDLaTiBm0CbmSJgJjfBpbdTtACMbjWcs2sgudiVMQATDEAMzpGFgSV6SJPahm6Wy+oa6SKyK61Vve1anVgfVqu24WIkcSIaRXXAXA1PY1Ga10S1RmXq36OugGl3xrbuvUxV2+-2B4Oh8MxqUY20-BXtAAsKZ9Ww+qFQnAYqj0yBEACNggAfb0-Jst9uoJyD9Oew0OS30Zj4CYwxSquxdcmUtREknbVmIAJx6uyRMerOqbUZsBGwflBcU3BLVQr26qdebkvynftL37w8jsDNtvEZyDqLnpdr2JW97y3Utn0iA1M3jA8v37GI4OIBC+x-U9-yyRdL2XYC10nDcwKfB0K2gn1e2-VBHDQ6gHGoIA"&gt;this&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;PromiseAll&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="k"&gt;readonly&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AwaitedPromiseAllResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s break this down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduce a generic &lt;code&gt;T&lt;/code&gt; with a &lt;code&gt;any[]&lt;/code&gt; constraint that we can manipulate&lt;/li&gt;
&lt;li&gt;Assign &lt;code&gt;values&lt;/code&gt; to &lt;code&gt;T&lt;/code&gt; and wrap the result of &lt;code&gt;T&lt;/code&gt; in our custom &lt;code&gt;AwaitedPromiseAllResult&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;Within &lt;code&gt;AwaitedPromiseAllResult&lt;/code&gt; we do the following
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// spread T so we can get the first item in the array and the rest&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AwaitedPromiseAllResult&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="k"&gt;readonly&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;TFirst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;TRest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
 &lt;span class="c1"&gt;// Unwrap the promise on the first item and repeat this process for the rest&lt;/span&gt;
 &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Awaited&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TFirst&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;AwaitedPromiseAllResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TRest&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;// when there is only one item left in the array, unwrap it and you are done&lt;/span&gt;
 &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;Awaited&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When testing our &lt;code&gt;AwaitedPromiseAllResult&lt;/code&gt; type separately it seemed to work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bkHr-Lna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8n8pscq9kk6bl8kxim6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bkHr-Lna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8n8pscq9kk6bl8kxim6.png" alt="Result when testing AwaitedPromiseAllResult in isolation" width="690" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;but when using the type in the function we get a whole different result… why, Why, WHY 😡&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5cBXBzJv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pp6eiax0mf9l3z4i4obs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5cBXBzJv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pp6eiax0mf9l3z4i4obs.png" alt="Result when testing PromiseAll function" width="690" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Here is why:
&lt;/h4&gt;

&lt;p&gt;Note that we constrain our generic as an &lt;code&gt;any[]&lt;/code&gt; and then assign our &lt;code&gt;values&lt;/code&gt; param as that. In other words &lt;code&gt;[1, 2, Promise&amp;lt;3&amp;gt;]&lt;/code&gt; would become &lt;code&gt;number | Promise&amp;lt;number&amp;gt;[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Okay, that makes sense. So what if we spread the &lt;code&gt;any[]&lt;/code&gt; as the &lt;code&gt;values&lt;/code&gt; type instead? &lt;a href="https://www.typescriptlang.org/play?#code/PQKgBA+l09YJoHsCuAnMBhRATApmACV1X1jKjBGAChqAXATwAd8BBAdwEMBLO3bAAqpEAW24BnXKwA20gEq5xyaXQA8AFTC4AHnwB22cWBKdsiPdIZhOehgG0AugD4wAXjCad+w2Dvc9AGbEHgBi3KjidAA0YAB08f5B6OoKkQ5g1GBgAPy+HDx82BphEXROMfGx+bz8QqISUrKpymopimXpmWAAXL6V1YUaTg4A3LTUeADG0pwkYAHIepN03OZgdWKSMtIaWrq4BkYmZhZWNvbOABQAbpzSyIq9x+aWffHqDgCUvRsNqgO1YSbRryRQtIZOMbUUCQciwDztTCcSRGOHwqjUbgiJiIVB0MCMFhgADeYAAogBHZB3GJk7QsZZgAC+8yBYAA5AABQm4AC0kwAFndpAcAOaKYDIFbScTs2iTcyRMBMIENbbqdoARjc61VW1klzsmpiACYYgBmdLIsAKvSRT7UW1KlX1fXSDWRE0635uw3GsBm3Wu3CxEjiRDSa64S7mz5WoxOugOxPKvUgj10c3etPbP2mmI+kNhiNRmNx5OK-Eu4Hq9oAFmzwe2-1QqE4DFUemQIgARsEAD5B4Gd7t91BOCd5gMWr60Hk25GKHV2Lp0hlqSnUnY8xABVNN2QZ-2F1RG-NgS0T8qr+m4ZaqTd3VQ7vfVtWH9qBk9n6dgLu94hnAnKIb3XB8qSfF99xrD9InNAs01Pf8xxiZDiFQ0dAKvECsjXO8Nwg7dmFwXdoPfd16wQ4MRwA1BHGw6gHGoIA"&gt;Well&lt;/a&gt; 🙂...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;PromiseAll&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&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="p"&gt;...;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gN_Ea_ia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sx8oobeehhb3ogxx79dy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gN_Ea_ia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sx8oobeehhb3ogxx79dy.png" alt="Spread type as a tuple" width="690" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q5jjo8Vs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6g4nnn391ampxb1m2a0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q5jjo8Vs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w6g4nnn391ampxb1m2a0.gif" alt="Yes" width="200" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome that works, but what happens if I override the generic constraint with something else?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9HyuUMP8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1p6uk87wnzned452bb06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9HyuUMP8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1p6uk87wnzned452bb06.png" alt="Pass generic override" width="690" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fmcEnjaJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uqw282zvcdm88dwwmok.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fmcEnjaJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uqw282zvcdm88dwwmok.gif" alt="Flipping table" width="400" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;This is where I gave up and looked at the solutions. All of them were basically a different flavour of the same thing. But before I just show you the solution allow me to stretch this post unnecessarily out a little more.&lt;/p&gt;

&lt;p&gt;We’ve come to the reason that I was implored to share this with you all. As you’ve seen in the previous section, by spreading an &lt;code&gt;any[]&lt;/code&gt; type you get a tuple. Which is an array of known types. And as you might know, an array is an object. Why is this important? Because Typescript is smart enough to treat it as such and allow you to map over the indexes of an array like you would the properties of a key/value pair object 🤯.&lt;/p&gt;

&lt;p&gt;Or in code words… &lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAsghmAggJ2XEiDOB5ARgKwgGNgAVAewEkA7AEwgA8JMAeUqR4COzKOakAG0AugD4oAXigBvAFBQog0gGkIIKAEtqUANZryAMyilhALmOqQsgL6zZoSFC6Zgk2AhRoMOAsTJU6RmYWQQBGABooACZIgHJMcgBbCABaADc4ABsAVwhYsQBuIA"&gt;basically this&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MapArrayAsObjectToIndexes&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;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TKey&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;TKey&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 href="https://res.cloudinary.com/practicaldev/image/fetch/s--2hlA5mz8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x8t52gw27im7ozhjthqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2hlA5mz8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x8t52gw27im7ozhjthqw.png" alt="demo of MapArrayAsObjectToIndexes result" width="690" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t5SanQL9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6p0wjh7uu490d1n2jvdg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t5SanQL9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6p0wjh7uu490d1n2jvdg.gif" alt="WTF" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yup 🙂&lt;/p&gt;

&lt;p&gt;And finally &lt;a href="https://www.typescriptlang.org/play?#code/PQKgBA+l09YJoHsCuAnMBhRATApmACV1X1jKjBGACg8BjAGwEMSwAzZAOzoBcBLRJzAAFVIgC2fAM64AggwYAeACphcADx65O2KWCacAngG0AugD4AFADcmDZLikAuMCSbZBDQ2GMA6f8qmAJQuohLSuIoA3tRgPgDWYHxC8biGiGxggS6yAO5MfFrYKsbxFtQAvuZg1NSgkOSwWY48mEwyeo1NVNR84gAOiKitPIb9+FFgAKIAjsh2ADTT6uO8YBXsYuJgAOQAAqPjALR0ABZ2DNoA5o7AyPwMUju1dIJSrf1bEfIMyi0AjGAALwiL4yH6WYz-JYAJiWAGZTPo9K9OO8gtRUe8wJ9wuCFH93jDgaC8XIFJDoWA4aTJDJfCQpIgGNZcJZ4UEke0wFieBjeTiweTfi14SSwnThZTYUsJREGY5maz2Zz+W8PkKfoSeAAWcWahSKWSoVBMQyKTjIcQAI2IYAAPrSIharbbUOYPdLqQjgrVDvg6O1HCTjLFlqseIpZvMlP6MoKyVqAbKhYooTKwIiPeYFmGpitcLwo3M7Io45lcZKk0SU2S01SaZabcQLB7c3F8xHizGy2NcPHK98CaLa5K0023UsJ8Qp66W9n2+HC5Ho6Xywmq8P3jrR87p6gzAvqKZqEA"&gt;the solution&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// as before use a generic `T` and convert it to a tuple for `values`'s type&lt;/span&gt;
&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;PromiseAll&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;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&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;T&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// map over the indexes of the array and return their unwrapped values &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;Awaited&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Typescript is fun to play with. And I know a lot of people might have already known all the things that I wrote about, but if there were only one or two people who found this interesting I will feel satisfied. But the bigger reason I shared this is to encourage you to play around. Understanding how Typescript's type system works has greatly benefited our day-to-day work even though we don't implement things in this way directly. So have fun and keep learning.&lt;/p&gt;

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