Capítulo 10 de 51

Chapter 10: TypeScript

Core Idea

Every Base UI component exposes its types as a namespace off the component object (e.g. Tooltip.Root.Props, Tooltip.Root.State) — this is the pattern to know for wrapping components, typing render functions, and typing change-event handlers.

Key Concepts

  • <Part>.Props: the full prop type for a part — use it to type a wrapper component that spreads props through: function MyTooltip(props: Tooltip.Root.Props) { return <Tooltip.Root {...props} />; }.
  • <Part>.State: the internal state shape passed to render function forms and className/style state-functions — e.g. Popover.Positioner.State includes open, side, align, anchorHidden for a positioner reacting to its own placement.
  • <Part>.ChangeEventDetails: the eventDetails object type passed as the second argument to change handlers (onValueChange, onOpenChange) — e.g. Combobox.Root.ChangeEventDetails.
  • <Part>.ChangeEventReason: the union of possible reason string values for that component's change events — pairs with the eventDetails.reason branching pattern from ch008 (Customization).
  • Other per-component types: <Part>.Actions for a component's actionsRef imperative-handle shape (e.g. Menu.Root.Actions); Toast.Root.ToastObject for the toast object's full interface; useRender.ComponentProps for extending React.ComponentProps with a render prop on your own custom components.

Code Examples

/* Wrapper component accepting all underlying props */
function MyTooltip(props: Tooltip.Root.Props) {
  return <Tooltip.Root {...props} />;
}
/* Typed render function using the part's own State type */
function renderPositioner(props: Popover.Positioner.Props, state: Popover.Positioner.State) {
  return <div {...props}>{state.open ? 'open' : 'closed'} on the {state.side} side</div>;
}
<Popover.Positioner render={renderPositioner} />;
/* Typed change handlers */
function onValueChange(value: string, eventDetails: Combobox.Root.ChangeEventDetails) {}
function onOpenChange(open: boolean, eventDetails: Combobox.Root.ChangeEventDetails) {}
  • What it demonstrates: the <Component>.<Part>.<TypeName> namespace convention is consistent enough to guess correctly for any component once learned on one (Props/State/ChangeEventDetails/ChangeEventReason/Actions).

Key Takeaways

  1. Type wrapper components with <Part>.Props, not a hand-rolled prop interface — it stays in sync with the library automatically across upgrades.
  2. When writing a render function, always type its state parameter with <Part>.State to get autocomplete on exactly the fields that part exposes (they differ per component).
  3. If building your own render-accepting component, useRender.ComponentProps is the type to extend rather than hand-writing a render prop type.

Connects To

  • ch007 (Composition): the render prop this chapter's State/Props types are meant to type.
  • ch008 (Customization): ChangeEventDetails/ChangeEventReason are the typed form of the eventDetails object introduced there.
  • ch050 (useRender): source of useRender.ComponentProps.