Skip to content

fix(react-router): fix custom link type ref inference #4121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

CynicalBusiness
Copy link

@CynicalBusiness CynicalBusiness commented May 9, 2025

Custom links created by createLink would incorrectly infer ref values for non-intrinsic components (such as those with their own ref prop like the documented example), which would result in the ref being "double-wrapped". That is:

Before:

{
  // Effective LinkComponentReactProps<TComp>
  // ...
  ref?: React.Ref<React.Ref<HTMLAnchorElement> | undefined> | undefined
  // notice the ref has been "ref'ed" twice
}

After fix:

{
  // Effective LinkComponentReactProps<TComp>
  // ...
  ref?: React.Ref<HTMLAnchorElement> | undefined>
}

This patch, the equivilant applied directly to link.d.ts via yarn patch, has been our workaround and it appears to work well:

@tanstack-react-router-npm-1.120.3-f6c72d7c75.patch
diff --git a/dist/esm/link.d.ts b/dist/esm/link.d.ts
index f7a4dfc2678f3669ee48b97c22e4c69d2f3ff195..be0adda3bf4302466c3c4b4d73ff6c78474a237f 100644
--- a/dist/esm/link.d.ts
+++ b/dist/esm/link.d.ts
@@ -4,9 +4,9 @@ import { ValidateLinkOptions, ValidateLinkOptionsArray } from './typePrimitives.
 import * as React from 'react';
 export declare function useLinkProps<TRouter extends AnyRouter = RegisteredRouter, const TFrom extends string = string, const TTo extends string | undefined = undefined, const TMaskFrom extends string = TFrom, const TMaskTo extends string = ''>(options: UseLinkPropsOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>, forwardedRef?: React.ForwardedRef<Element>): React.ComponentPropsWithRef<'a'>;
 type UseLinkReactProps<TComp> = TComp extends keyof React.JSX.IntrinsicElements ? React.JSX.IntrinsicElements[TComp] : React.PropsWithoutRef<TComp extends React.ComponentType<infer TProps> ? TProps : never> & React.RefAttributes<TComp extends React.FC<{
-    ref: infer TRef;
+    ref: React.Ref<infer TRef>;
 }> | React.Component<{
-    ref: infer TRef;
+    ref: React.Ref<infer TRef>;
 }> ? TRef : never>;
 export type UseLinkPropsOptions<TRouter extends AnyRouter = RegisteredRouter, TFrom extends RoutePaths<TRouter['routeTree']> | string = string, TTo extends string | undefined = '.', TMaskFrom extends RoutePaths<TRouter['routeTree']> | string = TFrom, TMaskTo extends string = '.'> = ActiveLinkOptions<'a', TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & UseLinkReactProps<'a'>;
 export type ActiveLinkOptions<TComp = 'a', TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = '.', TMaskFrom extends string = TFrom, TMaskTo extends string = '.'> = LinkOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & ActiveLinkOptionProps<TComp>;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant