{"id":7191,"date":"2019-06-15T08:28:16","date_gmt":"2019-06-15T08:28:16","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=7191"},"modified":"2019-06-15T08:28:16","modified_gmt":"2019-06-15T08:28:16","slug":"typescripts-never-type-whats-the-point","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/typescripts-never-type-whats-the-point\/","title":{"rendered":"TypeScript&#8217;s never type, what&#8217;s the point ?"},"content":{"rendered":"<p>At first the <em>never<\/em> type may seem a slightly odd, possibly even pointless type. It can be used to denote that a function never returns, such as an infinite loop or a function simply throws an Error, hence again, never returns. These use cases don&#8217;t seem that useful, but you get the idea. The <em>never<\/em> type denotes that something should never occur. <\/p>\n<p>Where <em>never<\/em> becomes a lot more useful is in situations where something should never occur in your application&#8217;s control flow, specifically regarding choice operators such as <em>switch<\/em> statements and <em>if..else<\/em> when used for exhaustive checks.<\/p>\n<p>Let&#8217;s look at an example of this&#8230;<\/p>\n<p>You have an type Choice which is currently made up of a union of three values, which looks like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\ntype Choice = 'A' | 'B' | 'C';\r\n<\/pre>\n<p>Let&#8217;s now create a simple function which returns a string based upon the choice value<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nfunction makeChoice(choice: Choice) {\r\n  switch(choice) {\r\n    case 'A': return 'A selected'\r\n    case 'B': return 'B selected'\r\n    case 'C': return 'C selected'\r\n  }\r\n  \/\/ should never reach\r\n}\r\n\r\nmakeChoice('C');\r\n<\/pre>\n<p>We&#8217;re handling all the possible values of the union and all is fine with the world. <\/p>\n<p>TypeScript correctly transpiles the code and if we mistakenly replace the change <em>makeChoice(&#8216;C&#8217;)<\/em> to <em>makeChoice(&#8216;D&#8217;)<\/em> (not included in the union) TypeScript reports the error <em>Argument of type &#8216;&#8221;D&#8221;&#8216; is not assignable to parameter of type &#8216;Choice&#8217;<\/em>. <\/p>\n<p>What happens is &#8211; if we had a <em>default<\/em> case or if the options within the switch were exhausted and the instruction pointer made it to the comment part of the function &#8211; which in this case should never occur (as all values in the union are handled). This is where the <em>never<\/em> type comes in once all options are exhausted the choice variable in essence becomes a type <em>never<\/em>. I know, it seems strange, but read on&#8230;<\/p>\n<p>So, what if we add a new value to the Choice union, let&#8217;s say &#8216;D&#8217;, then we have a bit of a problem, TypeScript will transpile without error but our case statement is not handling the new value and hence this may get into production without warning.<\/p>\n<p>Let&#8217;s make this a little more obvious by changing our code to this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nfunction makeChoice(choice: Choice) {\r\n  switch(choice) {\r\n    case 'A': return 'A selected'\r\n    case 'B': return 'B selected'\r\n    case 'C': return 'C selected'\r\n  }\r\n  let c: never = choice;\r\n}\r\n<\/pre>\n<p><em>Note: Assuming unused variables are not set as errors in your preferred linter then everything will compile and appear without error.<\/em><\/p>\n<p>What&#8217;s happening here is that the transpiler knows that all choice options are exhausted, hence choice (if you like) changes to become of type <em>never<\/em>. Hence the line of code <em> let c: never = choice;<\/em> is valid as this line\/instruction should never occur. <\/p>\n<p>What happens it we add a new choice, so we now add &#8216;D&#8217; to the Choice union and TypeScript will now report an error. This is because the <em>choice<\/em> variable may now have another value which is not handled by the switch statement and we&#8217;ll get the following error &#8220;Type &#8216;&#8221;D&#8221;&#8216; is not assignable to type &#8216;never'&#8221;. Which is good because now when we transpile time we&#8217;ll be alerted to a potential issue. <\/p>\n<p>Prior to adding the <em>let c: never = choice<\/em> if we transpile the code to JavaScript we get the following code, which if we change &#8216;C&#8217; to &#8216;D&#8217; will not report any problem (which could be fine or could be bad depending upon our usage).<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nfunction makeChoice(choice) {\r\n   switch (choice) {\r\n      case 'A': return 'A selected';\r\n      case 'B': return 'B selected';\r\n      case 'C': return 'C selected';\r\n   }\r\n}\r\nmakeChoice('C');\r\n<\/pre>\n<p>So what we really want to do in our TypeScript file is throw an Error in place of the <em>let c: never = choice<\/em>, then this will catch non-exhaustive switch statements and will be transpiled into JavaScript to give us a runtime guard to highlight a potential issue. <\/p>\n<p>Let&#8217;s create a simple function to handle this so our code now looks like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nfunction unreachable(param: never): never { \r\n   throw new Error('should not reach here')\r\n}\r\n\r\nfunction makeChoice(choice: Choice) {\r\n  switch(choice) {\r\n    case 'A': return 'A selected'\r\n    case 'B': return 'B selected'\r\n    case 'C': return 'C selected'\r\n  }\r\n  unreachable(choice);\r\n}\r\n<\/pre>\n<p>which transpiles to almost exactly the same code.<\/p>\n<p>As the function <em>unreachable<\/em> never returns, we mark it as such by using the <em>never<\/em> return type.<\/p>\n<p>If we now try to pass &#8216;D&#8217; to the function <em>makeChoice<\/em> in the JavaScript code, an exception will occur so we&#8217;re covered at runtime now as well as at tranpsile time.<\/p>\n<p>Another example of using <em>never<\/em> is in the type <em>NonNullable<\/em> which is part of TypeScript.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\ntype NonNullable&lt;T&gt; = T extends null | undefined ? never : T;\r\n<\/pre>\n<p>In this instance if the generic type T is null or undefined then <em>never<\/em> is returned, hence the following type will actually be of type <em>never<\/em> and this not assignable to<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\ntype A = NonNullable&lt;null&gt;;\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>At first the never type may seem a slightly odd, possibly even pointless type. It can be used to denote that a function never returns, such as an infinite loop or a function simply throws an Error, hence again, never returns. These use cases don&#8217;t seem that useful, but you get the idea. The never [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[46],"tags":[],"class_list":["post-7191","post","type-post","status-publish","format-standard","hentry","category-typescript"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7191","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=7191"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7191\/revisions"}],"predecessor-version":[{"id":7209,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7191\/revisions\/7209"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=7191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=7191"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=7191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}