Prompt and context
A Node.js service currently compiles TypeScript to JavaScript before the container starts. The team wants to execute .ts files directly to shorten scripts and the developer toolchain. Explain built-in type stripping, its support boundary, module resolution, configuration limits, testing, and production release strategy.
What the interviewer evaluates
- Whether you know Node.js removes type annotations without type checking or runtime code generation.
- Whether you identify enums, runtime namespaces, parameter properties, and decorators as non-erasable syntax.
- Whether you understand that Node.js ignores
tsconfig.json, so path aliases and target transforms do not apply automatically. - Whether you separate development scripts, compiled artifacts, dependencies, and production services.
Clarifying questions to ask
- Is the target a development script, CLI, test, or long-running production service?
- Does the code use enums, decorators, parameter properties, namespaces, or path aliases?
- Can module mode, Node version, TypeScript version, and the release image be standardized?
- Does the team need full type checking, source transformation, source maps, or older Node support?
30-second answer framework
I would treat the built-in feature as a lightweight executor. It replaces erasable type syntax with whitespace, performs no type checking, and does not generate JavaScript for enums or decorators. First scan the code and pin the Node version. Use import type, explicit extensions, and clear module rules instead of relying on tsconfig path aliases. Services that need full TypeScript semantics keep the compiler or tsx; the built-in path starts with scripts and small tools. CI runs type checks, runtime tests, and artifact checks before expanding the scope.
Step-by-step deep dive
1. Explain the erasure model
Node.js replaces type annotations with whitespace, so stack line numbers generally remain aligned without source maps. It does not type-check or transform syntax that needs JavaScript generation. Enums, runtime namespaces, parameter properties, and decorators produce unsupported-syntax errors. Direct execution is limited to erasable syntax.
2. Pin modules and imports
Node.js supports CommonJS and ES module TypeScript files; the actual mode depends on package configuration, extension, and invocation. Type imports must use import type; otherwise the erased import is treated as a value and fails at runtime. Use resolvable relative extensions and package.json imports rather than aliases that Node cannot transform.
3. Respect tsconfig and dependency boundaries
The built-in executor ignores tsconfig.json, so it does not apply target lowering, paths mapping, or other compiler transforms. Node.js also refuses TypeScript files under node_modules to keep uncompiled source from becoming a package contract. Use a full compiler or runtime tool when transformation, decorators, or TypeScript dependencies are required.
4. Plan validation and rollback
Run lint, type checks, unit tests, integration tests, and startup probes across the Node version matrix. Compare compiled and erased execution for behavior, startup time, and errors. Pin the runtime: type stripping is stable from v25.2 and v24.12, while v26 removes the experimental transform switch. If production fails, return to compiled artifacts instead of enabling unsupported transforms ad hoc.
High-quality sample answer
I would treat built-in type stripping as a lightweight TypeScript execution path, not a full compiler. Inventory enums, decorators, parameter properties, runtime namespaces, path aliases, and TypeScript dependencies; those need transformation or checking, so keep the compiler or tsx. Migrated code uses import type, stable module rules, and resolvable relative paths, while tsc --noEmit remains the type-check gate. Node.js ignores tsconfig, so build scripts must configure package imports explicitly. Canary development scripts and CLIs first, and have CI compare startup probes, runtime errors, tests, and image behavior. The capability is stable from v25.2/v24.12 and v26 removes the experimental transform switch. Production services switch only after the matrix passes and retain a compiled-artifact rollback.
Common mistakes
- Treating type stripping as type checking or a complete compiler.
- Running files with enums, decorators, parameter properties, or runtime namespaces directly.
- Relying on tsconfig paths, target transforms, or JSX settings.
- Omitting
import typeand causing a value-import runtime error after erasure. - Running uncompiled TypeScript from
node_modulesin a production image. - Measuring startup speed without type checks, integration tests, or an older-version matrix.
Follow-up questions and answers
Why does type stripping usually need no source map?
The implementation replaces annotations with whitespace and preserves character positions, so runtime lines generally still map to the source file. Transformed syntax still needs a full compiler and source maps.
When must tsx or a compiler remain?
Keep the toolchain for enums, decorators, parameter properties, path aliases, target transforms, full type checking, or TypeScript dependencies that need compilation.
How do you control Node version differences?
Pin versions in images, CI, and local tools and perform capability detection. Treat type stripping as a runtime prerequisite and fall back to a verified JavaScript artifact when it is absent.