<?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: beraliv</title>
    <description>The latest articles on DEV Community by beraliv (@beraliv).</description>
    <link>https://dev.to/beraliv</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%2F209777%2F6c5bda2e-d2b6-4a93-a2b8-f08ece8951d6.JPG</url>
      <title>DEV Community: beraliv</title>
      <link>https://dev.to/beraliv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/beraliv"/>
    <language>en</language>
    <item>
      <title>Advanced Typed Get</title>
      <dc:creator>beraliv</dc:creator>
      <pubDate>Sun, 04 Apr 2021 15:33:06 +0000</pubDate>
      <link>https://dev.to/beraliv/advanced-typed-get-52ak</link>
      <guid>https://dev.to/beraliv/advanced-typed-get-52ak</guid>
      <description>&lt;p&gt;Not a long time ago I discovered &lt;a href="https://github.com/type-challenges/type-challenges"&gt;type-challenges&lt;/a&gt; for myself. Today I'll show not only the implementation of &lt;code&gt;Get&lt;/code&gt;, but also some common issues with the implementation, improvements and its usage in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic implementation
&lt;/h2&gt;

&lt;p&gt;As I said, there's a repo on GitHub: type-challenges. &lt;a href="https://github.com/type-challenges/type-challenges/blob/master/questions/270-hard-typed-get/README.md"&gt;The current challenge&lt;/a&gt; is located in the "hard" category.&lt;/p&gt;

