{"id":2246,"date":"2019-06-24T08:29:25","date_gmt":"2019-06-24T16:29:25","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=2246"},"modified":"2019-06-24T08:29:25","modified_gmt":"2019-06-24T16:29:25","slug":"how-to-upgrade-to-typescript-without-anybody-noticing-part-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/how-to-upgrade-to-typescript-without-anybody-noticing-part-2\/","title":{"rendered":"How to Upgrade to TypeScript without anybody noticing, Part 2"},"content":{"rendered":"<p>This guide will show you how to fix Typescript compile errors in Javascript project that recently added Typescript support via a\u00a0<code>tsconfig.json<\/code>. It assumes that the\u00a0<code>tsconfig.json<\/code>\u00a0is configured according to\u00a0<a href=\"https:\/\/devblogs.microsoft.com\/typescript\/how-to-upgrade-to-typescript-without-anybody-noticing-part-1\/\">the description in part 1 of this post<\/a>, and that you also installed types for some of your dependencies from the\u00a0<code>@types\/*<\/code>\u00a0namespace. This guide is more of a list of tasks that you can pick and choose from, depending on what you want to fix first. Here are the tasks:<\/p>\n<ol>\n<li>Add missing types in dependencies.<\/li>\n<li>Fix references to types in dependencies.<\/li>\n<li>Add missing types in your own code.<\/li>\n<li>Work around missing types in dependencies.<\/li>\n<li>Fix errors in existing types.<\/li>\n<li>Add type annotations to everything else.<\/li>\n<\/ol>\n<p>This guide does\u00a0<em>not<\/em>\u00a0teach you how to write type definitions.\u00a0<a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/declaration-files\/introduction.html\" rel=\"nofollow\">The Declaration section of the Typescript handbook<\/a>\u00a0is the best place to learn about that. Here, you&#8217;ll just see types presented without a lot of explanation.<\/p>\n<h2><a id=\"user-content-add-missing-types-in-dependencies\" class=\"anchor\" href=\"https:\/\/github.com\/sandersn\/manual\/blob\/master\/How-to-upgrade-to-Typescript-without-anybody-noticing-part-2.md#add-missing-types-in-dependencies\" aria-hidden=\"true\"><\/a>Add missing types in dependencies<\/h2>\n<p>Let&#8217;s start with\u00a0<code>@types\/shelljs<\/code>. In Makefile.js, I see a few errors. The first is that the module\u00a0<code>require('shelljs\/make')<\/code>\u00a0isn&#8217;t found. The second group of errors is that the names &#8216;find&#8217;, &#8216;echo&#8217; and a few others aren&#8217;t found.<\/p>\n<p>These errors are related. It turns out that\u00a0<code>@types\/shelljs<\/code>\u00a0doesn&#8217;t even include\u00a0<code>shelljs\/make.d.ts<\/code>\u00a0right now. It&#8217;s completely missing. If you\u00a0<a href=\"https:\/\/github.com\/shelljs\/shelljs\/blob\/master\/make.js\">look at the source<\/a>,\u00a0<code>shelljs\/make.js<\/code>\u00a0does two things:<\/p>\n<ol>\n<li>Add the contents of the parent shelljs to the global scope.<\/li>\n<li>Add a global object named &#8216;target&#8217; that allows you to add make targets.<\/li>\n<\/ol>\n<p>Let&#8217;s say you want to add make to Definitely Typed so that it is available in\u00a0<code>@types\/shelljs<\/code>. Your first step is to create\u00a0<code>make.d.ts<\/code>\u00a0inside\u00a0<code>node_modules\/@types\/shelljs\/<\/code>. This is the wrong location \u2014 it&#8217;s inside your own\u00a0<code>node_modules<\/code> folder \u2014 but it makes development super easy to test that you&#8217;re actually adding the missing stuff. You can create a proper PR after everything is working.<\/p>\n<p>Start with this:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">import<\/span> <span class=\"pl-c1\">*<\/span> <span style=\"color: #0000ff;\">as<\/span> <span class=\"pl-smi\">shelljs<\/span> <span style=\"color: #0000ff;\">from<\/span> <span style=\"color:#A31515;\"><span class=\"pl-pds\">'<\/span>.\/<span class=\"pl-pds\">'<\/span><\/span>;\r\n<span style=\"color: #0000ff;\">declare<\/span> <span class=\"pl-c1\">global<\/span> {\r\n  <span style=\"color: #0000ff;\">const<\/span> cd<span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #0000ff;\">typeof<\/span> <span style=\"color: #267F99;\">shelljs<\/span>.<span style=\"color: #267F99;\">cd<\/span>;\r\n  <span style=\"color: #0000ff;\">const<\/span> pwd<span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #0000ff;\">typeof<\/span> <span style=\"color: #267F99;\">shelljs<\/span>.<span style=\"color: #267F99;\">pwd<\/span>;\r\n  <span style=\"color: #148A14;\">\/\/ ... all the rest ...<\/span>\r\n}<\/pre>\n<\/div>\n<p>This copies all of shelljs&#8217; contents into the global namespace. Then add the type for\u00a0<code>target<\/code>\u00a0to the globals as well:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">const<\/span> target<span style=\"color: #0000ff;\">:<\/span> {\r\n  all<span style=\"color: #0000ff;\">?<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Target<\/span>;\r\n  [<span class=\"pl-v\">s<\/span><span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">string<\/span>]<span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Target<\/span>;\r\n}\r\n<span style=\"color: #0000ff;\">interface<\/span> <span style=\"color: #267F99;\">Target<\/span> {\r\n  (<span style=\"color: #0000ff;\">...<\/span><span class=\"pl-v\">args<\/span><span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">any<\/span>[])<span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">void<\/span>;\r\n  result<span style=\"color: #0000ff;\">?<\/span><span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">any<\/span>;\r\n  done<span style=\"color: #0000ff;\">?<\/span><span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">boolean<\/span>;\r\n}<\/pre>\n<\/div>\n<p>This exposes a couple more errors. See the section on fixing errors in existing types for how to fix those.<\/p>\n<p>Now we want to publish this to Definitely Typed:<\/p>\n<ol>\n<li>Fork\u00a0<a href=\"https:\/\/github.com\/DefinitelyTyped\/DefinitelyTyped\">DefinitelyTyped<\/a>\u00a0on github.<\/li>\n<li><code>git clone https:\/\/github.com\/your-name-here\/DefinitelyTyped<\/code><\/li>\n<li><code>cp node_modules\/@types\/shelljs\/make.d.ts ~\/DefinitelyTyped\/types\/shelljs\/<\/code><\/li>\n<li><code>git checkout -b add-shelljs-make<\/code><\/li>\n<li>Commit the change and push it to your github fork.<\/li>\n<li>Create a PR for the change.<\/li>\n<\/ol>\n<p>If there are lint problems, the CI run on Definitely Typed will catch them.<\/p>\n<p>For more detail on writing definitions for Definitely Typed,\u00a0<a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/declaration-files\/introduction.html\" rel=\"nofollow\">see the Declaration section of the Typescript handbook<\/a>.<\/p>\n<h2><a id=\"user-content-fix-references-to-types-in-dependencies\" class=\"anchor\" href=\"https:\/\/github.com\/sandersn\/manual\/blob\/master\/How-to-upgrade-to-Typescript-without-anybody-noticing-part-2.md#fix-references-to-types-in-dependencies\" aria-hidden=\"true\"><\/a>Fix references to types in dependencies<\/h2>\n<p>typescript-eslint-parser actually has quite a bit of type information in its source already. It just happens to be written in JSDoc, and it&#8217;s often almost, but not quite, what Typescript expects to see. For example, in\u00a0<code>analyze-scope.js<\/code>,\u00a0<code>visitPattern<\/code>\u00a0has an interesting mix of types:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * Override to use PatternVisitor we overrode.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Identifier}<\/span> <span class=\"pl-smi\">node<\/span> The Identifier node to visit.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Object}<\/span> <span class=\"pl-smi\">[options]<\/span> The flag to visit right-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Function}<\/span> <span class=\"pl-smi\">callback<\/span> The callback function for left-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@returns<\/span> <span style=\"color: #267F99;\">{void}<\/span><\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span>\r\n<span style=\"color: #267F99;\">visitPattern<\/span>(<span class=\"pl-smi\">node<\/span>, <span class=\"pl-smi\">options<\/span>, <span class=\"pl-smi\">callback<\/span>) {\r\n    <span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">!<\/span>node) {\r\n        <span style=\"color: #0000ff;\">return<\/span>;\r\n    }\r\n\r\n    <span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">typeof<\/span> options <span style=\"color: #0000ff;\">===<\/span> <span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>function<span class=\"pl-pds\">\"<\/span><\/span>) {\r\n        callback <span style=\"color: #0000ff;\">=<\/span> options;\r\n        options <span style=\"color: #0000ff;\">=<\/span> { processRightHandNodes<span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">false<\/span> };\r\n    }\r\n\r\n    <span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-c1\">visitor<\/span> <span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">PatternVisitor<\/span>(<span class=\"pl-c1\">this<\/span>.<span class=\"pl-c1\">options<\/span>, node, callback);\r\n    <span class=\"pl-smi\">visitor<\/span>.<span style=\"color: #267F99;\">visit<\/span>(node);\r\n\r\n    <span style=\"color: #0000ff;\">if<\/span> (<span class=\"pl-smi\">options<\/span>.<span class=\"pl-smi\">processRightHandNodes<\/span>) {\r\n        <span class=\"pl-smi\">visitor<\/span>.<span class=\"pl-smi\">rightHandNodes<\/span>.<span class=\"pl-c1\">forEach<\/span>(<span class=\"pl-c1\">this<\/span>.<span class=\"pl-smi\">visit<\/span>, <span class=\"pl-c1\">this<\/span>);\r\n    }\r\n}<\/pre>\n<\/div>\n<p>In the JSDoc at the start, there&#8217;s an error on\u00a0<code>Identifier<\/code>. (<code>Object<\/code>\u00a0and\u00a0<code>Function<\/code>\u00a0are fine, although you could write more specific types.) That&#8217;s weird, because those types\u00a0<em>do<\/em>\u00a0exist in\u00a0<code>estree<\/code>. The problem is that they&#8217;re not imported. Typescript lets you import types directly, like this:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">import<\/span> { <span class=\"pl-smi\">Identifier<\/span>, <span class=\"pl-smi\">ClassDeclaration<\/span> } <span style=\"color: #0000ff;\">from<\/span> <span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>estree<span class=\"pl-pds\">\"<\/span><\/span>;<\/pre>\n<\/div>\n<p>But this doesn&#8217;t work in Javascript because those are types, not values. Types don&#8217;t exist at runtime, so the import will fail at runtime when\u00a0<code>Identifier<\/code>\u00a0is not found. Instead, you need to use an\u00a0<em>import type<\/em>. An import type is just like a dynamic import, except that it&#8217;s used as a type. So, just like you could write:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-c1\">estree<\/span> <span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #0000ff;\">import<\/span>(<span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>estree);<\/span><\/pre>\n<\/div>\n<p>to dynamically import the\u00a0<code>Identifier<\/code>\u00a0type from\u00a0<code>estree<\/code>, you can write:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/** <span style=\"color: #0000ff;\">@type<\/span> <span style=\"color: #267F99;\">{import(\"estree\").Identifier <\/span>*\/<\/span>\r\n<span style=\"color: #0000ff;\">var<\/span> id <span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #0000ff;\">...<\/span><\/pre>\n<\/div>\n<p>to import the type\u00a0<code>Identifier<\/code>\u00a0without an import statement. And, because it&#8217;s inconvenient to repeat\u00a0<code>import<\/code>\u00a0all over the place, you usually want to write a\u00a0<code>typedef<\/code>\u00a0at the top of the file:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/** <span style=\"color: #0000ff;\">@typedef<\/span> <span style=\"color: #267F99;\">{import(\"estree\").Identifier}<\/span> <span style=\"color: #267F99;\">Identifier<\/span> *\/<\/span><\/pre>\n<\/div>\n<p>With that alias in place, references to\u00a0<code>Identifier<\/code>\u00a0resolve to the type from estree:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Identifier}<\/span> <span class=\"pl-smi\">node<\/span> now has the correct type<\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span><\/pre>\n<\/div>\n<p><a href=\"https:\/\/github.com\/eslint\/typescript-eslint-parser\/commit\/f02b62d70cbabeebcfb6cd75dfaa2d94d0679fd5\">Here&#8217;s the commit.<\/a><\/p>\n<h2><a id=\"user-content-add-missing-types-in-your-own-code\" class=\"anchor\" href=\"https:\/\/github.com\/sandersn\/manual\/blob\/master\/How-to-upgrade-to-Typescript-without-anybody-noticing-part-2.md#add-missing-types-in-your-own-code\" aria-hidden=\"true\"><\/a>Add missing types in your own code<\/h2>\n<p>Fixing these types still leaves a lot of undefined types in\u00a0<code>analyze-scope.js<\/code>. The types\u00a0<em>look<\/em>\u00a0like\u00a0<code>estree<\/code>\u00a0types, but they&#8217;re prefixed with TS-, like\u00a0<code>TSTypeAnnotation<\/code>\u00a0and\u00a0<code>TSTypeQuery<\/code>. Here&#8217;s where\u00a0<code>TSTypeQuery<\/code>\u00a0is used:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * Create reference objects for the object part. (This is `obj.prop`)<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{TSTypeQuery}<\/span> <span class=\"pl-smi\">node<\/span> The TSTypeQuery node to visit.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@returns<\/span> <span style=\"color: #267F99;\">{void}<\/span><\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span>\r\n<span style=\"color: #267F99;\">TSQualifiedName<\/span>(<span class=\"pl-smi\">node<\/span>) {\r\n    <span class=\"pl-c1\">this<\/span>.<span style=\"color: #267F99;\">visit<\/span>(<span class=\"pl-smi\">node<\/span>.<span class=\"pl-c1\">left<\/span>);\r\n}<\/pre>\n<\/div>\n<p>It turns out that these types are specific to typescript-eslint-query. So you&#8217;ll have to define them yourself. To start, define the typedefs you need as\u00a0<code>any<\/code>. This gets rid of the errors at the cost of accuracy:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/** <span style=\"color: #0000ff;\">@typedef<\/span> <span style=\"color: #267F99;\">{any}<\/span> <span style=\"color: #267F99;\">TSTypeQuery<\/span> *\/<\/span>\r\n<span style=\"color: #148A14;\">\/\/ lots more typedefs ...<\/span><\/pre>\n<\/div>\n<p>At this point, you have two options: bottom-up discovery of how the types are used, or top-down documentation of what the types should be.<\/p>\n<p>Bottom-up discovery, which is you&#8217;ll see below, has the advantage that you will end up with zero compile errors afterward. But it doesn&#8217;t scale well; when a type is used throughout a large project, the chances of it being\u00a0<em>mis<\/em>used are pretty high.<\/p>\n<p>Top-down documentation works well for large projects that already have some kind of documentation. You just need to know how to translate documentation into Typescript types;\u00a0<a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/declaration-files\/introduction.html\" rel=\"nofollow\">the Declaration section of the Typescript handbook<\/a>\u00a0is a good starting point for this. You will sometimes have to change your code to fit the type using the top-down approach as well. Most of the time that&#8217;s because the code is questionable and needs to be changed, but sometimes the code is fine and the compiler gets confused and has to be placated.<\/p>\n<p>Let&#8217;s use bottom-up discovery in this case because it looks like top-down documentation would involve copying the entire Typescript node API into\u00a0<code>analyze-scope.js<\/code>. To do this, change the typedefs one by one to &#8216;unknown&#8217;, and look for errors that pop up. For example:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/** <span style=\"color: #0000ff;\">@typedef<\/span> <span style=\"color: #267F99;\">{unknown}<\/span> <span style=\"color: #267F99;\">TSTypeQuery<\/span> *\/<\/span><\/pre>\n<\/div>\n<p>Now there&#8217;s an error is on the usage of\u00a0<code>TSTypeQuery<\/code>\u00a0in\u00a0<code>TSQualifiedName<\/code>,\u00a0<code>node.left<\/code>:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * Create reference objects for the object part. (This is `obj.prop`)<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{TSTypeQuery}<\/span> <span class=\"pl-smi\">node<\/span> The TSTypeQuery node to visit.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@returns<\/span> <span style=\"color: #267F99;\">{void}<\/span><\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span>\r\n<span style=\"color: #267F99;\">TSQualifiedName<\/span>(<span class=\"pl-smi\">node<\/span>) {\r\n    <span class=\"pl-c1\">this<\/span>.<span style=\"color: #267F99;\">visit<\/span>(<span class=\"pl-smi\">node<\/span>.<span class=\"pl-c1\">left<\/span>);\r\n    <span style=\"color: #148A14;\">\/\/              ~~~~<\/span>\r\n    <span style=\"color: #148A14;\">\/\/ error: type 'unknown' has no property 'left'<\/span>\r\n}<\/pre>\n<\/div>\n<p>Looks like TSTypeQuery is supposed to have a\u00a0<code>left<\/code>\u00a0property, so change\u00a0<code>TSTypeQuery<\/code>\u00a0from\u00a0<code>unknown<\/code>\u00a0to\u00a0<code>{ left: unknown }<\/code>. There&#8217;s no more indication of what the type of\u00a0<code>left<\/code>\u00a0is, so leave it as\u00a0<code>unknown<\/code>:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/** <span style=\"color: #0000ff;\">@typedef<\/span> <span style=\"color: #267F99;\">{{ left: unknown }}<\/span> <span style=\"color: #267F99;\">TSTypeQuery<\/span> *\/<\/span><\/pre>\n<\/div>\n<p>As you can see, bottom-up type discovery can be a bit unsatisfying and underspecified, but it&#8217;s less disruptive to existing code.\u00a0<a href=\"https:\/\/github.com\/eslint\/typescript-eslint-parser\/commit\/57b517c5a763ee47e92aee93d0b97ed096eaeec7\">Here&#8217;s the commit.<\/a><\/p>\n<h2><a id=\"user-content-work-around-missing-types\" class=\"anchor\" href=\"https:\/\/github.com\/sandersn\/manual\/blob\/master\/How-to-upgrade-to-Typescript-without-anybody-noticing-part-2.md#work-around-missing-types\" aria-hidden=\"true\"><\/a>Work around missing types<\/h2>\n<p>Sometimes you&#8217;ll find that one of your dependencies has no\u00a0<code>@types<\/code>\u00a0package at all. You are free to define types and contribute them to\u00a0<a href=\"https:\/\/github.com\/DefinitelyTyped\/DefinitelyTyped\">Definitely Typed<\/a>, of course, but you usually need a quick way to work around missing dependencies. The easiest way is to add your own typings file to hold workarounds. Let&#8217;s look at\u00a0<code>visitPattern<\/code>\u00a0in\u00a0<code>analyze-scope.js<\/code> again:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * Override to use PatternVisitor we overrode.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Identifier}<\/span> <span class=\"pl-smi\">node<\/span> The Identifier node to visit.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Object}<\/span> <span class=\"pl-smi\">[options]<\/span> The flag to visit right-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Function}<\/span> <span class=\"pl-smi\">callback<\/span> The callback function for left-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@returns<\/span> <span style=\"color: #267F99;\">{void}<\/span><\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span>\r\n<span style=\"color: #267F99;\">visitPattern<\/span>(<span class=\"pl-smi\">node<\/span>, <span class=\"pl-smi\">options<\/span>, <span class=\"pl-smi\">callback<\/span>) {\r\n    <span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">!<\/span>node) {\r\n        <span style=\"color: #0000ff;\">return<\/span>;\r\n    }\r\n\r\n    <span style=\"color: #0000ff;\">if<\/span> (<span style=\"color: #0000ff;\">typeof<\/span> options <span style=\"color: #0000ff;\">===<\/span> <span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>function<span class=\"pl-pds\">\"<\/span><\/span>) {\r\n        callback <span style=\"color: #0000ff;\">=<\/span> options;\r\n        options <span style=\"color: #0000ff;\">=<\/span> { processRightHandNodes<span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">false<\/span> };\r\n    }\r\n\r\n    <span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-c1\">visitor<\/span> <span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">PatternVisitor<\/span>(<span class=\"pl-c1\">this<\/span>.<span class=\"pl-c1\">options<\/span>, node, callback);\r\n    <span class=\"pl-smi\">visitor<\/span>.<span style=\"color: #267F99;\">visit<\/span>(node);\r\n\r\n    <span style=\"color: #0000ff;\">if<\/span> (<span class=\"pl-smi\">options<\/span>.<span class=\"pl-smi\">processRightHandNodes<\/span>) {\r\n        <span class=\"pl-smi\">visitor<\/span>.<span class=\"pl-smi\">rightHandNodes<\/span>.<span class=\"pl-c1\">forEach<\/span>(<span class=\"pl-c1\">this<\/span>.<span class=\"pl-smi\">visit<\/span>, <span class=\"pl-c1\">this<\/span>);\r\n    }\r\n}<\/pre>\n<\/div>\n<p>Now there is an error on<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-c1\">visitor<\/span> <span style=\"color: #0000ff;\">=<\/span> <span style=\"color: #0000ff;\">new<\/span> <span style=\"color: #267F99;\">PatternVisitor<\/span>(<span class=\"pl-c1\">this<\/span>.<span class=\"pl-c1\">options<\/span>, node, callback)\r\n                <span style=\"color: #0000ff;\">~~~~~~~~~~~~~~~~~~<\/span>\r\n                Expected <span class=\"pl-c1\">0<\/span> <span class=\"pl-c1\">arguments<\/span>, but got <span class=\"pl-c1\">3.<\/span><\/pre>\n<\/div>\n<p>But if you look at\u00a0<a href=\"https:\/\/github.com\/sandersn\/typescript-eslint-parser\/blob\/master\/analyze-scope.js#L38\"><code>PatternVisitor<\/code>\u00a0in the same file<\/a>, it doesn&#8217;t even\u00a0<em>have<\/em>\u00a0a constructor. But it does extend <code>OriginalPatternVisitor<\/code>:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">const<\/span> <span class=\"pl-c1\">OriginalPatternVisitor<\/span> <span style=\"color: #0000ff;\">=<\/span> <span class=\"pl-c1\">require<\/span>(<span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>eslint-scope\/lib\/pattern-visitor<span class=\"pl-pds\">\"<\/span><\/span>);\r\n<span style=\"color: #148A14;\">\/\/ much later in the code...<\/span>\r\n<span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">PatternVisitor<\/span> <span style=\"color: #0000ff;\">extends<\/span> <span class=\"pl-e\">OriginalPatternVisitor<\/span> {\r\n    <span style=\"color: #148A14;\">\/\/ more code below ...<\/span>\r\n}<\/pre>\n<\/div>\n<p>Probably\u00a0<code>OriginalPatternVisitor<\/code>\u00a0has a 3-parameter constructor which\u00a0<code>PatternVisitor<\/code>\u00a0inherits. Unfortunately,\u00a0<code>eslint-scope<\/code>\u00a0doesn&#8217;t export\u00a0<code>lib\/pattern-visitor<\/code>, so\u00a0<code>PatternVisitor<\/code>\u00a0doesn&#8217;t\u00a0<em>get<\/em>\u00a0the 3-parameter constructor. It ends up with a default 0-parameter constructor.<\/p>\n<p>As described in &#8220;Add missing types in dependencies&#8221;, you could add\u00a0<code>OriginalPatternVisitor<\/code>\u00a0in\u00a0<code>lib\/pattern-visitor.d.ts<\/code>, just like we did for\u00a0<code>make.d.ts<\/code>\u00a0in shelljs. But when you&#8217;re just getting started, sometimes you just want to put a temporary type in place. You can add the real thing later. Here&#8217;s what you can do:<\/p>\n<ol>\n<li>Create\u00a0<code>types.d.ts<\/code>\u00a0at the root of typescript-eslint-parser.<\/li>\n<li>Add the following code:<\/li>\n<\/ol>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">declare<\/span> <span style=\"color: #0000ff;\">module<\/span> <span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>eslint\/lib\/pattern-visitor<span class=\"pl-pds\">\"<\/span><\/span> {\r\n    <span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">OriginalPatternVisitor<\/span> {\r\n        <span style=\"color: #0000ff;\">constructor<\/span>(<span class=\"pl-v\">x<\/span><span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">any<\/span>, <span class=\"pl-v\">y<\/span><span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">any<\/span>, <span class=\"pl-v\">z<\/span><span style=\"color: #0000ff;\">:<\/span> <span class=\"pl-c1\">any<\/span>) {\r\n        }\r\n    }\r\n    <span style=\"color: #0000ff;\">export<\/span> <span style=\"color: #0000ff;\">=<\/span> <span class=\"pl-smi\">OriginalPatternVisitor<\/span>;\r\n}<\/pre>\n<\/div>\n<p>This declares an &#8220;ambient module&#8221;, which is a pompous name for &#8220;fake workaround module&#8221;. It&#8217;s designed for exactly this case, though, where you are overwhelmed by the amount of work you need to do and just want a way to fake it for a while. You can even put multiple\u00a0<code>declare module<\/code>s in a single file so that all your workarounds are in one place.<\/p>\n<p>After this, you can improve the type of\u00a0<code>OriginalPatternVisitor<\/code>\u00a0in the same bottom-up or top-down way that you would improve any other types. For example, you can look at\u00a0<a href=\"https:\/\/github.com\/eslint\/eslint-scope\/blob\/master\/lib\/pattern-visitor.js#L40\"><code>pattern-visitor.js<\/code>\u00a0in eslint<\/a>\u00a0to find the names of the constructor parameters. Then, a little lower in the\u00a0<a href=\"https:\/\/github.com\/eslint\/eslint-scope\/blob\/master\/lib\/pattern-visitor.js#L66\"><code>Identifier<\/code>\u00a0method of\u00a0<code>OriginalPatternVisitor<\/code><\/a>\u00a0there is a usage of\u00a0<code>callback<\/code> that gives enough information to guess its type.<\/p>\n<p><a href=\"https:\/\/github.com\/eslint\/typescript-eslint-parser\/commit\/cd00d200049e449d395d6fe8d480c4620994f225\">Here&#8217;s what you&#8217;ll end up with<\/a>:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #0000ff;\">declare<\/span> <span style=\"color: #0000ff;\">module<\/span> <span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>eslint-scope\/lib\/pattern-visitor<span class=\"pl-pds\">\"<\/span><\/span> {\r\n    <span style=\"color: #0000ff;\">import<\/span> { <span class=\"pl-smi\">Node<\/span> } <span style=\"color: #0000ff;\">from<\/span> <span style=\"color:#A31515;\"><span class=\"pl-pds\">\"<\/span>estree<span class=\"pl-pds\">\"<\/span><\/span>;\r\n    <span style=\"color: #0000ff;\">type<\/span> <span style=\"color: #267F99;\">Options<\/span> <span style=\"color: #0000ff;\">=<\/span> <span class=\"pl-c1\">unknown<\/span>;\r\n    <span style=\"color: #0000ff;\">class<\/span> <span style=\"color: #267F99;\">OriginalPatternVisitor<\/span> {\r\n        <span style=\"color: #0000ff;\">constructor<\/span>(\r\n            <span class=\"pl-v\">options<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Options<\/span>,\r\n            <span class=\"pl-v\">rootPattern<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Node<\/span>,\r\n            <span style=\"color: #267F99;\">callback<\/span><span style=\"color: #0000ff;\">:<\/span> (<span class=\"pl-v\">pattern<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Node<\/span>, <span class=\"pl-v\">options<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Options<\/span>) <span style=\"color: #0000ff;\">=&gt;<\/span> <span class=\"pl-c1\">void<\/span>);\r\n    }\r\n    <span style=\"color: #0000ff;\">export<\/span> <span style=\"color: #0000ff;\">=<\/span> <span class=\"pl-smi\">OriginalPatternVisitor<\/span>;\r\n}<\/pre>\n<\/div>\n<h2><a id=\"user-content-fix-errors-in-existing-types\" class=\"anchor\" href=\"https:\/\/github.com\/sandersn\/manual\/blob\/master\/How-to-upgrade-to-Typescript-without-anybody-noticing-part-2.md#fix-errors-in-existing-types\" aria-hidden=\"true\"><\/a>Fix errors in existing types<\/h2>\n<p>Unfortunately, the improved type for pattern-visitor once again causes an error on\u00a0<code>new PatternVisitor<\/code>. This time, the callback&#8217;s type,\u00a0<code>Function<\/code>\u00a0isn&#8217;t specific enough to work with the specific function type of the callback:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #267F99;\">callback<\/span>: (<span class=\"pl-v\">pattern<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Node<\/span>, <span class=\"pl-v\">options<\/span><span style=\"color: #0000ff;\">:<\/span> <span style=\"color: #267F99;\">Options<\/span>) <span style=\"color: #0000ff;\">=&gt;<\/span> <span style=\"color: #0000ff;\">void<\/span><\/pre>\n<\/div>\n<p>So the existing JSDoc type annotation needs to change:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * Override to use PatternVisitor we overrode.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Identifier}<\/span> <span class=\"pl-smi\">node<\/span> The Identifier node to visit.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Object}<\/span> <span class=\"pl-smi\">[options]<\/span> The flag to visit right-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Function}<\/span> <span class=\"pl-smi\">callback<\/span> The callback function for left-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@returns<\/span> <span style=\"color: #267F99;\">{void}<\/span><\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span>\r\n<span style=\"color: #267F99;\">visitPattern<\/span>(<span class=\"pl-smi\">node<\/span>, <span class=\"pl-smi\">options<\/span>, <span class=\"pl-smi\">callback<\/span>) {<\/pre>\n<\/div>\n<p>The right fix is to change the type\u00a0<code>Function<\/code>\u00a0to the more precise\u00a0<code>(pattern: Node, options: Options) =&gt; void<\/code>:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\" style=\"background-color: #f0f0f0;padding: 10px;border-radius: 10px;\"><span style=\"color: #148A14;\">\/**<\/span>\r\n<span style=\"color: #148A14;\"> * Override to use PatternVisitor we overrode.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Identifier}<\/span> <span class=\"pl-smi\">node<\/span> The Identifier node to visit.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{Object}<\/span> <span class=\"pl-smi\">[options]<\/span> The flag to visit right-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@param<\/span> <span style=\"color: #267F99;\">{(pattern: Node, options: import(\"eslint-scope\/lib\/pattern-visitor\").Options) =&gt; void}<\/span> <span class=\"pl-smi\">callback<\/span> The callback function for left-hand side nodes.<\/span>\r\n<span style=\"color: #148A14;\"> * <span style=\"color: #0000ff;\">@returns<\/span> <span style=\"color: #267F99;\">{void}<\/span><\/span>\r\n<span style=\"color: #148A14;\"> *\/<\/span>\r\n<span style=\"color: #267F99;\">visitPattern<\/span>(<span class=\"pl-smi\">node<\/span>, <span class=\"pl-smi\">options<\/span>, <span class=\"pl-smi\">callback<\/span>) {<\/pre>\n<\/div>\n<h2><a id=\"user-content-add-jsdoc-types-to-everything-else\" class=\"anchor\" href=\"https:\/\/github.com\/sandersn\/manual\/blob\/master\/How-to-upgrade-to-Typescript-without-anybody-noticing-part-2.md#add-jsdoc-types-to-everything-else\" aria-hidden=\"true\"><\/a>Add JSDoc types to everything else<\/h2>\n<p>Once you get all the existing type annotations working, the next step is to add JSDoc types to everything else. You can turn on\u00a0<code>\"strict\": true<\/code>\u00a0to see how far you have to go \u2014 among other things, this marks any variables that have the type\u00a0<code>any<\/code>\u00a0with an error.<\/p>\n<p>You should fall into a back-and-forth of adding new JSDoc type annotations and fixing old types. Usually old types just need to be updated to work with Typescript, but sometimes you&#8217;ll find a bug.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This guide will show you how to fix Typescript compile errors in Javascript project that recently added Typescript support via a\u00a0tsconfig.json. It assumes that the\u00a0tsconfig.json\u00a0is configured according to\u00a0the description in part 1 of this post, and that you also installed types for some of your dependencies from the\u00a0@types\/*\u00a0namespace. This guide is more of a list [&hellip;]<\/p>\n","protected":false},"author":1338,"featured_media":1797,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2246","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>This guide will show you how to fix Typescript compile errors in Javascript project that recently added Typescript support via a\u00a0tsconfig.json. It assumes that the\u00a0tsconfig.json\u00a0is configured according to\u00a0the description in part 1 of this post, and that you also installed types for some of your dependencies from the\u00a0@types\/*\u00a0namespace. This guide is more of a list [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2246","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\/1338"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/comments?post=2246"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/2246\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media\/1797"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media?parent=2246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=2246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=2246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}