Status: Accepted (2026-04-14); revisit at v0.3
Every new Node package defaults to TypeScript. For @dotbabel/dotbabel
the question was whether to adopt TS from day one or stay on plain .mjs
with JSDoc.
Plain JavaScript ESM + JSDoc @typedefs. No TypeScript.
.mjs only, no .ts.export gets a JSDoc block — enforced by
scripts/check-jsdoc-coverage.mjs in CI.@typedefs (HarnessContext,
ValidationResult, StructuredError, …) consumed via
/** @type {import('./spec-harness-lib.mjs').HarnessContext} */ in
consumer code.npm publish ships the code verbatim. Debugging shows
the same file paths consumers see. Source maps are irrelevant.npx. No TS compile step, no dev/prod parity concerns..d.ts. Consumers who want stronger types in their projects get
JSDoc inference today. A hand-written index.d.ts is a v0.3+ option
(not blocking).scripts/check-jsdoc-coverage.mjs
cover most of the ground; we explicitly are not running tsc --noEmit.tsc --noEmit type-checking, .mjs as source — half
the complexity of full TS adoption. Rejected because CI still has to run
tsc on PRs (slow) and consumers still need to maintain .d.ts
provenance. Benefit is marginal..mjs — standard for most libraries.
Rejected on the “zero runtime deps + zero build step” aesthetic: the
harness is supposed to be embarrassingly simple to read. A transpile
step contradicts that..d.ts hand-authored today — deferred. The JSDoc coverage gate
already provides most of the editor experience. Revisit when a consumer
files a specific request..d.ts becomes
maintenance burden.