Skip to content

Incompatible types when using MenuItem and Tanstack Router createLink with ValidateLinkOptionsΒ #9161

@uncvrd

Description

@uncvrd

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<TRouter, TOptions>;
}

const LinkItem = createLink(MenuItem);

function TestLinkItem<TRouter extends RegisteredRouter, TOptions>(
  props: WrappedLinkMenuProps<TRouter, TOptions>
): React.ReactNode;
function TestLinkItem({ linkOptions }: WrappedLinkMenuProps) {
  return <LinkItem {...linkOptions} />;
}

However I get a type error on <LinkItem> stating

Type '{ onClick?: MouseEventHandler<HTMLAnchorElement> | undefined; dir?: string | undefined; lang?: string | undefined; hidden?: boolean | undefined; ... 292 more ...; children?: ReactNode | ((state: { ...; }) => ReactNode); }' is not assignable to type 'LinkComponentReactProps<(<T extends object>(props: MenuItemProps<T> & RefAttributes<T>) => ReactElement<any, string | JSXElementConstructor<any>> | null)>'.
  Types of property 'onClick' are incompatible.
    Type 'MouseEventHandler<HTMLAnchorElement> | undefined' is not assignable to type '((e: MouseEvent<FocusableElement, MouseEvent>) => void) | undefined'.
      Type 'MouseEventHandler<HTMLAnchorElement>' is not assignable to type '(e: MouseEvent<FocusableElement, MouseEvent>) => void'.
        Types of parameters 'event' and 'e' are incompatible.
          Type 'MouseEvent<FocusableElement, MouseEvent>' is not assignable to type 'MouseEvent<HTMLAnchorElement, 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions