title: Import a JavaScript module or library into TypeScript
body: <p>Over many years I've struggled with this same issue. I cannot seem to work out how to use a JavaScript library from TypeScript, reliably.</p>
  <p>I seem to get it working by accident and then move on and not revisit such code for years until a extrinsic change forces a breakage, like today when I updated VS 2019.</p>
  <p>I've spent days reading about modules and requires and loaders, but I get more and more confused.</p>
  <p>Example. I want to use DayJS in a TypeScript <code>.ts</code> file I am writing.</p>
  <p>Here's the sample code.</p>
  <pre><code>import * as dayjs from 'dayjs'
  dayjs().format()
  </code></pre>
  <p>The thing I can't understand is that this syntax has never worked for me with any library for two reasons:</p>
  <ol>
  <li>It omits the path to the <code>dayjs</code> folder, for me it should be <code>lib/dayjs</code></li>
  <li>It doesn't specify a file, and my previous working reference to <code>moment.js</code> was pointed at the <code>moment.js</code> file.</li>
  </ol>
  <p>It's not clear whether <code>'dayjs'</code> is a folder or a file.</p>
  <p>Two issues that compound learning are:</p>
  <ol>
  <li>TypeScript gives the same error whether it's found something but cannot find anything to load, or whether the path is invalid/nonexistent.</li>
  </ol>
  <blockquote>
  <p>error TS2307: Cannot find module 'lib/dayjs' or its corresponding type declarations.</p>
  </blockquote>
  <ol start="2">
  <li><p>TypeScript seems to allow the import to point to a file without a file extension, for example, this code seems to satisfy and silence the error above, because on disk there is an <code>index.js</code> file. This &quot;flexibility&quot; leads to ambiguity and confusion.</p>
  <p><code>import * as dayjs from &quot;lib/dayjs/index&quot;;</code></p>
  </li>
  </ol>
  <p>The TypeScript documentation itself doesn't give an example of importing from a JavaScript library, only from other <code>.ts</code> files, which it does without the extension.</p>
  <p>Here are the DayJS files on disk.</p>
  <pre><code>lib\dayjs\esm          
  lib\dayjs\locale       
  lib\dayjs\plugin       
  lib\dayjs\CHANGELOG.md 
  lib\dayjs\dayjs.min.js 
  lib\dayjs\index.d.ts   
  lib\dayjs\locale.json  
  lib\dayjs\package.json 
  lib\dayjs\README.md    
  </code></pre>
  <p>The following syntax gives no error, TypeScript compiles it and even loads intellisense/documentation.</p>
  <pre><code>import * as dayjs from &quot;lib/dayjs/index.d.js&quot;;
  </code></pre>
  <p>But that file doesn't exist! So my web app doesn't work because Chrome can't get it. But the following <em>doesn't</em> compile, even though the file exists!!</p>
  <pre><code>import * as dayjs from &quot;lib/dayjs/index.d.ts&quot;;
  </code></pre>
  <blockquote>
  <p>error TS2691: An import path cannot end with a '.d.ts' extension. Consider importing 'lib/dayjs/index' instead.</p>
  </blockquote>
  <p>However, when I do what the error suggests, well again that's a <code>404</code> for Chrome.</p>
  <p>Does anyone know what on Earth is going on??</p>
  <p>What's the definitive way to use a JavaScript library in TypeScript?</p>
  <hr />
  <p>Update</p>
  <p>I have now used the <code>baseUrl</code> and <code>paths</code> settings in <code>tsconfig.json</code> to get an import statement compiling in TypeScript which transpiles to a path that is <code>200 OK</code> when deployed/hosted.</p>
  <pre><code>&quot;compilerOptions&quot;: {
      
      &quot;target&quot;: &quot;es5&quot;,
      &quot;module&quot;: &quot;es2015&quot;,
      &quot;baseUrl&quot;: &quot;./wwwroot/&quot;,
      &quot;paths&quot;: {
          &quot;lib/dayjs/dayjs.min.js&quot;: [ &quot;lib/dayjs/index&quot; ]
      },
  ...
  </code></pre>
  <p>TypeScript intellisense is telling me that my usage of DayJS is correct.</p>
  <pre><code>var f = dayjs().format(&quot;dddd D MMMM YYYY&quot;);
  var t = dayjs(date).format(&quot;dddd D MMMM YYYY&quot;);
  </code></pre>
  <p>But in the browser, Chrome reports an error:</p>
  <blockquote>
  <p>TimeHelpers.js:16 Uncaught TypeError: dayjs is not a function</p>
  </blockquote>
  <p>I've no clue. I might try moment again, but that gave me some other odd error where <code>global</code> was undefined right at the top of its source code.</p>
  <p>Otherwise, apparently I can declare dayjs as <code>Any</code> to satisfy the TS compiler and then use an old-fashioned <code>&lt;script&gt;</code> tag to load it in on the page. This is nuts.</p>
  <hr />
  <p>Update</p>
  <p>I've made enough progress, by adding the following two lines to my <code>tsconfig.json</code>, and changing to</p>
  <pre><code>&quot;esModuleInterop&quot;: true,
  &quot;allowSyntheticDefaultImports&quot;: true,
  </code></pre>
  <p>And</p>
  <pre><code>import dayjs from &quot;lib/dayjs/dayjs.min.js&quot;
  </code></pre>
  <p>And I now get an error other people are getting which is a relief, because at least I now know to not use DayJS.</p>
  <p><a href="https://github.com/iamkun/dayjs/issues/313" rel="nofollow noreferrer">https://github.com/iamkun/dayjs/issues/313</a></p>
  <hr />
  <p>Update</p>
  <p>Long day today, but some progress was made.</p>
  <ul>
  <li>I've reconfigured <code>baseUrl</code> and <code>paths</code> in <code>tsconfig.json</code> based on what I've reread and reinterpreted from the docs.</li>
  <li>I've switched to trying <code>luxon</code> but have <a href="https://github.com/moment/luxon/issues/953" rel="nofollow noreferrer">problems</a> with that.</li>
  <li>VS Code and the compiler see the Luxon typings and intellisense works.</li>
  <li>I've added a small tweak to my <code>gulpfile.js</code> to mutate an import path so that Chrome can load it when deployed, works.</li>
  <li>Tomorrow I will go back and try moment or one of the others and see if I can apply my new knowledge to get one of those packages working.</li>
  </ul>
  <p>I'll post a full explainer when I've got it all working.</p>