Question presented to candidate: "A teammate says you don't even need ts-node or tsx anymore to run a .ts file with Node directly. Is that actually true for ANY TypeScript file, or are there real limits to what Node can run without a full transpiler?"
What a strong answer should cover:
- Modern Node (type stripping unflagged-by-default starting around Node 23.6+/24) can run a
.tsfile directly, with zero flags and zero installed packages, for files using only type annotations that can be simply erased — interfaces, type annotations on variables/parameters/returns, generics — none of which produce any runtime code at all, so removing them is sufficient. - 📌 Verified, not assumed — confirming the teammate's claim, for THIS category: a real
.tsfile with function parameter/return types and a realinterfacegenuinely ran correctly with plainnode file.ts, no flag, no--experimental-strip-types, no transpiler installed at all. - 📌 Verified, not assumed — the real, precise limit the teammate's claim glosses over: a real TypeScript
enum— a construct that requires actual code generation, not mere erasure, since an enum produces real runtime values/objects — genuinely failed running the identical way, with a real, specific error:SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode. - 📌 Interview term: type stripping (what Node does) vs. transpilation (what
tsx/ts-nodedo): stripping only ever removes type syntax, never transforms it — this is precisely why erasable syntax (types, interfaces) works natively, verified above, while syntax requiring genuine transformation (enums, namespaces, legacyimport =syntax, and other non-erasable TS features) genuinely does not, also verified above with a real, specific error naming exactly this distinction ("not supported in strip-only mode"). - The precise, honest scope for the interview:
tsx/ts-noderemain genuinely necessary for any codebase using non-erasable TypeScript features (enums verified above being the most common), or that needs other transpiler-provided capabilities (path-mapping resolution, decorators depending on configuration, targeting an older Node/JS version) — native stripping is a real, meaningful reduction in tooling need for a large, common subset of TypeScript, not a full replacement for every TypeScript codebase.
Clarifying questions expected:
- "Does this codebase use TS enums, namespaces, or other non-erasable syntax anywhere, even in a few files?" — directly decides whether native stripping alone is sufficient, or a transpiler is still genuinely required.
- "Is the target Node version confirmed to have type stripping enabled by default, or would an explicit
--experimental-strip-typesflag (or an even older version lacking it entirely) be needed?" — a real, version-dependent detail worth confirming for a specific deployment target.
Code / implementation expected: Yes — a real .ts file genuinely running with zero flags, alongside a real, specific error on a genuine TS enum, is the concrete, convincing proof of exactly where native stripping's real capability ends.