eth_scanner
eth_scanner8mo ago

My TRPC hooks are getting typed as `any`

I'm using a Typescript + Express backend (Node.js, version 18), and a React Native (Typescript) frontend. For some reason by TRPC tanstack-query hooks don't seem to be typing things correctly. I am trying to understand why. I have a monorepo setup with a file structure like this: root -frontend -backend So the frontend and backend files can import from each other, and everything lives under one .git in the root. In my backend, I create a router and export the type:
const appRouter = router({
myName1: myRouter1,
myName2: myRouter2,
});

export type AppRouter = typeof appRouter;
const appRouter = router({
myName1: myRouter1,
myName2: myRouter2,
});

export type AppRouter = typeof appRouter;
Here is an example typing I get when I hover over a procedure in one of my subrouters. I don't return any in any of my procedures.
const myProcedureName: QueryProcedure<{
input: number;
output: ({
author: {
id: number;
};
} & {
myDataField: number;
})[];
}>
const myProcedureName: QueryProcedure<{
input: number;
output: ({
author: {
id: number;
};
} & {
myDataField: number;
})[];
}>
In my React Native app, I import the type:
import {createTRPCReact} from '@trpc/react-query';
import type {AppRouter} from 'my/file/path/to/backend';
export const trpc = createTRPCReact<AppRouter>();
import {createTRPCReact} from '@trpc/react-query';
import type {AppRouter} from 'my/file/path/to/backend';
export const trpc = createTRPCReact<AppRouter>();
Then in my App.tsx, I create the trpcClient:
const trpcClient = trpc.createClient({
links: [
httpBatchLink({
url: `${API_URL}/trpc`,
}),
],
});
const trpcClient = trpc.createClient({
links: [
httpBatchLink({
url: `${API_URL}/trpc`,
}),
],
});
Now when I use a hook:
// useProfile.ts
export default function useProfile(id: number) {
return trpc.user.myProcedureName.useQuery(id);
}

//MyComponent.ts
function Component() {
const {data} = useProfile(id);
// useProfile.ts
export default function useProfile(id: number) {
return trpc.user.myProcedureName.useQuery(id);
}

//MyComponent.ts
function Component() {
const {data} = useProfile(id);
My data gets typed as any, what am I doing wrong in my setup?
5 Replies
eth_scanner
eth_scannerOP8mo ago
I've managed to distill the issue even further: When I make this procedure on the backend:
const getPostsByUser = protectedProcedure
.input(z.number())
.query(async ({ input: targetId, ctx }) => {
return "HELLO" as const;
});
const getPostsByUser = protectedProcedure
.input(z.number())
.query(async ({ input: targetId, ctx }) => {
return "HELLO" as const;
});
Then my frontend hook data field gets typed correctly. But if I use a prisma query:
const getPostsByUser = protectedProcedure
.input(z.number())
.query(async ({ input: targetId, ctx }) => {
return await myPrismaQuery();
});
const getPostsByUser = protectedProcedure
.input(z.number())
.query(async ({ input: targetId, ctx }) => {
return await myPrismaQuery();
});
My frontend hook data field gets typed as any. Why is this happening? My prisma query is certainly not returning type any.
eth_scanner
eth_scannerOP8mo ago
Here is an image of the return type of my prisma query.
No description
eth_scanner
eth_scannerOP8mo ago
What's even weirder is if I cast the return type:
const record = await myPrismaQuery();
return record as number; // invalid cast
const record = await myPrismaQuery();
return record as number; // invalid cast
Then my frontend data gets typed correctly as number | undefined. But if I remove the cast, turning it into the typing as pictured above, then the frontend starts getting any.
eth_scanner
eth_scannerOP8mo ago
I got it fixed by following this four year old twitter thread: https://x.com/colinhacks/status/1298030688063561728?lang=en
Colin McDonnell (@colinhacks) on X
"nohoist" is literally not documented anywhere except in the blog post where it was introduced https://t.co/SuobFbSq4z
Twitter
eth_scanner
eth_scannerOP8mo ago
Is there a reason this isn't listed in the docs anywhere (or did I miss it?). It seems like it should be a pretty common issue given how prevalent prisma is. I get it isn't an issue with TRPC per se, but it does seem like it could have a useful place here. I'd be happy to make a docs contribution.

Did you find this page helpful?