Skip to content

Conversation

RobinMalfait
Copy link
Member

@RobinMalfait RobinMalfait commented Sep 18, 2025

This PR fixes an issue where the Combobox only inferred the type of the internal value based on the value prop.

We only wanted to infer the type of the Combobox based on the value prop to make it less confusing where values came from. But if you are using an uncontrolled component then the value is not provided to the Combobox.

In most cases this isn't an actual issue, but it is if you also want to us the by prop to improve comparing values based on a certain property.

Without this change, the only way of typing the by prop correctly is by using an explicit type on the Combobox:

- <Combobox
+ <Combobox<typeof people[number]>

With this change, the internal value type will be inferred by the onChange meaning that the by prop is properly typed now.

Test plan

Given a reproduction where the by prop is correct if you look at the type of the onChange:

import * as React from 'react'
import { Combobox } from './combobox'

export function App() {
  function handleChange(person: { id: string; name: string } | null) {
    console.log(person)
  }

  return <Combobox by="name" onChange={handleChange}></Combobox>
}

Before:

image

After:

image

There is no output because there are no errors.


Given a reproduction where the by prop is incorrect if you look at the type of the onChange:

import * as React from 'react'
import { Combobox } from './combobox'

export function App() {
  function handleChange(person: { id: string; name: string } | null) {
    console.log(person)
  }

  return <Combobox by="username" onChange={handleChange}></Combobox>
}

Before:

image

After:

image

The error type is much simpler and easier to reason about. It's not as clean as a simple 'id' | 'name' because the by prop can also be a function. But at least there isn't a wall of TypeScript errors you have to reason about. Maybe we can improve this part in a future PR.

Fixes: #3636

We only wanted to infer the type of the Combobox based on the `value`
prop. But if you are using an uncontrolled component then the `value` is
not provided to the `Combobox`.

In most cases this isn't an actual issue, but it is if you _also_ want
to us the `by` prop to improve comparing values based on a certain
property.

Without this change, the only way of typing the `by` prop correctly is
by using an explicit type on the `Combobox`:

```diff
- <Combobox
+ <Combobox<typeof people[number]>
```

With this change, the internal value type will be inferred by the
`onChange` meaning that the `by` prop is properly typed now.

Co-Authored-By: Jordan Pittman <thecrypticace@gmail.com>
Copy link

vercel bot commented Sep 18, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
headlessui-react Ready Ready Preview Comment Sep 18, 2025 3:32pm
headlessui-vue Ready Ready Preview Comment Sep 18, 2025 3:32pm

@RobinMalfait RobinMalfait merged commit 31b3e47 into main Sep 18, 2025
8 checks passed
@RobinMalfait RobinMalfait deleted the fix/issue-3636 branch September 18, 2025 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

React Combobox v2 type definitions don't support "by" prop in uncontrolled usage
2 participants