Node can run .ts, .mts and .cts files without a build step. Per the Node docs it "will replace TypeScript syntax with whitespace, and no type checking is performed". The work is done by Amaro, a wrapper around the SWC TypeScript parser. Support is on by default from v23.6.0 (and v22.18.0) and the docs mark it stable from v24.12.0; I ran everything on v24.19.0 with no warning.
Because only syntax is deleted, line and column numbers are preserved, so stack traces are right without source maps. The rules follow from "delete, never generate":
- Only erasable syntax. Anything that needs generated JavaScript throws
ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX: enums, namespaces containing values, parameter properties,import x = require().--experimental-transform-types(added v22.7.0) enables the transformation, still with an experimental warning and with source maps on. - No type checking. A type error does not stop the program. Run
tsc --noEmitseparately. - No
tsconfig.json.paths,targetand other options are ignored.pathsaliases fail to resolve; the nearest equivalent ispackage.jsonsubpath imports starting with#. - Real file extensions.
import "./types.ts", not"./types". typekeyword on type imports. Node cannot know thatConfigis a type, soimport { Config }stays and fails at link time.verbatimModuleSyntaxmakestscenforce this.- Not in
node_modules. Node refuses TypeScript files there, to discourage publishing.tspackages. - No
.tsxand no decorators:@dec class A {}failed withSyntaxError: Invalid or unexpected token.
The Node docs recommend erasableSyntaxOnly, verbatimModuleSyntax, rewriteRelativeImportExtensions and module: nodenext, so tsc rejects exactly what Node would reject.