{"id":1074,"date":"2021-08-18T21:48:48","date_gmt":"2021-08-18T13:48:48","guid":{"rendered":"https:\/\/sora.sound.moe\/?p=1074"},"modified":"2021-08-18T21:48:48","modified_gmt":"2021-08-18T13:48:48","slug":"how-to-write-typescript-definition-files","status":"publish","type":"post","link":"https:\/\/sora.sound.moe\/?p=1074","title":{"rendered":"How to write TypeScript definition files"},"content":{"rendered":"\n<!--more-->\n\n\n\n<p>Recently, I started writing some TypeScript definition files from my team. These definition files addressed the problem that some old common packages writing in JavaScript are missing TypeScript support. Meanwhile, our team is migrating projects from JavaScript to TypeScript incrementally.<\/p>\n\n\n\n<p>TypeScript definition file (.d.ts) is like an add-on for JavaScript files that can provide TypeScript definitions without changing the original file. We call declarations that don\u2019t define an implementation \u201cambient\u201d<sup>[1]<\/sup>. To write an ambient module from an existing module, use <code>declare modul<\/code>e keyword. For example.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>declare module \"lodash\" {\n    export function uniq&lt;T&gt;(data: T&#91;]) =&gt; T&#91;];\n}<\/code><\/pre>\n\n\n\n<p>When writing an ambient module, there are serveral points you need to take care of.<\/p>\n\n\n\n<ul><li>Test it in different IDEs.<\/li><\/ul>\n\n\n\n<p>It&#8217;s strange but I found VSCode and WebStorm sometimes have different behaviors treating the same definition file. Test from both IDEs to make sure your definition works.<\/p>\n\n\n\n<ul><li>Don&#8217;t use <code>import<\/code> outside the module<\/li><\/ul>\n\n\n\n<p>You can&#8217;t use <code>import<\/code> outside of the <code>declare module<\/code> block. This will cause TypeScript treating the file as a normal module rather than an ambient module<sup>[2]<\/sup>. The right way to reference types from other modules is<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>declare module \"lodash\" {\n    import { Request, Response } from \"express\";\n    export interface CustomRequest extends Request {\n        \/\/ ....\n    }\n}<\/code><\/pre>\n\n\n\n<ul><li>Add some <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/2\/generics.html\">generics<\/a> for uncertain return values<\/li><\/ul>\n\n\n\n<p>When you are adding type definitions for a method that do not have a certain data structure for return values, add a generic parameter to let user to control it. For example.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>export const getQueryFormURL&lt;T = Record&lt;string, string&gt;&gt; = (url: string) =&gt; T;<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2>References<\/h2>\n\n\n\n<ol><li>https:\/\/www.typescriptlang.org\/docs\/handbook\/modules.html#working-with-other-javascript-libraries<\/li><li>https:\/\/stackoverflow.com\/questions\/39040108\/import-class-in-definition-file-d-ts<\/li><\/ol>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"twentyseventeen-featured-image":false,"twentyseventeen-thumbnail-avatar":false},"uagb_author_info":{"display_name":"Sora","author_link":"https:\/\/sora.sound.moe\/?author=1"},"uagb_comment_info":0,"uagb_excerpt":null,"_links":{"self":[{"href":"https:\/\/sora.sound.moe\/index.php?rest_route=\/wp\/v2\/posts\/1074"}],"collection":[{"href":"https:\/\/sora.sound.moe\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sora.sound.moe\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sora.sound.moe\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sora.sound.moe\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1074"}],"version-history":[{"count":0,"href":"https:\/\/sora.sound.moe\/index.php?rest_route=\/wp\/v2\/posts\/1074\/revisions"}],"wp:attachment":[{"href":"https:\/\/sora.sound.moe\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1074"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sora.sound.moe\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1074"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sora.sound.moe\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1074"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}