{"id":3163,"date":"2021-10-27T12:48:52","date_gmt":"2021-10-27T20:48:52","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=3163"},"modified":"2023-04-27T13:11:28","modified_gmt":"2023-04-27T21:11:28","slug":"type-treat-2021-day-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/type-treat-2021-day-3\/","title":{"rendered":"Type | Treat 2021 \u2013 Day 3"},"content":{"rendered":"<h2>Type | Treat Challenge 3<\/h2>\n<p>Welcome to the third <code>Type | Treat<\/code> challenge! These challenges are a series of blog posts which have 2 code challenges in, one for beginners and one for intermediate TypeScript programmers. We&#8217;re on day three, which means going over the answers from <a href=\"https:\/\/devblogs.microsoft.com\/typescript\/type-treat-2021-day-2\/\" rel=\"nofollow\">yesterday<\/a> and have 2 new challenges.<\/p>\n<h2>Yesterday&#8217;s Solution<\/h2>\n<h3>Beginner\/Learner Challenge<\/h3>\n<p>There is many ways to decide how to type existing data, you could use <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/2\/everyday-types.html#literal-types\" rel=\"nofollow\">literal types<\/a> when you&#8217;re sure of the exact formats &#8211; or be more liberal and use <code>string<\/code> when you expect a variety. We opted for literals, but using <code>string<\/code> is totally cool too.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre><span class=\"pl-k\">type<\/span> <span class=\"pl-smi\">UnderripePumpkin<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">color<\/span>: <span class=\"pl-s\">\"green\"<\/span><span class=\"pl-kos\">,<\/span>\r\n    <span class=\"pl-c1\">soundWhenHit<\/span>: <span class=\"pl-s\">\"dull thud\"<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-k\">type<\/span> <span class=\"pl-smi\">RipePumpkin<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">color<\/span>: <span class=\"pl-s\">\"purple\"<\/span> <span class=\"pl-c1\">|<\/span> <span class=\"pl-s\">\"orange\"<\/span> <span class=\"pl-c1\">|<\/span> <span class=\"pl-s\">\"blue\"<\/span><span class=\"pl-kos\">,<\/span>\r\n    <span class=\"pl-c1\">soundWhenHit<\/span>: <span class=\"pl-s\">\"echo-y\"<\/span>\r\n<span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-k\">type<\/span> <span class=\"pl-smi\">OverripePumpkin<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span>\r\n    <span class=\"pl-c1\">color<\/span>: <span class=\"pl-s\">\"green\"<\/span> <span class=\"pl-c1\">|<\/span> <span class=\"pl-s\">\"white\"<\/span><span class=\"pl-kos\">,<\/span>\r\n    <span class=\"pl-c1\">soundWhenHit<\/span>: <span class=\"pl-s\">\"squishy\"<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>The second part of the challenge used <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/2\/narrowing.html#using-type-predicates\" rel=\"nofollow\">type predicates (or type guards)<\/a> annotates a function which returns a <code>booleon<\/code> with narrowing information about the paramters. This means we can tell TypeScript that when the return values to <code>isRipe<\/code>is true, then the argument <code>pumpkin<\/code> is of the type <code>RipePumpkin<\/code>:<\/p>\n<div class=\"highlight highlight-source-diff\">\n<pre><span class=\"pl-md\"><span class=\"pl-md\">-<\/span> function isRipe(pumpkin: any) {<\/span>\r\n<span class=\"pl-mi1\"><span class=\"pl-mi1\">+<\/span> function isRipe(pumpkin: any): pumpkin is RipePumpkin {<\/span>\r\n       return \"soundWhenHit\" in pumpkin &amp;&amp; pumpkin.soundWhenHit === \"echo-y\"\r\n  }<\/pre>\n<\/div>\n<p>Successfully completing this challenge would have no errors.<\/p>\n<p><a href=\"https:\/\/www.typescriptlang.org\/play?#code\/JYWwDg9gTgLgBAbwMYQgawAoFdxuAOwGUIswBfOAMyghDgCIYBPMAUwFpp2YpWBDGPQBQQgPSi4ATRIByXnAAWrADZgCAczgl4AuHzjKISPsqqoAJuwBGffGjg8mGhxDgBnaDrESrwTWuVWLUo4MBwwPHw3OAIYVw8QVhgFZwB3FKQFGOisNz4rQLMoOBA+SPVvOAAVBT5gUPDI9xIwOAAKPnNzZsSDVhAIfHUoPjc3ABo4TOBlZXrbbpQUfCx4EBm0ADoAShFlt3gw3AI3AC44bGP8AG0AXTgAXjhroTg3xCmIQyhz+mHWVj4eiTDxYfDmADqSnwAAlgDBfuYsLMHAosOZ6HAyONXu8EJ9vr8wlAwIFgc0wZDoXCEQxWJkIOwmJjsbi3viUISGP9AeTQeCoYCaYjkaZkuiWTj3h9OdBful4aw+SQBdT4b83ABHLDANwKZlYqV4glyhjQWzqJUglVUoXqukMpmStkyr6mv68XnWymC2H2+hIlHijGGl0ct0-M0jIZWimqu20+j0hSMg2s6Xhrn0ApYWP821+xPJ1POjMmyP0c0x5U+tVFx1poT3ETiOAAYVscCYJDgrAAHjw+Eh4Mkgsw2NFKNBUZ64OZgJRKKxePh4MYYKx1NBgKxohAQqO3EEjhETgB+ETjoIAVXBy6gwDYl1P+EeiBdsorPKBRre+d9woMIGYpohiQhkEIV5wAASo+rDPk0TwIB+EZElgJJknAAA+UYWkq2EMDmVouv+da-MWTrgZBLBBAA8gAbvecEIQQb7IdKn6-N+mI4fQCobsCJE2gB-pajqerMlRlQQqwMgorkQT6FBYLAIMLjuHwTCoro+gnk0xivlYin4Fp+6orux4QGMwAFGONFuJeNEXI0rFPHAt7mExT4ua+OGwd5VwEQxXnwT5LYSAAMqgaDRFuEDmJM+AQKkfQwNEpRoIpoQ7pMqRBKktgjq4lDAFABxwJa8DaHoKJmaOcAPmwDRXG4myVDUuqfJ5cCpNAMV6PAUBgjAoCsJMVirNUNGEEgjXwOYEC7vgMjwEe-TqZSy4HAs2nwAABnpJwAGLQBgO57ZUnWDMoWn+aFVwyNESWpJs7adt2WCogQ9hmfoBVaXEUy1DG5lwHtup3Xt6l-FgfBQCG9WMDR9AXkIlBgsOqmvhDcFtId+DnCx+DbOc+PZDBzE+e+0q8DA6GvvQpEJpirFkwAZGzzUvpsTOFo8DxPEmDbCBBQj7IcPluCdUBnUETz461JXKBuUBtDjbC7K27wAHoXuLFKtE8KDoETxCkHjkvS7LmsSDrF5AA\" rel=\"nofollow\">Our answer<\/a>.<\/p>\n<h3>Intermediate\/Advanced Challenge<\/h3>\n<p>This challenge was first about understanding different read vs write properties available in both <code>classes<\/code> and <code>interface<\/code>\/<code>typed<\/code> objects. Personally, I&#8217;ve seen this with <code>document.location<\/code> a lot where you always get a rich object when you read but can write to that property with a string. We wanted a similar concept, but using <code>punch<\/code> which for me is generally a &#8216;throw it all in and see what happens&#8217; style of drink.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre><span class=\"pl-k\">class<\/span> <span class=\"pl-smi\">PunchMixer<\/span> <span class=\"pl-kos\">{<\/span>\r\n  #<span class=\"pl-c1\">punch<\/span>: <span class=\"pl-smi\">Punch<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-kos\">{<\/span><span class=\"pl-c1\">flavour<\/span>: <span class=\"pl-s\">''<\/span><span class=\"pl-kos\">,<\/span> <span class=\"pl-c1\">ingredients<\/span>: <span class=\"pl-kos\">[<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">}<\/span><span class=\"pl-kos\">;<\/span>\r\n\r\n  <span class=\"pl-k\">public<\/span> <span class=\"pl-k\">get<\/span> <span class=\"pl-en\">punch<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-kos\">)<\/span>: <span class=\"pl-smi\">Punch<\/span> <span class=\"pl-kos\">{<\/span>\r\n      <span class=\"pl-k\">return<\/span> <span class=\"pl-smi\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">punch<\/span><span class=\"pl-kos\">;<\/span>\r\n  <span class=\"pl-kos\">}<\/span>\r\n\r\n  <span class=\"pl-k\">public<\/span> <span class=\"pl-k\">set<\/span> <span class=\"pl-en\">punch<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">punch<\/span>: <span class=\"pl-smi\">Punch<\/span> <span class=\"pl-c1\">|<\/span> <span class=\"pl-smi\">Punch<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-s\">'ingredients'<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">[<\/span><span class=\"pl-smi\">number<\/span><span class=\"pl-kos\">]<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n      <span class=\"pl-k\">if<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-k\">typeof<\/span> <span class=\"pl-s1\">punch<\/span> <span class=\"pl-c1\">===<\/span> <span class=\"pl-s\">'string'<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n          <span class=\"pl-smi\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">punch<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">ingredients<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">push<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">punch<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n      <span class=\"pl-kos\">}<\/span> <span class=\"pl-k\">else<\/span> <span class=\"pl-k\">if<\/span> <span class=\"pl-kos\">(<\/span><span class=\"pl-s\">'flavour'<\/span> <span class=\"pl-k\">in<\/span> <span class=\"pl-s1\">punch<\/span><span class=\"pl-kos\">)<\/span> <span class=\"pl-kos\">{<\/span>\r\n          <span class=\"pl-smi\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">punch<\/span> <span class=\"pl-c1\">=<\/span> <span class=\"pl-s1\">punch<\/span><span class=\"pl-kos\">;<\/span>\r\n      <span class=\"pl-kos\">}<\/span> <span class=\"pl-k\">else<\/span> <span class=\"pl-kos\">{<\/span>\r\n          <span class=\"pl-smi\">this<\/span><span class=\"pl-kos\">.<\/span>#<span class=\"pl-c1\">punch<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-c1\">ingredients<\/span><span class=\"pl-kos\">.<\/span><span class=\"pl-en\">push<\/span><span class=\"pl-kos\">(<\/span><span class=\"pl-s1\">punch<\/span><span class=\"pl-kos\">)<\/span><span class=\"pl-kos\">;<\/span>\r\n      <span class=\"pl-kos\">}<\/span>\r\n  <span class=\"pl-kos\">}<\/span>\r\n<span class=\"pl-kos\">}<\/span><\/pre>\n<\/div>\n<p>This solution uses a mix of private class fields, indexed types and type narrowing to set up a local punch object which is always returned.<\/p>\n<p>The next step was to make this class generic in some form so that a type parameter passed in to the class would dictate what the return value of a <code>vend<\/code> function was.<\/p>\n<div class=\"highlight highlight-source-diff\">\n<pre><span class=\"pl-md\"><span class=\"pl-md\">-<\/span> class PunchMixer {<\/span>\r\n<span class=\"pl-mi1\"><span class=\"pl-mi1\">+<\/span> class PunchMixer&lt;MixerType&gt; {<\/span>\r\n<span class=\"pl-mi1\"><span class=\"pl-mi1\">+<\/span>    mixer!: MixerType;<\/span>\r\n\r\n  \/\/ ...\r\n<span class=\"pl-mi1\"><span class=\"pl-mi1\">+<\/span>   public vend(): MixerType {<\/span>\r\n<span class=\"pl-mi1\"><span class=\"pl-mi1\">+<\/span>        return this.mixer;<\/span>\r\n<span class=\"pl-mi1\"><span class=\"pl-mi1\">+<\/span>    }<\/span>\r\n  }<\/pre>\n<\/div>\n<p>We were not too worried about how you passed back the <code>MixerType<\/code> &#8211; our first draft had <code>return {} as MixerType<\/code> but a private field feels nicer.<\/p>\n<p><a href=\"https:\/\/www.typescriptlang.org\/play?#code\/PTAEHUFMBsGMHsC2lQCMCGsDWoBmAnJUAT3gFd9RDV4AXAS1gGdQALTHWdRABwEJQATXIByAG4pUkSADtQ6JlkgATUPVwAoECXKgucskxSkKoGZADuoRfWjQWteKETol8qvBq1QF1o1Zs6DLK0JAsWmCI9AAe9DIA5qC0rCg8ZDKwAbjwlEGgZDwIUQmgPOj4tMQAdBoRoAAK6ZlqLHlxtJD4YQwlyvhxOFJchsa6+qVk3uh21jm0LPC4SX4JTHXtTvS0ADQkkN5bLfLQFujELLDQCkaqCqAARGkZrPc+KXImzq4o6HoFNRpKjwUI1nqAALygADeGlAcLwVzE5HwAC5rLR+glYfC4vEusp6LJ5miABRMDG40AAH2heHwZC2aPJmPiuxkZEQUlRZg5XNAAF8AJQAbQAuhp+bVtFBxCgXDxgapyN5fOgVbZoIEFbJ5N4TJQyhViLtxp8LP0Ou5Ltc6r5-D4clgWBYtgFpprkpIYPArAhlJAAPygWrWpgsUGZACyMU6AB5o9FOgAVYjAgB80OxcIAxE9MmiIwFIVDcIjkWiRCJdrj8YSZMTQGL+QBuLPOGP4PhohPJ1OQVtttKoaCMUDxfYTZ4kwUFpoBGHwxdUfYUOTJehMKq5uetxeSwdkYejozePOsEln2dgmmF4UiGsqOvzESi4XszmdUWCzNLnFLElApAiyTs04JgaAIjMriIjfguv5Luum7bs8VQPgSRKbmkTDnmegq7vB-KgDARhqP+IilugSIUCIahyLhP7wYuiFbmeEIgaw+G-oRxEoHBjFwsxyGZKhCS1hhVRYThc54W2e5tvui5DiOsCgBIwTTt2HYpsCDG-l0tCrssG5VFEib4JxAoSlKYAkuoOhkD4QTeI4ST4MQRnOq6yp6FcYZhLsnzjH08A8MsKDmFYUjQD62x1KgkygHQKT4C6Ri7DwoQKCgmUSB5ejwP6xzwOYgohsV5LtmZbERQ0c49vg07WaAADKSA-LADDlW89rsNqcjKBQlKeqU5SVLsLhxNA7kjKoLliNM9DKGqkB1PqPnXA6+BOvILCQNEwIdSoZUyBVRLJik9Sje5kIkjI3CQEyFIJN+4IZlCkoICd3h4ugqAAIIAOK+SwN13cgj0sulc5XpkL1vR95XOSFACqPCFmxt33RDuJQ88MOsHD0II198jKMoACSsAoDdl61c8hPvbUGi4E0nV0VdzW0KNTDTrppMU1TJKmZ0EnSW2bZnfgSYXVdJL3H99ylYuwv4KLYKQvcAMMuYYagAADFUev3LUi6S9LkCXUacsAEKK22Ktq6BtIEAytBovczLoBYXL9GE9xsrynRogAbJZEv1udFuy-cADCduLj9-1A9cNv+5VIu4W2jg8KjhZy3H40do7BPBvbRescWdKu+7P3AkwafvlyaIAEwAMyWcr5dzmx9z1HEkDoAqoSgAAUgyVPG222gkiFbPTNWSyfPSa5+BcBUoEw3AZZAuyIdYrDkNAqgyHQRH4IQ+BK3+oBC13KFoU+m6hAkySgHw4EACywbJ+UnfAoRVE6BfOWrVkDrhKPEU+wtVAFFomFdi8d4SSn3NoS23hm5HF+LgSwoARw6zQN6KwiENCGkqJzbmjUmox2Kj9eYu92AqkdCoRKCULAwE1CSNhbAQqQD4N+JgTgTAiFUCOJQdQXJMC4MPNaPD8BqnoMVJITh2DBGHi4GQ7kVYsDiPA0h1RgzaCTE4ZQThkhqnssI3B9A3AuRcDYlI61dbjnMP0KRU15DzVsL9UIdQgizWUZRH4eBWYKLkNkSgakCQlG8p6eglBQxGBYAAWjME4cwR1tAuQsDkNySinCIDIM0X6MSHH0F4KEZA9Z5GKP9FzWwLBkooAAFaGFoHUcczkHGAWdI6Skdw9oHQ6MoKopdAItX-vAGOsDK4IGitye4+JXiSjGcnXWlcmD0AAF4PQeEwFwdglm1BZhkNmI0KiEiYH9Wgf0NHNSkZAXmcFPoVRHGIXEAAleASB6rVRwYWeqsZWrRSmTwNMjU4TPO8FgLYmRZA-MhDVf5HZYyrKYGC0q2IzYyytvLRB0LaCwpkPVYuPdOZuWIFgY2ELEZjmBmxfFhLiWRPBaAbQ8IAB6AZsTxGBlUDZ2ymZwixVHHFtsr6vI+V8xAxKK4PHeawQ85RUCj3HpAKlv8KqwGmVYt5CRPnfKLsyq+bK4ScuxFqngVRZk5CskAA\" rel=\"nofollow\">Our Answer<\/a>.<\/p>\n<h2>The Challenge<\/h2>\n<h3>Beginner\/Learner Challenge<\/h3>\n<p><a href=\"https:\/\/gist.github.com\/gists\/927ccc66ae3022dc64c4f650109b937a\" rel=\"nofollow\">Figure out how to stop people giving you bad strings for your custom lengths.<\/a><\/p>\n<h3>Intermediate\/Advanced Challenge<\/h3>\n<p><a href=\"https:\/\/gist.github.com\/gists\/927ccc66ae3022dc64c4f650109b937a\" rel=\"nofollow\">Stop losing your literals in Halloween posters<\/a><\/p>\n<h2>How To Share Your Solution<\/h2>\n<p>Once you feel you have completed the challenge, you will need to select the <strong>Share<\/strong> button in the playground. This will automatically copy a playground URL to your clipboard.<\/p>\n<p>Then either:<\/p>\n<ul>\n<li>Go to Twitter, and create a tweet about the challenge, add the link to your code and mention the <a href=\"https:\/\/twitter.com\/typescript\" rel=\"nofollow\">@TypeScript<\/a> Twitter account with the hashtag <a href=\"https:\/\/twitter.com\/search?q=%23TypeOrTreat\" rel=\"nofollow\">#TypeOrTreat<\/a>.<\/li>\n<li>Leave us a comment with your feedback on the <a href=\"https:\/\/dev.to\/typescript\" rel=\"nofollow\">dev.to<\/a> post, or in this post.<\/li>\n<\/ul>\n<h3>Best Resources for Additional Help<\/h3>\n<p>If you need additional help you can utilize the following:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/intro.html\" rel=\"nofollow\">The New TypeScript Handbook<\/a><\/li>\n<li>The <a href=\"https:\/\/discord.com\/invite\/typescript\" rel=\"nofollow\">TypeScript Community Discord<\/a><\/li>\n<li>The comments on each <a href=\"https:\/\/dev.to\/typescript\" rel=\"nofollow\">Dev.to<\/a> post!<\/li>\n<li>Our previous <a href=\"https:\/\/www.typescriptlang.org\/play\/#gist\/303ebff59a6fc37f88c86e86dbdeb0e8-0\" rel=\"nofollow\"><code>Type | Treat<\/code> 2020 challenges<\/a><\/li>\n<\/ul>\n<p>Happy Typing \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Type | Treat Challenge 3 Welcome to the third Type | Treat challenge! These challenges are a series of blog posts which have 2 code challenges in, one for beginners and one for intermediate TypeScript programmers. We&#8217;re on day three, which means going over the answers from yesterday and have 2 new challenges. Yesterday&#8217;s Solution [&hellip;]<\/p>\n","protected":false},"author":6925,"featured_media":3143,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3163","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Type | Treat Challenge 3 Welcome to the third Type | Treat challenge! These challenges are a series of blog posts which have 2 code challenges in, one for beginners and one for intermediate TypeScript programmers. We&#8217;re on day three, which means going over the answers from yesterday and have 2 new challenges. Yesterday&#8217;s Solution [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/3163","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/users\/6925"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/comments?post=3163"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/3163\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media\/3143"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media?parent=3163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=3163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=3163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}