{"id":1122,"date":"2023-03-23T14:15:30","date_gmt":"2023-03-23T13:15:30","guid":{"rendered":"https:\/\/greladesign.co\/blog\/?p=1122"},"modified":"2023-03-24T12:45:41","modified_gmt":"2023-03-24T11:45:41","slug":"typescript-add-typing-to-the-lodash-keys-helper","status":"publish","type":"post","link":"https:\/\/greladesign.co\/blog\/2023\/03\/23\/typescript-add-typing-to-the-lodash-keys-helper\/","title":{"rendered":"TypeScript: Add typing to the lodash keys helper"},"content":{"rendered":"\n<p>With lodash (Version 4.17.21 at time of writing) and @types\/lodash (Version 4.14.191 at time of writing) using the <code>keys<\/code> helper will lose the type information of the given object.<\/p>\n\n\n\n<!--more-->\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"TypeScript\" data-shcb-language-slug=\"typescript\"><span><code class=\"hljs language-typescript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ test object upon which we will call keys<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">type<\/span> TObject = {\n<\/span><\/span><span class='shcb-loc'><span>  fieldNum: <span class=\"hljs-built_in\">number<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  fieldStr: <span class=\"hljs-built_in\">string<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  fieldBln: <span class=\"hljs-built_in\">boolean<\/span>;\n<\/span><\/span><span class='shcb-loc'><span>  fieldArr: <span class=\"hljs-built_in\">string<\/span>&#91;];\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> o: TObject = {\n<\/span><\/span><span class='shcb-loc'><span>  fieldNum: <span class=\"hljs-number\">42<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  fieldStr: <span class=\"hljs-string\">'greladesign'<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  fieldBln: <span class=\"hljs-literal\">true<\/span>,\n<\/span><\/span><span class='shcb-loc'><span>  fieldArr: &#91;<span class=\"hljs-string\">\"a\"<\/span>, <span class=\"hljs-string\">\"b\"<\/span>, <span class=\"hljs-string\">\"c\"<\/span>]\n<\/span><\/span><span class='shcb-loc'><span>};\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">const<\/span> keysOfObject = keys(o); <span class=\"hljs-comment\">\/\/ tooltip will show: const keysOfObject: string&#91;]<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/<\/span>\n<\/span><\/span><span class='shcb-loc'><span>keysOfObject.forEach((field <span class=\"hljs-comment\">\/* :string *\/<\/span>): <span class=\"hljs-function\"><span class=\"hljs-params\">void<\/span> =&gt;<\/span> {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ You have lost the information about keys of the object, <\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-comment\">\/\/ TypeScript will no longer be able to verify field for you<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">if<\/span> (field === <span class=\"hljs-string\">'fieldBoolean'<\/span>) { <span class=\"hljs-comment\">\/\/ TS will accept this incorrect field name<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">const<\/span> flag = o&#91;field]; <span class=\"hljs-comment\">\/\/ TS will use any here<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>})\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">TypeScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">typescript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As you can see this is not very useful, luckily it is easy to resolve<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"TypeScript\" data-shcb-language-slug=\"typescript\"><span><code class=\"hljs language-typescript shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-comment\">\/\/ add following to your typings e.g. lodash-override.d.ts<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">export<\/span> {};\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-keyword\">declare<\/span> <span class=\"hljs-keyword\">module<\/span> 'lodash' {\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-keyword\">interface<\/span> LoDashStatic {\n<\/span><\/span><span class='shcb-loc'><span>    keys&lt;O&gt;(object?: O): (keyof O)&#91;]; \n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">TypeScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">typescript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>With this module augmentation the TS will now properly identify misspelled field name and will give a nice warning: <code>\"This condition will always return 'false' since the types 'keyof TObject' and '\"fieldBoolean\"'<\/code> have no overlap.&#8221; or <code>\"This comparison appears to be unintentional because the types 'keyof TObject' and '\"fieldBoolean\"' have no overlap.\"<\/code>.<\/p>\n\n\n\n<h3>Source code<\/h3>\n\n\n\n<ul class=\"wp-container-3 wp-block-social-links has-large-icon-size is-style-pill-shape\"><li class=\"wp-social-link wp-social-link-github wp-block-social-link\"><a href=\"https:\/\/github.com\/LukaszGrela\/blog-code-typescript-add-typing-to-the-lodash\" aria-label=\"Source code\" rel=\"noopener nofollow\" target=\"_blank\" class=\"wp-block-social-link-anchor\"> <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" role=\"img\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z\"><\/path><\/svg><\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>With lodash (Version 4.17.21 at time of writing) and @types\/lodash (Version 4.14.191 at time of writing) using the keys helper will lose the type information of the given object.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":""},"categories":[356],"tags":[357],"_links":{"self":[{"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/posts\/1122"}],"collection":[{"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/comments?post=1122"}],"version-history":[{"count":10,"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/posts\/1122\/revisions"}],"predecessor-version":[{"id":1146,"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/posts\/1122\/revisions\/1146"}],"wp:attachment":[{"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/media?parent=1122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/categories?post=1122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/greladesign.co\/blog\/wp-json\/wp\/v2\/tags?post=1122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}