{"id":2086,"date":"2022-08-17T13:53:33","date_gmt":"2022-08-17T11:53:33","guid":{"rendered":"https:\/\/nguenkam.com\/blog\/?p=2086"},"modified":"2022-08-17T13:53:33","modified_gmt":"2022-08-17T11:53:33","slug":"user-defined-type-guards-in-typescript","status":"publish","type":"post","link":"https:\/\/nguenkam.com\/blog\/index.php\/2022\/08\/17\/user-defined-type-guards-in-typescript\/","title":{"rendered":"User-defined Type Guards in Typescript"},"content":{"rendered":"\n<p>Type Guards are one of the key features of type-safe code.<\/p>\n\n\n\n<p>The\u00a0<a rel=\"noreferrer noopener\" href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\" target=\"_blank\">TypeScript Handbook<\/a>\u00a0describes type guards as:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p><em>Some expression that performs a runtime check that guarantees the type in some scope<\/em><\/p><\/blockquote>\n\n\n\n<p>The most important part of this description is that type guards are in fact a form of\u00a0<em><span class=\"has-inline-color has-vivid-cyan-blue-color\">runtime check<\/span><\/em>, which means the variable is of expected type at the moment of code execution.<\/p>\n\n\n\n<p>Instead of using the<span class=\"has-inline-color has-vivid-cyan-blue-color\">\u00a0<code>any<\/code>\u00a0<\/span>keyword to force the TypeScript compiler to stop complaining about an unknown property, it is much more readable to use Type Guards. They do not disable type checks in application code, and thus make it less error prone. Your code runs, your tests pass. The compiler is happy and so are you.<\/p>\n\n\n\n<p>TypeScript comes with built-in type guards like\u00a0<code>typeof<\/code>,\u00a0<code>instanceof<\/code>,\u00a0<code>in<\/code>\u00a0and literal type guards. They\u2019re very useful, but have limited scope in modern web development.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Using instanceof<\/h4>\n\n\n\n<p><code><span class=\"has-inline-color has-vivid-cyan-blue-color\">instanceof<\/span><\/code>\u00a0can be used to check if a variable is an instance of a given class. The right side of the\u00a0<span class=\"has-inline-color has-vivid-cyan-blue-color\"><code>instanceof<\/code>\u00a0<\/span>operator needs to be a constructor function.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Pet { }\r\n\r\nclass Dog extends Pet {\r\n    bark() {\r\n        console.log('woof');\r\n    }\r\n}\r\n\r\nclass Cat extends Pet {\r\n    purr() { \r\n        console.log('meow');\r\n    }\r\n}\r\n\r\nfunction example(foo: any) {\r\n    if (foo instanceof Dog) {\r\n        foo.bark(); \/\/ OK, foo is type Dog in this block\r\n\/\/      foo.purr(); \/\/ Error! Property 'purr' does not exist on type 'Dog'.\r\n} \r\n    \r\n    if (foo instanceof Cat) {\r\n        foo.purr(); \/\/ OK, foo is type Cat in this block\r\n\/\/      foo.bark(); \/\/ Error! Property 'bark' does not exist on type 'Cat'.\r\n    }\r\n}\r\n\r\nexample(new Dog());\r\nexample(new Cat());<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Using typeof<\/h4>\n\n\n\n<p><code><span class=\"has-inline-color has-vivid-cyan-blue-color\">typeof<\/span><\/code>\u00a0is used when you need to distinguish between types\u00a0<code><span class=\"has-inline-color has-luminous-vivid-amber-color\">number<\/span><\/code>,\u00a0<code><span class=\"has-inline-color has-luminous-vivid-amber-color\">string<\/span><\/code>,\u00a0<span class=\"has-inline-color has-luminous-vivid-amber-color\"><code>boolean<\/code>,<\/span>\u00a0<code><span class=\"has-inline-color has-luminous-vivid-amber-color\">bigint<\/span><\/code>,\u00a0<code><span class=\"has-inline-color has-luminous-vivid-amber-color\">object<\/span><\/code>,\u00a0<code><span class=\"has-inline-color has-luminous-vivid-amber-color\">function<\/span><\/code>,\u00a0<code><span class=\"has-inline-color has-luminous-vivid-amber-color\">symbol<\/span><\/code>, and\u00a0<code><span class=\"has-inline-color has-luminous-vivid-amber-color\">undefined<\/span><\/code> .<\/p>\n\n\n\n<p>When trying to use other string constants (like <em><strong>customized Type<\/strong><\/em>) , the\u00a0<code>typeof<\/code>\u00a0operator will not error, but won\u2019t work as expected either, which leads to bugs that are hard to track. These kinds of expressions will not be recognized as type guards.<\/p>\n\n\n\n<p>Unlike\u00a0<code><span class=\"has-inline-color has-vivid-cyan-blue-color\">instanceof<\/span><\/code>,\u00a0<code><span class=\"has-inline-color has-vivid-cyan-blue-color\"><strong>typeof<\/strong><\/span><\/code>\u00a0will work with a variable of any type. In the example below,\u00a0<code>foo<\/code>\u00a0could be typed as<strong>\u00a0<code>number<\/code><\/strong><code> <strong>| string<\/strong><\/code>\u00a0without issue.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function example(foo: any) {\r\n    if (typeof foo === 'number') {\r\n        console.log(foo + 100); \/\/ foo is type number\r\n    }\r\n    if (typeof foo === 'string') {\r\n        console.log('not a number: '+ foo); \/\/ foo is type string\r\n    }\r\n}\r\nexample(23);\r\nexample('foo');<\/code><\/pre>\n\n\n\n<p>This prints:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>123\r\nnot a number: foo<\/code><\/pre>\n\n\n\n<p>The tricky part is that\u00a0<code><strong>typeof<\/strong><\/code>\u00a0only performs shallow type-checking. It can determine if a variable is a generic object, but cannot tell the shape of the object. This will not work:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (typeof foo === 'Dog')  \/\/ foo is maybe an Object, but it can not determine if it is a      \n                           \/\/ type 'Dog' . to do that, we have to use the <em><strong>instanceof<\/strong><\/em> Method<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Using in<\/h4>\n\n\n\n<p>The\u00a0<code><span class=\"has-inline-color has-vivid-cyan-blue-color\">in<\/span><\/code>\u00a0operator does a safe check for the existence of a property on an object of\u00a0<code>union<\/code>\u00a0type. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function example(foo: Dog | Cat) {\r\n  if ('purr' in foo) {\r\n    foo.purr();  \/\/ foo is narrowed Cat\r\n  }\r\n  else {\r\n    foo.bark(); \/\/ foo is narrowed to Dog\r\n  }\r\n}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Using Literal Type Guards<\/h4>\n\n\n\n<p>Additionally, you can use\u00a0<code>===<\/code>,\u00a0<code>==<\/code>,\u00a0<code>!==<\/code>\u00a0and\u00a0<code>!=<\/code>\u00a0to distinguish between literal values, and thus form simple type guards, like in the following example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>type ConfirmationState = 'yes' | 'no' | 'N\/A';\r\n\r\nfunction confirmationHandler(state: ConfirmationState) {\r\n  if (state == 'yes') {\r\n    console.log('User selected yes');\r\n  } else if (state == 'no') {\r\n    console.log('User selected no');\r\n  } else {\r\n    console.log('User has not made a selection yet');\r\n  }\r\n}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4><span class=\"has-inline-color has-vivid-red-color\">User Defined Type Guards<\/span><\/h4>\n\n\n\n<p>In real-life projects, you might want, to declare your <em><strong>own type guards<\/strong><\/em> with custom logic to help the TypeScript compiler determine the type. You will need to declare a function that serves as type guard using any logic you\u2019d like.<\/p>\n\n\n\n<p id=\"c88f\">This function\u2014\u00a0<em>User Defined Type Guard function \u2014\u00a0<\/em>is a function that returns a\u00a0<em>type predicate\u00a0<\/em>in the form of\u00a0<code>event is MouseEvent<\/code>\u00a0in place of a return type:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function handle(event: any): event is MouseEvent {\r\n    \/\/ body that returns boolean\r\n}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">If the function returns\u00a0<code>true<\/code>, TypeScript will narrow the type to\u00a0<code>MouseEvent<\/code>\u00a0in any block guarded by a call to the function. In other words, the type will be more specific.\u00a0<code>event is MouseEvent<\/code>\u00a0ensures the compiler that the\u00a0<code>event<\/code>\u00a0passed into the Type Guard is in fact a\u00a0<code>MouseEvent<\/code>. For example:\n<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>function isDog(test: any): test is Dog {\r\n  return test instanceof Dog;\r\n}\r\n\r\nfunction example(foo: any) {\r\n    if (isDog(foo)) {\r\n        \/\/ foo is type as a Dog in this block\r\n        foo.bark();\r\n    } else {\r\n        \/\/ foo is type any in this block\r\n        console.log(\"don't know what this is! &#91;\" + foo + \"]\");\r\n    }\r\n}\r\n\r\nexample(new Dog());\r\nexample(new Cat());<\/code><\/pre>\n\n\n\n<p>This prints:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>woof\r\ndon\u2019t know what this is! &#91;&#91;object Object]]<\/code><\/pre>\n\n\n\n<p><strong>PS:<\/strong> <em><span class=\"has-inline-color has-vivid-cyan-blue-color\">Type guard functions don\u2019t have to use\u00a0<code>typeof<\/code>\u00a0or\u00a0<code>instanceof<\/code>, they can use more complicated logic. For example<\/span><\/em>, \u00a0this code checks function\u00b4s parameter to determine whether it\u2019s\u00a0<code>customType 'GeneralType'<\/code> : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>type GeneralType = 'type1' | 'type2';\r\n\nfunction someFunction(arg1:any) {\r\n  if (isCustomType(arg1)) {\r\n    \/\/ Do something\r\n  }\r\n  \/\/ Continue function\r\n}\r\n\r\nfunction isCustomType(arg: any): arg is GeneralType {\r\n  return &#91;'type1', 'type2'].some(element => element === arg);\r\n}<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Being one of the most underestimated features of TypeScript, Type guards are incredibly useful for narrowing types and satisfying the compiler. They help ensure type-safety and promote code that is easier to maintain.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Type Guards are one of the key features of type-safe code. The\u00a0TypeScript Handbook\u00a0describes type guards as: Some expression that performs a runtime check that guarantees the type in some scope The most important part of this description is that type guards are in fact a form of\u00a0runtime check, which means the variable is of expected [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1993,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[83],"tags":[577,578,576,579],"_links":{"self":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/2086"}],"collection":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=2086"}],"version-history":[{"count":1,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/2086\/revisions"}],"predecessor-version":[{"id":2087,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/2086\/revisions\/2087"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/1993"}],"wp:attachment":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=2086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=2086"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=2086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}