Open tmax22 opened 2 months ago
It's not the size; using a very very large props type as the base doesn't reproduce the problem
type BaseProps = Record<`${'a' | 'b' | 'c' | 'd'}${'a' | 'b' | 'c' | 'd'}${'a' | 'b' | 'c' | 'd'}${'a' | 'b' | 'c' | 'd'}${'a' | 'b' | 'c' | 'd'}`, string>;
const Link = <T extends React.ElementType>(
props: WithComponentOverride<BaseProps, T>
) => {
const Component = props.component; // ok
return <Component {...props} />;
};
Need to figure out what's weird about TanstackLinkProps
but it's a tangled web
Marking off some progress here...
import React from 'react';
import { RouteByPath, } from "@tanstack/react-router";
import { AnyRoute } from "@tanstack/react-router";
export type CheckPath<TRouteTree extends AnyRoute> =
RouteByPath<TRouteTree, `${string}/`> extends never ? { to: string } : {};
export type ActiveLinkOptions<TRouteTree extends AnyRoute> = {
to: string;
} & CheckPath<TRouteTree>;
export type WithComponentOverride<P, T extends React.ElementType> = P & InferProps<T> & {
component: T;
};
export type InferProps<T extends React.ElementType> =
T extends React.ComponentType<infer P> ? P : {};
declare const Link2: LinkComponent;
type Orig_TanstackLinkProps = Parameters<typeof Link2>[0];
const Link = <T extends React.ElementType>(
props: WithComponentOverride<Orig_TanstackLinkProps, T>
) => {
const p: keyof typeof props = 'component';
const Component = props.component; // TS2339: Property component does not exist on type <...blabla...>
// ...
return <Component {...props} />;
};
export type LinkComponent = <TRouteTree extends AnyRoute>(props: ActiveLinkOptions<TRouteTree>) => React.ReactElement;
I've gotten this far but we need to cut our losses trying to reduce Route
and its twenty-one type parameters down to something that can be investigated.
import { Route } from '@tanstack/react-router';
import React from 'react';
export interface AnyRoute extends Route<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any> {
}
export type ParseRoute<TRouteTree, TAcc = TRouteTree> = TRouteTree extends {
types: {
children: infer TChildren;
};
} ? TChildren extends Array<unknown> ? ParseRoute<TChildren[number], TAcc | TChildren[number]> : TAcc : TAcc;
export type RoutesByPath<TRouteTree extends AnyRoute> = {
[K in ParseRoute<TRouteTree> as K['fullPath']]: K;
} & Record<'.' | '..', ParseRoute<TRouteTree>>;
export type RouteByPath<TRouteTree extends AnyRoute, TPath> = (string extends TPath ? ParseRoute<TRouteTree> : RoutesByPath<TRouteTree>[TPath]);
export type CheckPath<TRouteTree extends AnyRoute> =
RouteByPath<TRouteTree, `${string}/`> extends never ? { to: string } : {};
export type ActiveLinkOptions<TRouteTree extends AnyRoute> = {
to: string;
} & CheckPath<TRouteTree>;
export type WithComponentOverride<P, T extends React.ElementType> = P & InferProps<T> & {
component: T;
};
export type InferProps<T extends React.ElementType> =
T extends React.ComponentType<infer P> ? P : {};
declare const Link2: LinkComponent;
type Orig_TanstackLinkProps = Parameters<typeof Link2>[0];
const Link = <T extends React.ElementType>(
props: WithComponentOverride<Orig_TanstackLinkProps, T>
) => {
const p: keyof typeof props = 'component';
const Component = props.component; // TS2339: Property component does not exist on type <...blabla...>
// ...
return <Component {...props} />;
};
export type LinkComponent = <TRouteTree extends AnyRoute>(props: ActiveLinkOptions<TRouteTree>) => React.ReactElement;
We need someone to provide a minimal self-contained repro here; the tanstack types are beyond comprehension.
🔎 Search Terms
TypeScript Error only on big type only when assigned to a variable
🕗 Version & Regression Information
typescript v5.4.5
⏯ Playground Link
https://stackblitz.com/edit/vitejs-vite-mcran5?file=src%2FLink.tsx
💻 Code
copy paste from https://stackoverflow.com/questions/78252365/typescript-error-only-on-big-type-only-when-assigned-to-a-variable
🙁 Actual behavior
even after many years of writing typescript you sometimes get unexpected results:
assume generic type function
WithComponentOverride
whose purpose is accepting component props and another generic parameter which tells which ComponentType the component is:and usage:
now other components can use
MyComponent
and decide which Host element the root of the component would be in typesafe way:works perfectly.
now let's try to apply this generic type to a much more complicated type, taken from the component from
@tanstack/react-router
we get
TS2339
error even though we shouldn't get one.we can even see
{ component: T; }
right there in the type:what is even stranger is that when accessing the type directly(and not via assigned variable) works as expected:
WHAT'S GOING ON? I genuinely think that is a typescript bug here, but I can't tell for sure.
for the curious, here is the full typescript error:
the only difference between
TanstackLinkProps
andMyComponentProps
is the size of the type.WithComponentOverride
should act the same on both of them.Dont belive me? heres a demo
🙂 Expected behavior
.
Additional information about the issue
No response