&lt;p&gt;Here we work only with objects (as the solution doesn't require accessing arrays and tuples) and also we always can access object keys as they are defined in test cases.&lt;/p&gt;

&lt;p&gt;So what should we start then from?&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting keys
&lt;/h3&gt;

&lt;p&gt;Imagine we solve the same challenge in JavaScript:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qnbd-vMY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kfisg2ivxrnqq9z9yu6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qnbd-vMY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kfisg2ivxrnqq9z9yu6.png" alt="Get function in JavaScript" width="880" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before calling &lt;code&gt;keys.reduce&lt;/code&gt;, we need to get a list of all keys. In JavaScript we can call &lt;code&gt;path.split('.')&lt;/code&gt;. In Typescript, we also need to get the keys from the path string.&lt;/p&gt;

&lt;p&gt;Thankfully, since TypeScript 4.1, we have &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-1/#template-literal-types"&gt;Template Literal types&lt;/a&gt;. We can infer the keys by removing dots.&lt;/p&gt;

&lt;p&gt;We can use the &lt;code&gt;Path&lt;/code&gt; type to do so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a6O98UQh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2isycizim005bqmu11se.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a6O98UQh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2isycizim005bqmu11se.png" alt="Path transforms a string into keys, version 1" width="880" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks very simple and short. However once we write tests, we understand what was missed, as seen in the &lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBACghsAFgHgCoD4oF4qqhAD2AgDsATAZygAMASAbwEsSAzCAJygGkIQBfAHQNmbTgCUIFYH2oAoKFAD8UANo8QAGigCd8JMglT0AXXlQAXKtOyA9ACooAfWcvXL3JOBQAwnAqSnNyDHKDsbWUYAWzAAe3YveigAUQBHAFc4ABstJIJIAGMvPigWdhjIqAByAAFQSABafMQszNIAc0kbNOBGTIpK2Vk66Hy-AJwVM1yC4GRUjMzkPRRKmJIIeoBrXnqwBERK9C0VVfWtnb2kSuN0I6m8iEK59Kyl-eRKgCZzkAFLg6Oqi+P0qWkq-2utw09xmzwWb30lSQ7AgEAE21+EMBJ2RqNBVQx+PB+0hd2MQA"&gt;Playground validation&lt;/a&gt;. We forgot the case with only one single key left. Let's add it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hFkBy8rN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obfokhxlvxgaee115f0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hFkBy8rN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obfokhxlvxgaee115f0a.png" alt="Path transforms a string into keys, final version" width="880" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To try it out, we can have a look at the &lt;a href="https://www.typescriptlang.org/play?ssl=5&amp;amp;ssc=9&amp;amp;pln=1&amp;amp;pc=1#code/C4TwDgpgBACghsAFgHgCoD4oF4qqhAD2AgDsATAZygAMASAbwEsSAzCAJygGkIQBfAHQNmbTgCUIFYH2oAoKFAD8UANo8QAGigCd8JMglT0AXXlQAXLnxFSlGsNYduvGWYXK1vUwoWWVp2QB6ACooAH0IyKjI3ElgKABhOApJcOj0sKhgwNlGAFswAHt2ePooAFEARwBXOAAbLXKCSABjeL4oFnZCvKgAcgABUEgAWhbEerrSAHNJQOrgRjqKPtlZYegW5NScFTMm1uBkKtq65D0UPsKSCBGAa14RsAREPvQtFSub+8fnpD7jOh3vtmhA2scavVzi9kH0AEw-EACP6vd6qeGIvpaPoogFAjQgw4Q07Q-R9JDsCAQAQPJG4tGfClUrH9WksnEvPHA4xAA"&gt;Playground with tests cases&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reducing the object
&lt;/h3&gt;

&lt;p&gt;After having the keys, we can finally call &lt;code&gt;keys.reduce&lt;/code&gt;. To do so, we use another type &lt;code&gt;GetWithArray&lt;/code&gt; so we already know that keys are a string tuple:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yq-Kv0v9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sa6xsck0omxijuezy0ig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yq-Kv0v9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sa6xsck0omxijuezy0ig.png" alt="GetWithArray for objects, version 1" width="880" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explain it in more detail:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;K extends [infer Key, ...infer Rest]&lt;/code&gt; checks that we have at least one element in a tuple&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Key extends keyof O&lt;/code&gt; lets us use &lt;code&gt;O[Key]&lt;/code&gt; to move recursively to the next step&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's test it again on the &lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBA4hwHUCWwAWBBATpghiAPAPIA0UA0gHxQC85UEAHsBAHYAmAzlANpIsBmETOQghSAOkl9BwgEoQOwALoAoKFAD8IkPSatOUANaiA9vyiE16zbHjI0WXAULcyopaXmKKV9QC4oFggANyErAKDQzBUVAHoAKigAfRTUtNSoABUFYCgAYRwOBWT00qSoeNiVJABbMBNMXIBvKABRAEcAVxwAG1JWhkgAY1yAXyh+TBMaqAByAAFQSABaIdRentYAcwVYzuAkHo5ZmKXobMVCACMAKwgRmigmqwPgTYCAAwBlIamenquOGEQ06immSA4OAOJhYHysbChEE+ACYAAwARgAHMt0ajlqiACxw9Q4faoBoBZ7WQI4GpIqAfdCbBiiKAAISEEAAXnxidYeiYhlCkDDKb5rEMUCBPgBZTosJBrPnqUZWVWqlRnKBCopcWjcKwDYbAfAdbo9fBwRAoDDYPD4C7Aa53EakbizV6bWZKCikb6-Ez-QHA0HAcGQ6Gwii+w2De4ms29S12G2Oe2O53xt2zBHMb2+hlorE4vGEj7R4ix42mrpJq32W1OB05TOung5hS-JBgSP50iRIQVqvxmvm5PWhx2ggZ25Z9uktANWakWYsWkQPsMpmMVkczDc3lD9RGkeJi311NT5uXWdt90L8mYZdzAVC3sryWgTcfOUKpVHto4xGUc6xTScmxnF1gGzB8lw-IE2GfVdOhqK4hE3AdMCHJQgA"&gt;Playground&lt;/a&gt;. We again forgot the last case with a tuple without elements. Let's add it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DCHamx1p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eexpl99drr9tzya6er1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DCHamx1p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eexpl99drr9tzya6er1z.png" alt="GetWithArray for objects, version 2" width="840" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBA4hwHUCWwAWBBATpghiAPAPIA0UA0gHxQC85UEAHsBAHYAmAzlANoC6AUFCgB+KIUFQAXHUbN2XbkhYAzCJnIQQpAHS6lq9QCUIHYAKFDRZTfSatOUANaaA9srESLI2PGRosuASE3NYgvKTGphSeFtIsEABuajFxicn8APQAVFAA+vkFhQVQAComwFAAwjgcJnlFDblQWRn8SAC2YC6YFQDeUACiAI4ArjgANqQDDJAAxhUAvlDKmC7tUADkAAKgkAC0s6gT46wA5iYZI8BI4xwb-Py70GWmhABGAFYQ8zRQvRLXYAnaQAAwAyrNVuNxm8cOpZiNTGskBwcNcXCwQRI2GiIKCAEwABgAjAAOPbEwl7QkAFixQhwV1Q3Wk-y8LBw7TxUBB6BODBsACE1BAAF5KekWcYuWZopAY1kxISzFAgUEAWRGLCQh0lQgWEgNBse4GgstqXFo3Ak0zmwHwwzG43wcEQKAw2Dw+BewHeX3mpG4G0BJw2vAopHBkJc0Nh8MRwGRqPRmIoEZtM2+9sdExdvndAS9Pr9WcDGxxzDDEZ5RLJFKptJBaeIGbtDtGuddfg9gW95RLAZ45ZMkKQYBTVdI8SSmGbraz7adebd-k9BGLn1LQ8ZaG6G1IGw5XMnPL5jCFIvFqfTQltC5zzq7BbXfdem8HQZ3zMw+820tlE4HiqoAniCmrarqc63pm8yLp2+arr2G7+sAZZfnuQFwmwv6HiM7RvGoJ7Tmoc68EAA"&gt;Final version with tests is available on Playground&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  All together
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3cPp5UX---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3irjjqup2217mgphgbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3cPp5UX---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3irjjqup2217mgphgbp.png" alt="Get for type challenge" width="850" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's test it together to clarify everything's working as expected: &lt;a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBACghsAFgHgCoD4oF4qqhAD2AgDsATAZygAMASAbwEsSAzCAJygGkIQBfAHQNmbTgCUIFYH2oAoKFAD8UANo8QAGigCd8JMglT0AXXlQAXLnxFSlGsNYduvGWeVrephZZWnZoSCgAcQhgAHVGJABBdnY4EGQAeS0uTBwua2JyKl83KESzSwzCLLsVESd1LR0BCvFJYC8FJWcQTNsqAGteAHsWfLNmlpDwyMQYuITEjxBjLUNgdEHmyxIIADcOZdWNrf9waBGkrRg04NCI6Nj449gEFFOl2QB6ACooAH0v75-v3AaoABhOAUSSfX4Qj5QV7PWSMAC2YB67GAUHoUAAogBHACucAANloMQRIABjVF8KAsdg9eFQADkAAEAhAALSkxAE-GkADmkmeOOAjHxFHpsn2gVQDUSACMAFYQcnYNFmIXAbmWagAZVJNPx+JlcE4pJxUlpjAoCEYPRIcgUZAQEE1ACYAAwARgAHKz3a7Wa6ACx2qBwQWIZGWejLEhweFOmhRbkEXhQABCHAgAC9mMGFPieqSrTbI8sFKTIiBNQBZHEkRgc3NQPhmZvNiXQQugqg4FRmYlk4DIbF4-HII5SqSyhXkrT0tXc+noLTa3U9fWG42m4Dmy1Cm3UdBLvskxWD4cEsehNDS+Wn2cO4iL5dur0+v2Bg9HhT909D3EX8cb2nYB70kXVGDAPcSCfKA1k2dhDw0Y8Bz-EdL0HCdgCnO8GVDJBkQEGM4xg6hE0IFN03YLMc0Q5Df3PUdAMnW8Z1wsMCPzQsoIEctQBIms6wbWjvxPclUIAq9MOw1j6Tw8N2B4o0yEInF4RlDgYLgjhaOMIA"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great, we did it ✅&lt;/p&gt;




&lt;p&gt;To read the full article, go to &lt;a href="https://blog.beraliv.dev/2021-03-26-typed-get/"&gt;Advanced Typed Get | beraliv&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also includes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.beraliv.dev/2021-03-26-typed-get/#2-optional-paths"&gt;Optional paths&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.beraliv.dev/2021-03-26-typed-get/#3-accessing-arrays-and-tuples"&gt;Accessing arrays and tuples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.beraliv.dev/2021-03-26-typed-get/#4-one-solution"&gt;One solution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.beraliv.dev/2021-03-26-typed-get/#5-binding-to-javascript"&gt;Binding to JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.beraliv.dev/2021-03-26-typed-get/#summary"&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

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