Generate and publish TypeScript declarations#153
Conversation
JSDoc types lived in src but were never shipped, forcing consumers to hand-maintain their own idiomorph.d.ts. - Add a 'types' script emitting module-shaped .d.ts from the ESM bundles (compiling src directly yields a global 'declare var' instead). - Wire it into 'dist'; expose via package.json 'types' + export conditions and ship dist/*.d.ts. - Scope the dist copy to src/*.js and gitignore src/*.d.ts so stray declarations can't leak; revert tsconfig to noEmit.
There was a problem hiding this comment.
Pull request overview
This PR adds first-class TypeScript declaration publishing for Idiomorph by generating module-shaped .d.ts files from the ESM bundles and wiring them into the package’s publish surface (types, exports, and files). It also updates JSDoc callback typedefs/signatures to preserve call signatures in the generated declarations.
Changes:
- Switch JSDoc typedefs for
Morph/NoOpto@callbackand correctmorph()’s return type toPromise<Node[]> | Node[]. - Add an npm
typesbuild step to emit and shipdist/*.d.ts, and expose them viapackage.json(types+exportstypesconditions). - Tighten dist packaging (copy only
src/*.js) and ignore accidentalsrc/*.d.ts.
Reviewed changes
Copilot reviewed 2 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/idiomorph.js | Updates JSDoc to generate correct callable types and return type for morph(). |
| package.json | Adds types generation script; publishes declarations via types/exports and includes .d.ts in files. |
| .gitignore | Prevents accidental src/*.d.ts from being committed/published. |
| dist/idiomorph.js | Regenerated dist bundle reflecting JSDoc/signature and small runtime changes. |
| dist/idiomorph.esm.js | Regenerated ESM bundle used as the source for declaration generation. |
| dist/idiomorph.cjs.js | Regenerated CJS bundle for exports.require. |
| dist/idiomorph.amd.js | Regenerated AMD bundle. |
| dist/idiomorph.min.js | Regenerated minified browser bundle. |
| dist/idiomorph-ext.js | Regenerated htmx extension bundle. |
| dist/idiomorph-ext.esm.js | Regenerated ESM htmx extension bundle used for declaration generation. |
| dist/idiomorph-ext.min.js | Regenerated minified htmx extension bundle. |
| dist/idiomorph.d.ts | New generated declaration file for the main entry. |
| dist/idiomorph-ext.d.ts | New generated declaration file for the ./htmx entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
This could be made more robust by adding an npm lifecycle hook so stale/missing types can't get published: "prepublishOnly": "npm run dist"since |
The single ESM-shaped .d.ts described a named 'Idiomorph' export, but the
CJS bundle does 'module.exports = Idiomorph' (require() returns the object
directly). CJS/node16 consumers got types that passed yet crashed at
runtime.
Generate a separate idiomorph.d.cts ('export = Idiomorph', with a namespace
merge exposing Config et al) from the CJS bundle, and split the '.' export
into per-condition types: idiomorph.d.ts for import, idiomorph.d.cts for
require. Add dist/*.d.cts to files.
Now a CJS named import correctly fails to typecheck (TS2595) instead of
compiling to a runtime crash; 'import x = require("idiomorph")' works.
|
#122 would simplify this ofc - and allow us to drop the last commit. |
Fixes #152.
Idiomorph already authors its types as JSDoc in
src/idiomorph.js, but they were never emitted or shipped — so consumers have to hand-maintain their ownidiomorph.d.ts. This wires up generation and publishing.Changes
Use @callback to preserve Morph/NoOp signatures@typedef {Function} Morph/NoOpcollapsed to bareFunctionin generated declarations, dropping themorph()call signature.@callbackkeeps it.morph()actually returnsPromise<Node[]> | Node[](therestoreFocuspath is async), notundefined | Node[]—@returnscorrected to match.Generate and publish TypeScript declarationstypesnpm script that emits module-shaped.d.tsfrom the ESM bundles (dist/idiomorph.esm.js/idiomorph-ext.esm.js). Generating from the ESM build (which hasexport {Idiomorph}) yields a proper module declaration; compilingsrcdirectly emits a globaldeclare varthat won't resolve forimport { Idiomorph } from "idiomorph".typesinto thedistbuild, aftergen-modules.package.json: top-leveltypes, atypescondition on the.and./htmxexports, anddist/*.d.tsinfiles.src/*.jsand gitignoresrc/*.d.tsso a stray declaration can't leak into the published bundle.tsconfigstaysnoEmitsotypecheckremains a pure check.Verification
A consumer can now:
npm run typecheckandnpm run format:checkboth pass.