---
title: TypeScript
subtitle: A guide to using TypeScript with Base UI.
description: A guide to using TypeScript with Base UI.
---

> FineSoft Components documentation. Independent Stencil port; not the official Base UI website.
>
> React API text and `@base-ui/react` examples are upstream references. FineSoft Stencil examples use `finesoft-components`. Do not treat the two packages as interchangeable.

# TypeScript

A guide to using TypeScript with Base UI.

## Namespaces

Base UI uses namespaces to organize types. Every component has two core interfaces:

- `Props` (such as `Tooltip.Root.Props`)
- `State` (such as `Tooltip.Root.State`)

### Props

When creating wrapping components, you can use the `Props` type to accept all of the underlying Base UI props for the component.

```tsx title="Prop types"
import { Tooltip } from '@base-ui/react/tooltip';

function MyTooltip(props: Tooltip.Root.Props) {
  return <Tooltip.Root {...props} />;
}
```

### State

The `State` type is the internal state of the component.
For example, `Positioner` components (such as `<Popover.Positioner>`) have state that describes the position of the element in relation to their anchor.

```tsx title="Positioner state"
function renderPositioner(props: Popover.Positioner.Props, state: Popover.Positioner.State) {
  return (
    <div {...props}>
      <ul>
        <li>The popover is {state.open ? 'open' : 'closed'}</li>
        <li>I am on the {state.side} side of the anchor</li>
        <li>I am aligned at the {state.align} of the side</li>
        <li>The anchor is {state.anchorHidden ? 'hidden' : 'visible'}</li>
      </ul>
      {props.children}
    </div>
  );
}

<Popover.Positioner render={renderPositioner} />;
```

### Events

Types relating to custom Base UI events are also exported on component parts' namespaces.

- `ChangeEventDetails` (such as `Combobox.Root.ChangeEventDetails`) is the object passed to change handlers like `onValueChange` and `onOpenChange`.
- `ChangeEventReason` (such as `Combobox.Root.ChangeEventReason`) is the union of possible reason strings for a change event.

```tsx title="Change event types"
function onValueChange(value: string, eventDetails: Combobox.Root.ChangeEventDetails) {
  console.log(value, eventDetails);
}

function onOpenChange(open: boolean, eventDetails: Combobox.Root.ChangeEventDetails) {
  console.log(open, eventDetails);
}
```

### Other accessible types

Depending on the component API, other types are also exported on component parts or utility functions.
The following list is non-exhaustive, and each of these are documented where necessary.

- Popups have an `actionsRef` prop to access imperative methods. For example, `Menu.Root.Actions` gives access to the shape of the `actionsRef` object prop on `<Menu.Root>`.
- The `toast` object on `<Toast.Root>` is a complex object with many properties. `Toast.Root.ToastObject` gives access to this interface.
- Components that have a `render` prop have an extended `React.ComponentProps` type, enhanced with a `render` prop. The `useRender.ComponentProps` type on the function gives access to this interface.

## FineSoft Stencil comparison

Stencil exports component property interfaces, change-detail types, state types, and action types from the public package. Native custom events wrap their detail type in `CustomEvent<T>`.

```ts title="stencil-types.ts"
import type { Components } from 'finesoft-components';
import type { ComboboxOpenChangeDetail, ComboboxValueChangeDetail } from 'finesoft-components/combobox';
import type { PopoverState, PopoverRootActions } from 'finesoft-components/popover';
import type { ToastObject } from 'finesoft-components/toast';
import type { VNode } from 'finesoft-components/use-render';

export type TooltipProps = Partial<Components.FsTooltipRoot>;
export type PositionerState = Pick<PopoverState, 'open' | 'side' | 'align' | 'anchorHidden'>;
export type PopupActions = { current: PopoverRootActions | null };
export type Notification = ToastObject;
export type RenderResult = VNode;

export function onValueChange(event: CustomEvent<ComboboxValueChangeDetail>) {
  console.log(event.detail.value, event.detail.reason);
}
export function onOpenChange(event: CustomEvent<ComboboxOpenChangeDetail>) {
  console.log(event.detail.open, event.detail.reason);
}
```

Stencil JSX declarations come with the package. React consumers additionally declare their custom tags in React's JSX namespace, combining native attributes with the relevant `Components` interface and native custom-event handlers. Refs on transparent parts refer to the custom-element host; use a documented `inputRef` when a form library needs the actual input. The [form examples](/react/handbook/forms.md) show both ref paths in use.
