`useLabel`'s `labelProps` fails type-check when used with a `div`
- Dominant language
- TypeScript
- Stars
- 15.9k
- Forks
- 1.6k
- Avg merge
- 3d 9m
- Merged PRs (30d)
- 59
Description
### Provide a general summary of the issue here
It seems `useLabel().labelProps` is typed in a way that only works on "`label`-like" elements.
While type-check works for `span`, it fails for a `div`.
### 🤔 Expected Behavior?
This should pass type-check:
```tsx
const { labelProps, fieldProps } = useLabel({ labelElementType: 'div' });
return (
);
```
### 😯 Current Behavior
It fails with the following (quite verbose) type-check error:
```
Type '{ children: string; id?: string | undefined; role?: AriaRole | undefined; tabIndex?: number | undefined; style?: CSSProperties | undefined; className?: string | undefined; ... 219 more ...; onTransitionStartCapture?: TransitionEventHandler<...> | undefined; } | { ...; }' is not assignable to type 'DetailedHTMLProps, HTMLDivElement>'.
Type '{ children: string; form?: string | undefined; htmlFor?: string | undefined; defaultChecked?: boolean | undefined; defaultValue?: string | number | readonly string[] | undefined; suppressContentEditableWarning?: boolean | undefined; ... 271 more ...; onTransitionStartCapture?: TransitionEventHandler<...> | undefined...' is not assignable to type 'DetailedHTMLProps, HTMLDivElement>'.
Type '{ children: string; form?: string | undefined; htmlFor?: string | undefined; defaultChecked?: boolean | undefined; defaultValue?: string | number | readonly string[] | undefined; suppressContentEditableWarning?: boolean | undefined; ... 271 more ...; onTransitionStartCapture?: TransitionEventHandler<...> | undefined...' is not assignable to type 'HTMLAttributes'.
Types of property 'onToggle' are incompatible.
Type 'ToggleEventHandler | undefined' is not assignable to type 'ToggleEventHandler | undefined'.
Type 'ToggleEventHandler' is not assignable to type 'ToggleEventHandler'.
Property 'align' is missing in type 'HTMLLabelElement' but required in type 'HTMLDivElement'.
```
### 💁 Possible Solution
`labelProps` are currently typed as:
```tsx
export interface LabelAria {
labelProps: DOMAttributes | LabelHTMLAttributes,
// ...
```
While only `{ id: string, htmlFor?: string }` is returned.
---
One approach can be to narrow down the type, to just what we know we return, but I can see how that can be undesirable, as it can make changing the API surface in the future harder.
---
Another approach can be to make the returned type depend on the optional `labelElementType` key:
https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAJQKYEMDGMA0cDecAyKARkgDYASAKgLL4CCMMUwRArjEgM5wC+cAZlAgg4AciioMogNwAoUJFi44AEQDy1BkxbsuvAUJGiAAhPQwAtDACeYLgHpOACxQSAJjNlebdgsTJ0zCgACkJgnAA8lHBIAB4cAHZu3ADWSNYQ-HBUtACipEggSAkwlCgA5gByKEXUKGAAfHAAvLJw7XDRcYnJYqT+pKJwAPy4bR0T-SSk+YXFpbZIwwBcnXITfKs44xPtU2SzRSWUi6uUmDu8cvIlSFD86Eh+04HAKFEx8cW9aRlZOfhDvMylUakg6o0xpMBqEIOFVupNIxmGwONwAD7PMgArQo3SRAFA44Vaq1eoAbUoAF0GnIeF5+KwEhhgBAEnBWJwkIRph9ut9UulMtkaICCkdSiSwRCWn0BqIGgAKMBhTirHkBIKw8JRBoASnVA1e70otK8aDZnHgeH2pG13D4zQ5XI1pEVOB4erkFoSVuUtvtq1trvt+idnO5A3dcFtRIWdlWoltQ093st1pjMNVq04YBQCRDqrDzsj02jsfFwNOYlz+ZTXtkPr9NqzcLVcDcwAAboW28WI67ywM4ycE2JO1369cm-B6AAhXL4WURW24AB0G4Dqr4OA3a+DrfCPAaKEz0zPZAi9ltZpnqgAkgA1WWKy4RCcNS4Td-d9cbie9keDTOBArCkG4cAkHAEApFeH5fh0P5drum6Hpwx4gWBEEPMApBwd2n7fvY8ENneADKwR0JUy61uyKFrrRgHoSecC0ReeGOHmCS0kAA
(Notice the change from `ElementType` to `keyof HTMLElementTagNameMap`, so we can correctly index it with `T`)
### 🖥️ Steps to Reproduce
https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wG4AoUSWOAbzgFcBnJAGRQCMkAbOAXzjZcBIuhgBaFFGAoy5cmggA7JvHrdOPAAo4wTAFxwAJsABu7Ltx0Q9-OAF5GLCzwAU6zdwCi3JCCRKMAAqAJ5gSIb4Jqb4-ACUFIoqanAaltZ6hkxgKEouVrpMdo7MbJ7uqZ4+fgHBYREE2bmxfAnySapwTUoOcAA83XQAdCPd+RlMfAB8KF05PWk8fQD03VOJyp3RvX3btCND0eOF07Pbi9wr0etAA
```tsx
function SomeComponent() {
const { fieldProps: divFieldProps, labelProps: divLabelProps } = useLabel({
label: 'This is a div label',
labelElementType: 'div',
});
const { fieldProps: spanFieldProps, labelProps: spanLabelProps } = useLabel({
label: 'This is a span label',
labelElementType: 'span',
});
return (
This is a span label
);
}
```
### Version
Latest `react-aria`.
Contributor guide
Research direction
Start from the useLabel API and reproduce the TypeScript error with the provided div and span examples. Trace the declared type of labelProps and verify that the div example passes type-check while the existing span example continues to work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- accessibility, frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100