notes.dt.in.th

Since Node.js v22.7.0, there’s a --experimental-transform-type flag that lets me run TypeScript files natively in Node.js without the need for extra tools like tsx or ts-node.

This means I can now:

  • Build and run Node.js applications in TypeScript without extra build steps
  • Deploy functions (like AWS Lambda or Google Cloud Run Functions) written in TypeScript without extra build steps

This is how I set it up Node.js projects:

  • I add this in package.json to ensure Node treats the files in the project as an ES module by default:

    "type": "module",
  • I install the type definitions and tsconfig preset:

    pnpm add -D @types/node@22 @tsconfig/node22
  • I use this tsconfig.json:

    {
      "extends": "@tsconfig/node22/tsconfig.json",
      "compilerOptions": {
        "verbatimModuleSyntax": true,
        "allowImportingTsExtensions": true,
        "noEmit": true
      }
    }

    This config ensures compatibility with Node 22's module system and TypeScript's latest features.

    OptionWhy it is needed
    verbatimModuleSyntaxMust be set to true, otherwise, TypeScript will let you import types without the type keyword, which is not supported in Node 22. All non-type imports must be a value, otherwise you will get a “SyntaxError: The requested module does not provide an export named '...'” error.
    allowImportingTsExtensionsMust be set to true, otherwise, TypeScript will tell you to import .ts files with the .js extension. But since .ts files are now run natively without being compiled to .js, the .js files do not exist. By setting this to true, TypeScript will let you import .ts files with the .ts extension.
    noEmitMust be set to true, otherwise TypeScript will try to compile the files to .js files, which is not needed since Node can now run .ts files directly.
  • To run TypeScript files, the --experimental-transform-type flag must be passed to Node CLI. There are many ways to do this:

    • By setting the NODE_OPTIONS environment variable
    • By passing the flag directly on the CLI

    In some projects, I add this to the scripts section of my package.json:

    "node": "node --experimental-transform-type --env-file=.env"

    This lets me run TypeScript files and load environment variables from a .env file.

    Now, I can just run:

    pnpm node src/index.ts

    …and Node will execute my TypeScript code directly, with no build step or extra tooling required.