Skip to content

feat(types): ship TypeScript definitions for the public API - #512

Merged
kevinchappell merged 10 commits into
mainfrom
feat/typescript-definitions
Sep 28, 2026
Merged

kevinchappell merged 10 commits into
mainfrom
feat/typescript-definitions

Conversation

@kevinchappell

Copy link
Copy Markdown
Collaborator

Stacked on #511 (control sets). Merge #511 first; this PR's own changes are the 10 commits after it. Please squash-merge (one commit, fcdb782 fixes code added earlier in this PR).

What

Formeo now ships TypeScript definitions, so the README's "Full type definitions included" is true.

  • src/types/formeo.d.ts is the single, hand-written source. It covers FormeoEditor and FormeoRenderer, every option, event callback, before hook (onBeforeAdd/Remove/Clone/Save, with onBeforeAdd's detail a union keyed on componentType), action (click.btn, save.form, remove.component, remove.page, item removals with isClearAll), the formeo* DOM events (on document and on elements), destroy(), pages and renderer pagination, control sets (controlSet definitions and componentType: 'controlSet'), and the formData shape. The old README names FormeoOptions and FormData still work, marked @deprecated.
  • The types follow the runtime, not just the docs. For example, both constructors accept no options; controls.disable.formActions: false is a type error because it throws; a component's config.events.onRender / onAddChild handler is typed for both calls the runtime makes (the event, then the legacy element / { parent, child } call); and the editor's onRender, formeoOnRender and formeoConditionUpdated are left out because nothing fires them.
  • Checked by tsc: npm run test:types compiles fixtures (src/types/*.test-d.ts) against the d.ts, with @ts-expect-error lines that fail if a type is loosened. It runs in CI (pull-request.yml) and on pre-push.
  • Published: after build:lib, tools/build-types.mjs copies the d.ts to dist/formeo.d.ts and dist/formeo.d.cts; package.json has types and a types condition first in each exports["."] entry. tools/dist.test.mjs now handles nested conditions and checks that tsc finds the types from bundler and nodenext (.mts and .cts) consumers.
  • TypeScript 7 (typescript@^7.0.2, devDependency) via the tsc CLI only. Commit-message linting still works with it installed (its config is in package.json).

Docs

docs/typescript.md (what's typed, before-hook narrowing, DOM events, control sets, supported TypeScript versions: 4.7+, 5.0+ for bundler, dom lib; node10 needs TS ≤ 6 or bundler/nodenext; replacing your own declare module 'formeo' or Window declarations), a rewritten README TypeScript section, docs/README.md, the editor constructor row (options are optional), the action names in docs/options/actions/README.md (click.btn, save.form), and CLAUDE.md. A separate commit fixes docs/options/events/README.md: the edit panel events fire for stages too (Refs #316).

For consumers

Code that was any is now type-checked, so upgrading may surface type errors in existing TypeScript code. Projects with their own declare module 'formeo' or Window.FormeoEditor declarations should delete them (formeo-io has one).

Testing

Follow-ups

  • controls.disable.formActions: false throws at runtime (typed as an error for now)
  • The editor's onRender, formeoOnRender and formeoConditionUpdated are documented but never fired: wire them up or drop them from the docs
  • Run @arethetypeswrong/cli in CI
  • Remove the deprecated FormeoOptions / FormData aliases in the next major

Refs #184

Hand-written types for FormeoEditor and FormeoRenderer, every option, event, before hook,
action and DOM event, and the formData shape. npm run test:types compiles a usage fixture
against them with tsc --noEmit.

Refs #184
A controls.elements entry with controlSet (no tag of its own) and componentType 'controlSet'
with data { layout, row, fields } in the onBeforeAdd detail.

Refs #227
Copy src/types/formeo.d.ts to dist/formeo.d.ts and dist/formeo.d.cts after build:lib and point
types plus every exports condition at them. dist.test.mjs now reads nested exports conditions and
checks that tsc resolves the types from bundler and nodenext (ESM and CJS) consumers.

Refs #184
Add docs/typescript.md, rewrite the README TypeScript section, and correct click.btn/save.form,
the onSave example and the optional editor options argument.

Refs #184
Copilot AI lite review requested due to automatic review settings September 28, 2026 18:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Base automatically changed from feat/227-control-sets to main September 28, 2026 18:59
@kevinchappell
kevinchappell merged commit b1bae71 into main Sep 28, 2026
1 check passed
@kevinchappell
kevinchappell deleted the feat/typescript-definitions branch September 28, 2026 19:04
@kevinchappell

Copy link
Copy Markdown
Collaborator Author

🎉 This PR is included in version 5.13.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants