#Tanstack router looses types in loader

16 messages · Page 1 of 1 (latest)

placid prairie
#

I am developing a SPA using Tanstack router and convex.dev.

The following code works and result is properly typed inside the loader function. In my route component, when I run const data = Route.useLoaderData(); the TypeScript type is any.

Am I using the loader function wrong here? I've tried adding an explicit return type, but it still didn't work

export const Route = createFileRoute(
  "/_app/freelance/my-applications/_layout/$applicationId",
)({
  component: RouteComponent,
  loader: async ({
    context,
    params,
  }: {
    context: { queryClient: QueryClient };
    params: { applicationId: Id<"applications"> };
    }): Promise<{
      application: Application;
      job: Job;
    }> => {
    const result = await context.queryClient.ensureQueryData(
      convexQuery(api.app.applications.getApplication, {
        applicationId: params.applicationId,
      }),
    );
    if (!result?.application) {
      throw new Error(
        `Application with ID "${params.applicationId}" not found.`,
      );
    }
    return result;
  },
});

function RouteComponent() {
  const data = Route.useLoaderData();

  return (
    <div>
      <h1>Page</h1>
    </div>
  );
}
celest light
#

please provide a complete minimal example

placid prairie
#

@celest light What more do I need to show? I'm not sure how to give a better without including all of the Convex logic.

The function getApplication returns typed data and the result variable is typed.

I'm just asking how to ensure that Route.useLoaderData(); is typed

#

Is it recommended to do something like this? And manually type the Route.useLoaderData() call?

type LoaderData = {
  application: Application;
  job: Job;
};

export const Route = createFileRoute(
  "/_app/freelance/my-applications/_layout/$applicationId",
)({
  component: RouteComponent,
  loader: async ({
    context,
    params,
  }: {
    context: { queryClient: QueryClient };
    params: { applicationId: Id<"applications"> };
    }): Promise<LoaderData> => {
    const result = await context.queryClient.ensureQueryData(
      convexQuery(api.app.applications.getApplication, {
        applicationId: params.applicationId,
      }),
    );
    if (!result?.application) {
      throw new Error(
        `Application with ID "${params.applicationId}" not found.`,
      );
    }
    return result;
  },
});

function RouteComponent() {
  const data: LoaderData = Route.useLoaderData();

  return (
    <div>
      <h1>Page</h1>
    </div>
  );
}
celest light
#

a full example would be e.g. forking an existing example from stackblitz

#

something that can be debugged

#

not just some snippet

placid prairie
#

ok

#

But should Tanstack router handle the return type of Route.useLoaderData automatically? I'm not sure what's possible and there's not too much on the docs

celest light
#

yes it should

#

there must be something wrong in your setup

placid prairie
#

Ok that's good to know

placid prairie
#

@celest light

Ok. I think it might have been because I was missing this code. Is this required for some type inferance?

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}
celest light
#

absolutely

#

which is why I asked for a complete example

#

it would have shown that this was missing