Widget Types: generic attribute schemas#78247
Conversation
Parametrize WidgetTypeMetadata and WidgetType over the widget's attribute object (Item). Add WidgetRenderProps. Promote the widget-types module to a composite TS project so consumers in other compilation units can reference it cleanly.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Size Change: 0 B Total Size: 7.95 MB ℹ️ View Unchanged
|
|
Flaky tests detected in 2537c60. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/25815201432
|
What?
Parametrizes the widget identity types over the widget's attribute object so a widget binds its own attribute shape once and gets typed
attributes,example, andsetAttributesthroughout the framework.WidgetTypeMetadata< Item = unknown >WidgetType< Item = unknown >WidgetRenderProps< Item = unknown >(new export)Promotes
routes/dashboard/widget-types/to a composite TS project so consumers in other compilation units (e.g.widgets/<name>/) can declare a project reference to it cleanly.Part of #77616
Why?
Attribute schemas declared via
attributes?: Field< any >[]and example defaults viaRecord< string, unknown >are unchecked.A typo in an attribute id or in an example value goes undetected at the registration site.
Binding the types over
Itemlets each widget pass its own attribute shape once and get end-to-end type safety from authoring through the render surface:The change is backward compatible: the generic defaults to
unknown, so existing consumers (e.g.widgets/hello-world) keep working without changes.How?
WidgetTypeMetadatabecomesWidgetTypeMetadata< Item = unknown >. Inside the interface,attributesbecomesField< Item >[]andexample.attributesbecomesPartial< Item >.WidgetTypeextends the parametrized metadata:WidgetType< Item = unknown > extends WidgetTypeMetadata< Item >.New exported
WidgetRenderProps< Item = unknown >so the consuming surface passes typedattributes(and optionalsetAttributes) into the widget's render component.routes/dashboard/widget-types/gets its owntsconfig.json(composite project) and the parentroutes/dashboard/tsconfig.jsonadds the matching{ "path": "widget-types" }entry.Testing
npx tsgo --build routes/dashboard/widget-types/tsconfig.jsonruns clean.npm run lint:tsconfigpasses.widgets/hello-world(which does not parametrize today) still type-checks unchanged.Dependency notes
Independent of:
widgets/TypeScript scaffolding)presentationhint)Touches
routes/dashboard/widget-types/types.tson a different hunk than #78209. Logically independent; whichever merges first, the other rebases without conflict.Follow-ups
widgets/hello-worldas a documented example.