fix(examples): type the settings holders for Handsontable 18.1 (DEV-2727) - #281
Merged
Merged
Conversation
…727)
18.1.0 rewrote `ColumnSettings` from `Omit<GridSettings, 'data'>` to
`Omit<RemoveIndexSignature<GridSettings>, 'data'>`. Under 18.0.0 that
`Omit` collapsed against `GridSettings`'s `[key: string]: any` index
signature, so every named column option resolved to `any`. Stripping the
signature first makes the declared option types real, and two starters had
been relying on the collapse:
- angular: `gridSettings` was an unannotated object literal, so
`dateFormat: { year: 'numeric', ... }` widened to `{ year: string }` and
failed against `Intl.DateTimeFormatOptions` at the `[settings]` binding.
`ng build` is the only starter dev server that type-checks, so this
surfaced as a demo that never renders while the browser console stayed
clean and the dev server kept serving the last good bundle.
- base-web: `colorRenderer` declared `value: string` and an instance
parameter of `Handsontable` rather than `HotInstance`; a column
`renderer` was `any` before.
nuxt gets the same annotation preventively: `hotSettings` is the identical
unannotated-holder shape and only escapes today because it carries no
strictly-typed option and `nuxt build` does not type-check.
The angular fix cannot live on the `dateFormat` line itself.
`pipeline/starter-overrides.mjs` (`angular:dateFormat`) replaces that whole
line per bucket at import time, so a cast written there would be
regenerated away and never ship.
Also re-resolves `handsontable` and the wrapper packages in all 16 starter
lockfiles, which still pinned 18.0.0 while every package.json says
"latest" - the ERR_PNPM_OUTDATED_LOCKFILE drift 822d082 fixed last time.
`@handsontable/pikaday` is left at 1.0.0 (NEVER_REWRITE).
Verified at 18.1.0: `ng build` red before / green after; the generated
bucket-18 angular artifact installs with --frozen-lockfile and builds
clean; base-web, example1, fluent-ui, mui, next.js, next-shadcn.js, react,
remix, typescript and vue all build; runner `pnpm test` 940 pass / 0 fail
and `pnpm typecheck` clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
…r-18-1-column-settings
Contributor
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes DEV-2727. Companion backport:
fix/DEV-2727-angular-18-1-column-settings-p18→prod-examples/18(same commit, cherry-picked). This PR alone does not fix?v=18.1.0— bucket 18 generates from the frozen branch, so master only reaches thenextbucket and future branch cuts.What broke
18.1.0 rewrote
ColumnSettingsinhandsontable/settings.d.ts:GridSettingscarries[key: string]: any, so under 18.0.0 thatOmitcollapsed to a bare index signature and every named column option resolved toany. Stripping the signature first makes the declared types real.dateFormatitself did not change — only whether anyone checked it.Two starters were relying on the collapse:
gridSettingswas an unannotated object literal, sodateFormat: { year: 'numeric', … }widened to{ year: string }and failed againstIntl.DateTimeFormatOptionsat the[settings]binding.ng buildis the only starter dev server that type-checks, and its failure is silent from outside: the dev server keeps serving the last good bundle and the browser console stays clean, which is why this reads as a demo that simply never renders.colorRendererdeclaredvalue: stringand an instance parameter ofHandsontableinstead ofHotInstance. A columnrendererwasanybefore.nuxt gets the same annotation preventively:
hotSettingsis the identical unannotated-holder shape and only escapes today because it carries no strictly-typed option andnuxt builddoes not type-check. Verified it has teeth — injectingautoWrapCol: 12345now errors.Every other starter passes its settings literal directly as a call argument or JSX/template prop, where contextual typing keeps the literals narrow.
examples/example1/index.tscarries the identicaldateFormatobject and compiles fine.Why the fix is not on the
dateFormatlinerunner/pipeline/starter-overrides.mjs(id: "angular:dateFormat") replaces that whole line per bucket at import time, asserting exactly one match on exactly one line. A cast oras constwritten there would be regenerated away and never ship. Annotating the holder is the only form that survives generation — andGridSettingsis exported by the Angular wrapper at 16.2.0 and 17.1.0 too, so the annotation is safe at every bucket.Lockfiles
All 16 starters say
"handsontable": "latest"inpackage.jsonwhile their lockfiles still pinned 18.0.0 — theERR_PNPM_OUTDATED_LOCKFILEdrift822d0820fixed the last time, which breaks the container bake and silently pushes Tier-2 sessions onto the--no-frozen-lockfilefallback.@handsontable/pikadayis left at 1.0.0 (NEVER_REWRITE).Note for next time:
pnpm install --lockfile-onlydoes not re-resolve alatestspecifier — with the specifier unchanged pnpm considers the lockfile current and reuses the old resolution.pnpm update handsontable @handsontable/<wrapper> --lockfile-onlyis the command.No generated artifacts are committed.
import-starters.ymlregenerates the buckets from the correct source refs once this lands.Verification (raw pnpm throughout, no rtk)
examples/angularat 18.1.0:ng buildred before with the exact DEV-2727 error, green after.node pipeline/import.mjs --bucket=18 --source=<prod-examples/18 worktree>/examples --ref=prod-examples/18— then extractedangular.jsonto a temp dir outside the repo.pnpm install --frozen-lockfileclean,ng buildclean, pinned 18.1.0. The overlay appliedangular:dateFormat,angular:data-iso,angular:data-passthroughand correctly rewrote the branch's format string to the Intl object.base-web,example1,fluent-ui,mui,next.js,next-shadcn.js,react,remix,typescript,vueall build at 18.1.0.nuxttype-checks undervue-tsc(no dependency added — borrowed the vue starter's binary).runner:pnpm test940 pass / 0 fail,pnpm typecheckclean, working tree clean.Found while testing, not fixed here
examples/base-webfailsTS2688: Cannot find type definition file for 'node'in any isolated build.tsconfig.node.jsonsets"types": ["node"]but base-web has no@types/nodedependency; it passes in-tree only because TypeScript walks up to the repo root's hoisted copy. The Tier-2 container works at/appwith/baked/<framework>-18/and has no such ancestor, so base-web's share/build path is likely already broken — independently of 18.1. The starter matrix misses it because it bootsdev, notbuild. Tracked as DEV-2730.@handsontable/vue3@18.1.0declares"types": "./index.d.ts"and ships no.d.tsfile at all. SoHotTableis implicitlyanyin the vue/nuxt starters, which is why nuxt's annotation had to come fromhandsontable/settingsrather than the wrapper. A core-repo packaging defect — DEV-2732.server-examples/has the same defect, verified. All 7 Angular frontends use the unannotated-holder shape; a scratch build ofexpress/client-angularis green at 18.0.0 and red at 18.1.0 with the identicaldateFormat.yearerror. Theirpackage-lock.jsonfiles still pin 18.0.0, so nothing is broken until someone refreshes a lock. The React frontends spread{...(settings as any)}and are unaffected. DEV-2731.runner/apps/authoring/package.json,src/theme/presets.tsBUNDLED_VERSION,src/catalog.tsVERSION_OPTIONS/DEFAULT_VERSION.@handsontable/pikadayis an unused dependency ofexamples/javascript(no import anywhere; also a staleallowedCommonJsDependenciesentry inexamples/angular/angular.json, and theNEVER_REWRITEexemption exists only for it). DEV-2733.