Add typed state generics to component definitions#56
Conversation
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com>
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves the component module’s TypeScript API by threading an explicit TState generic through component definitions and render contexts so component state no longer widens to Record<string, unknown>.
Changes:
- Add
TStategenerics toComponentDefinitionandComponentRenderContext. - Thread
TStatethroughdefineComponent()andcomponent(), and typegetState/setStateagainstkeyof TState. - Add a test asserting typed state is preserved for both
ComponentDefinition<Props, State>andComponentRenderContext<Props, State>.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
src/component/types.ts |
Adds TState to component definition and render context typings. |
src/component/component.ts |
Threads TState through factory functions and types getState/setState accordingly. |
tests/component.test.ts |
Adds a type-focused test to validate state generic preservation. |
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com>
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com>
Applied the review-thread fixes in d9eecb8 and polished the final test adjustment in 8aa55fc. The follow-up now requires an initial state object for explicit |
There was a problem hiding this comment.
Pull request overview
Threads a TState generic through the component type system so component render contexts, lifecycle hooks, and state helpers can preserve a declared state shape instead of widening to Record<string, unknown>.
Changes:
- Add
TState-aware component types (ComponentRenderContext,ComponentDefinition) and state helper typing (getState/setState) viaComponentStateShape. - Update
defineComponent()andcomponent()to accept and propagateTState(including typedthisin lifecycle hooks). - Add type-focused tests ensuring state generics are preserved and state helpers are key/value constrained.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/component/types.ts |
Introduces ComponentStateShape/ComponentElement/ComponentClass and threads TState through ComponentDefinition + ComponentRenderContext. |
src/component/component.ts |
Updates defineComponent()/component() generics and strongly types internal state + getState/setState. |
tests/component.test.ts |
Adds type-level assertions (@ts-expect-error, expectType) validating typed state propagation and helper constraints. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jonas Pfalzgraf <jolun.swtor@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jonas Pfalzgraf <jolun.swtor@gmail.com>
|
@copilot einige pipelines schlagen fehl |
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com>
Erledigt in 94b19c5. Ich habe die Rückwärtskompatibilität für |
There was a problem hiding this comment.
Pull request overview
This PR extends the bquery/component API surface to support typed component state via a TState generic, and adds a dedicated CI type-check step to ensure type-level assertions in component tests are validated.
Changes:
- Thread
TStatethroughComponentDefinition,ComponentRenderContext,defineComponent(), andcomponent()to preserve declared state shapes. - Add typed
getState()/setState()overloads and update lifecycle hook typing to expose state helpers viathis. - Add
test:types(tsc against a focused test tsconfig) and corresponding CI step to enforce@ts-expect-error/expectTypeassertions.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/component/types.ts |
Adds TState generics and typed state shapes + hook/element helper types. |
src/component/component.ts |
Implements typed state plumbing in the runtime component class + overloads for defineComponent/component. |
tests/component.test.ts |
Adds type-assertion coverage for typed/untyped state paths; tightens prop validator type guards. |
tests/setup.ts |
Adjusts getComputedStyle global wiring for tests. |
tsconfig.component-test.json |
Introduces a dedicated tsconfig for type-checking component tests. |
package.json |
Adds test:types script to run the focused type-check. |
.github/workflows/test.yml |
Runs test:types in CI before runtime tests. |
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com>
Erledigt in d1aa335. Die |
There was a problem hiding this comment.
Pull request overview
Threads an explicit TState generic through the component API so component definitions, render contexts, and state helpers retain the declared state shape, and adds CI type-checking to enforce the new type assertions.
Changes:
- Add
TStatetoComponentDefinition/ComponentRenderContextand introduce supporting types (ComponentStateShape,ComponentElement,ComponentClass). - Update
defineComponent()/component()to support typed state helpers while preserving the untyped fallback + legacygetState<T>(key: string)overload. - Add component typing assertions + introduce a dedicated
test:typesCI step with a focusedtsconfig.component-test.json.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.component-test.json | Adds a focused TS config to type-check component typing assertions in tests. |
| tests/setup.ts | Adjusts the getComputedStyle global wiring for the test environment. |
| tests/component.test.ts | Adds typed-state type assertions and extends validator checks in prop validation tests. |
| src/component/types.ts | Introduces TState generics and new public component typing surface. |
| src/component/component.ts | Threads TState through component creation, adds typed getState/setState overloads, and overloads defineComponent/component. |
| package.json | Adds test:types script to run the focused TS type-check. |
| .github/workflows/test.yml | Runs bun run test:types in CI before runtime tests. |
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com>
Erledigt in 6ab5949. Die Lifecycle-Hook-Typen unterstützen jetzt wieder sowohl method-style Hooks mit typisiertem |
There was a problem hiding this comment.
Pull request overview
This PR enhances the component module’s TypeScript API by threading a TState generic through component definitions and render contexts so state helpers and render({ state }) retain the declared state shape, while preserving an untyped fallback for backward compatibility. It also adds a dedicated CI type-check step to ensure type-assertion tests are actually validated.
Changes:
- Add
TStategenerics toComponentDefinitionandComponentRenderContext, plus supporting state/element/class helper types. - Update
defineComponent()/component()to carry typed state through to lifecyclethishelpers and render context. - Add compile-time typing tests (with
@ts-expect-errorassertions) and enforce them via a newtest:typesCI step.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.component-test.json | New focused TS config for type-checking component typing assertions. |
| tests/setup.ts | Adjusts getComputedStyle global wiring to a typed wrapper. |
| tests/component.test.ts | Adds typed-state type assertions and updates validators to be type-safe at runtime. |
| src/component/types.ts | Introduces TState generics and typed lifecycle hook this via overloaded call signatures. |
| src/component/component.ts | Threads typed state through defineComponent/component, adds overloads, and types state helpers. |
| package.json | Adds test:types script for CI type-checking. |
| .github/workflows/test.yml | Runs bun run test:types before runtime tests. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jonas Pfalzgraf <jolun.swtor@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR extends the component/defineComponent Web Components helper to support an explicit typed state generic (TState) so component render context, lifecycle hooks, and state helpers preserve the declared state shape instead of widening to Record<string, unknown>.
Changes:
- Add
TStateplumbing acrossComponentDefinition,ComponentRenderContext, lifecycle hookthistyping, anddefineComponent()/component()overloads. - Introduce typed
getState/setStatesignatures while preserving the legacy cast-stylegetState<TResult>(key: string)overload for backward compatibility. - Add type-level assertions in component tests and enforce them in CI via a dedicated
test:typesTypeScript step.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/component/types.ts |
Adds TState generics, typed render context, typed lifecycle hook this, and state helper typings with compatibility overloads. |
src/component/component.ts |
Threads TState through defineComponent() / component() and updates internal state helper method signatures. |
tests/component.test.ts |
Adds runtime + type-level tests asserting typed-state behavior and untyped fallback behavior. |
tsconfig.component-test.json |
Adds a focused tsconfig to type-check src plus component tests with type assertions. |
.github/workflows/test.yml |
Runs the new type-check step in CI before runtime tests. |
package.json |
Adds the test:types script used by CI. |
tests/setup.ts |
Adjusts the getComputedStyle global wiring used by CSS-related tests. |
* Add `bool()` support for boolean attributes in component templates (#55) Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de> * Add typed state generics to component definitions (#56) Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de> * Pass attribute change metadata to component `updated()` hooks (#58) Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de> * Add per-component sanitizer overrides for component render output (#57) * Initial plan * feat: add per-component sanitizer options Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * docs: clarify component sanitizer baseline Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * docs: warn about sensitive component sanitizer opts Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * test: cover sanitizer allowTags overrides Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * perf: precompute component sanitizer allowlists Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Signed-off-by: Jonas Pfalzgraf <info@josunlp.de> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de> * Pass previous props into component `beforeUpdate` (#59) * Initial plan * Add previous props to beforeUpdate hook Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * Refine beforeUpdate old props implementation Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * Fix beforeUpdate typing regressions Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Signed-off-by: Jonas Pfalzgraf <info@josunlp.de> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de> * Add explicit signal subscriptions to `component()` renders (#60) * Initial plan * feat: add component signal subscriptions Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * chore: document signal subscription tracking Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: address signal integration review feedback Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: tighten component signal typing Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: resolve eslint failure in component signal test Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: handle reconnect lifecycle and signal effect errors Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: preserve reconnect signal wiring after hook errors Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: skip beforeUpdate for signal rerenders Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Signed-off-by: Jonas Pfalzgraf <info@josunlp.de> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de> * Add trusted sanitized fragments for `safeHtml` composition (#61) * Initial plan * feat: add trusted safeHtml fragment support Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * chore: finalize trusted safeHtml support Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * docs: address trusted safeHtml review feedback Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * docs: fix second trusted safeHtml review follow-up Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * refactor: split trusted html helpers from sanitizer Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * refactor: tighten trusted html branding Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * docs: tighten trusted html internals Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Signed-off-by: Jonas Pfalzgraf <info@josunlp.de> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de> * Reuse component shadow-root style nodes across re-renders (#62) * Initial plan * fix: reuse component style element on rerender Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * chore: finalize component style reuse fix Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * test: tighten style reuse regression assertions Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * Add `@bquery/bquery/storybook` template helpers for Storybook stories (#63) * Initial plan * feat: add storybook template helper Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * docs: clarify storybook when fallback behavior Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: keep storybook helpers out of full bundle Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix: sanitize storybook helper output Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * test: tighten storybook helper security coverage Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * feat: enhance storyHtml with improved boolean attribute handling and sanitization tests * fix: update storyHtml example to reflect correct boolean attribute output * fix: defensive tag delimiter and parser comments per code review Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * chore: release version 1.6.0 - Update CHANGELOG.md for version 1.6.0 release notes including added features, changes, fixes, and security improvements. - Enhance README.md to document new boolean attribute helpers and Storybook integration. - Update bun.lock to reflect dependency upgrades for Storybook and happy-dom. - Modify definition.md to include new Storybook helpers and component state management features. - Revise components.md to demonstrate new boolean attribute handling and typed state in components. - Update getting-started.md with Storybook authoring examples and improved module descriptions. - Enhance security.md to clarify sanitization practices and introduce trusted fragment handling. - Revise index.md to highlight new Storybook helpers in the feature list. - Update llms.txt to reflect the new version 1.6.0. - Bump version in package.json to 1.6.0 and update devDependencies for Storybook. * Address review feedback for test setup, test type coverage, and component state keys (#65) * Initial plan * Address review feedback for test typing and setup Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * Finalize review feedback fixes Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * Export component state key type Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * Default component state key generic Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * Tighten component/state update semantics and Storybook attribute sanitization (#66) * Initial plan * fix review follow-up for state updates and storybook sanitization Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix storybook attribute value scanning Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * fix storybook interpolation boundary parsing Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> * docs align storybook attribute scan jsdoc Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> --------- Signed-off-by: Jonas Pfalzgraf <info@josunlp.de> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: JosunLP <20913954+JosunLP@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jonas Pfalzgraf <info@josunlp.de>
ComponentDefinitionalready preserved prop types, but component state was still widened toRecord<string, unknown>. This change threads an explicit state generic through the component API so render context and state helpers retain the declared state shape.API typing
TStatetoComponentDefinitionTStatetoComponentRenderContextTStatethroughcomponent()anddefineComponent()Typed state access
render({ state })setState()and the keyedgetState()overload tokeyof TStateso typed state helper usage stays aligned with the declared component statedefineComponent()instances/classes so state helpers remain visible to TypeScript consumersCompatibility and lifecycle typing
TStateis not explicitly provided, so existing components can still use string-keyed state without inference changing behaviorgetState<T>(key: string): Tcast-style overloadTStatetyping and the legacy overload can coexist without type errorsthissignatures while documenting that arrow hooks remain supported for callbacks that do not rely on component instance APIs viathisCoverage
ComponentDefinition<Props, State>andComponentRenderContext<Props, State>TStateis omitted, including the legacygetState<T>()compatibility pathtest:typesstep and focused test tsconfig so the newexpectType/@ts-expect-errorassertions are actually validated✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.