Mixing JavaScript and TypeScript in Node.js

Javascriptnode.jsTypescriptJsdoc

Javascript Problem Overview


While having parts of a Node.js in plain ES6, is it possible to mix in some Typescript modules within the same project?

E.g. having some Types defined in TypeScript that are imported via require into plain ES6 files?

Javascript Solutions


Solution 1 - Javascript

Yes this is possible.

Combine the following TypeScript compiler options

  1. --allowJs

    Explicitly supports mixed JavaScript and TypeScript sources

  2. --outDir

Since all files will be transpiled, it is necessary to output the resulting JavaScript into a different directory otherwise the input .js files would be overwritten1.

  1. --checkJs

This is completely optional. If specified, the compiler will typecheck JavaScript files, reporting errors just as in TypeScript files, where as it would otherwise tolerate inconsistencies.

As to using types declared in a TypeScript file in a JavaScript file, this can indeed be done.

TypeScript actually powers all of the JavaScript intellisense in tools like Visual Studio Code.

Types may be placed in JSDoc2 comments. These comments can reference types imported from TypeScript (.ts/.tsx/.d.ts) files. IDEs like Visual Studio Code will provide syntax-highlighting and auto completion within these comments.

There's a caveat however. Because there's no manifest syntax for types in JavaScript, they cannot be imported individually but must be attached to a value which is imported. This is most conveniently achieved via TypeScript's declaration merging as shown below.

Example:

a.ts

export default createThing;

function createThing(...args): createThing.Thing  {...}

namespace createThing {
  export interface Thing {...}
}

b.js

import createThing from './a';

/**
 * @param {createThing.Thing} thing
 */
export function takesThing(thing) {}

Notes:

1: --outDir is not necessary if you additionally specify the --noEmit flag. You would do this when using a tool such as SystemJS (with plugin-typescript) or Webpack (with ts-loader) to host the TypeScript transpiler. The same applies if you are using TS Node.

2: Although called JSDoc comments, they are interpreted in the context of the TypeScript type system, not the JSDoc system. Languages and tools like TypeScript, and Google's Closure Compiler, effectively hijack the JSDoc syntax for their own purposes and thereby confer potentially conflicting meanings to its constructs. This isn't usually a problem but it's worth knowing because it can be difficult to determine the applicability and correctness of these comments and the compatibility of the types that they reference or declare.

Remarks:

Although this question and answer is all about importing types for use in JavaScript files, it's very often unnecessary as the compiler will infer the types from the values of your expressions.

It's also worth mentioning that if you find yourself needing to write a lot of JSDoc style type annotations you are almost certainly better off converting the file to TypeScript as the syntax for expressing types in JSDoc is clumsy. Thanks to the --allowJs option, you can do this on a file by file basis, as described above.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexander ZeitlerView Question on Stackoverflow
Solution 1 - JavascriptAluan HaddadView Answer on Stackoverflow