Minimalistic example of configuring TypeScript and Node to:
- emit modern ES modules code
- import modules that use Node built-ins
- import modules that don't have named exports
- import your own modules without specifying an extension
- lint with ESLint, with TypeScript support
- test the TypeScript code instantly without having to build first
- run the resulting JavaScript code
Bonus: continuous integration script for GitHub Actions. It automatically runs tests on every pushed commit.
In tsconfig.json
, set this in compilerOptions
:
"target": "ES2022",
"module": "ES2022", // Output `import`/`export` ES modules
- run
npm install --save-dev @types/node
- in
tsconfig.json
undercompilerOptions
, set"moduleResolution": "node"
, sotsc
can find modules when targeting ES6+"types": ["node"]
to avoid errors related to Node built-in modules
Normally we could write in TypeScript
import { Foo } from 'package';
but when generating ES modules code, that statement will be passed through as is, and will cause Node to fail with
SyntaxError: The requested module 'package' does not provide an export named 'Foo'
because package
doesn't provide named exports.
What we'll do is import the entire module, and then destructure it:
import package from 'package';
const { Foo } = package;
However, this will generate Error TS1192: Module '...' has no default export.
To prevent that, set "allowSyntheticDefaultImports": true
in tsconfig.json
.
When transpiling, TypeScript won't generate an extension for you. Run Node with the node --experimental-specifier-resolution=node
parameter:
node --experimental-specifier-resolution=node run.js
Otherwise, node mandates that you specify the extension in the import
statement.
Add "type": "module"
to package.json
, because TypeScript can't generate files with the .mjs extension.
To be able to run eslint
, we must create an .eslintrc.json
file. Then, install the required dependencies:
npm i -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-deprecation eslint-plugin-unicorn
The cleanest way to fully support Mocha with TypeScript, ES Modules and ESLint, is to use ts-node/esm
. What we need to do:
npm install -D mocha @types/mocha
- add
"mocha"
to thetypes
array intsconfig.json
- use the
.mocharc.jsonc
file to config (do not use .js config files).
To run Mocha from package.json
, we simply add a "test": "npx mocha"
line.
If your script generates an error, you'll see the line numbers from the generated .js
files, which is not helpful. We want to see the original paths and line numbers from the .ts
files. To do that, we'll add sourceMap: true
to tsconfig.json
, install source-map-support
and run node with the -r source-map-support/register
parameter. Note that Mocha already takes care of source mapping so you'll see the .ts
line numbers without having to do anything extra.
Using Travis CI and coveralls, we can configure automatic testing and coverage reporting via .travis.yml
configuration file.