adobe / adobe/react-spectrum

Incompatible types when using MenuItem and Tanstack Router createLink with ValidateLinkOptions

Open
#9,161 0 comments 0 reactions 0 assignees View on GitHub
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

Hi! I have run into a type incompatibility issue when using RAC `MenuItem` with Tanstack Router's `createLink` and `ValidateLinkOptions` helpers.

Tanstack Router provides helper methods to allow you to create a "wrapper" component around `MenuItem` as documented by the RAC docs using the `createLink` method. This works great

```
const LinkItem = createLink(MenuItem);
```

The issue is when I need to add additional properties to the `LinkItem`.

The Tanstack Router docs state that you can extend a `Link` type by using the `ValidateLinkOptions` here https://tanstack.com/router/latest/docs/framework/react/guide/type-utilities#type-checking-link-options-with-validatelinkoptions

So you can get link routing type safety while adding other props. I figured I could do something similar like this (taken from Router docs)

```
export interface WrappedLinkMenuProps<
TRouter extends RegisteredRouter = RegisteredRouter,
TOptions = unknown,
> {
title: string;
linkOptions: ValidateLinkOptions;
}

const LinkItem = createLink(MenuItem);

function TestLinkItem(
props: WrappedLinkMenuProps
): React.ReactNode;
function TestLinkItem({ linkOptions }: WrappedLinkMenuProps) {
return ;
}
```

However I get a type error on `` stating

```
Type '{ onClick?: MouseEventHandler | undefined; dir?: string | undefined; lang?: string | undefined; hidden?: boolean | undefined; ... 292 more ...; children?: ReactNode | ((state: { ...; }) => ReactNode); }' is not assignable to type 'LinkComponentReactProps<((props: MenuItemProps & RefAttributes) => ReactElement> | null)>'.
Types of property 'onClick' are incompatible.
Type 'MouseEventHandler | undefined' is not assignable to type '((e: MouseEvent) => void) | undefined'.
Type 'MouseEventHandler' is not assignable to type '(e: MouseEvent) => void'.
Types of parameters 'event' and 'e' are incompatible.
Type 'MouseEvent' is not assignable to type 'MouseEvent'.
Type 'FocusableElement' is missing the following properties from type 'HTMLAnchorElement': charset, coords, download, hreflang, and 143 more.
```

I had to do some searching but I think it has to do with type "Contravariance" where the parameter type from RAC of `FocusableElement` is TOO generic and when we pass in a more specific type like `HTMLAnchorElement`, typescript doesn't like this...

I struggled to determine with whom the work relies on getting this working properly (if possible) and I was curious if this was a bug or should I just deal with this?

Thanks a lot for any thoughts or insight!

### 🤔 Expected Behavior?

I expect to be able to pass props that are for HTMLAnchorElement and the RAC component should allow these props to be passed

### 😯 Current Behavior

I currently get a type error when spreading the link props on the Link component (error message above)

### 💁 Possible Solution

The only solution I can think of is to `as any` the `linkOptions` but I really wanted to avoid this

### 🔦 Context

_No response_

### 🖥️ Steps to Reproduce

https://codesandbox.io/p/devbox/2z7rds?file=%2Fapp%2Froutes%2Findex.tsx

This should open in the app -> routes -> index.tsx file where the example has been added to the top of the file (what I added in the ticket)

### Version

1.13.0

### What browsers are you seeing the problem on?

Chrome

### If other, please specify.

_No response_

### What operating system are you using?

Mac OS

### 🧢 Your Company/Team

_No response_

### 🕷 Tracking Issue

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.