Losing the type between the client and server

Hello everyone, I am new to tRPC and the magic of types in typescript so I am looking for ideas as to what is happening, the client is receiving any type instead of a string
volks
volks586d ago
I doubt this is a bug, but I have no idea where to go for. This is on the client
(property) onSuccess?: ((data: {
id: any;
exists: any;
name: any;
email: string;
}, variables: {
provider?: any;
presignupEmail?: string | undefined;
email: string;
userID: string;
}, context: unknown) => unknown) | undefined
(property) onSuccess?: ((data: {
id: any;
exists: any;
name: any;
email: string;
}, variables: {
provider?: any;
presignupEmail?: string | undefined;
email: string;
userID: string;
}, context: unknown) => unknown) | undefined
And this is on the server
(method) ProcedureBuilder<{ _config: RootConfig<{ ctx: { user?: undefined; } | { user: { uid: string; email: string; }; }; meta: {}; errorShape: DefaultErrorShape; transformer: CombinedDataTransformer; }>; ... 5 more ...; _output_out: typeof unsetMarker; }>.mutation<{
id: string;
exists: boolean;
name: string | undefined;
email: string;
}>(resolver: (opts: ResolveOptions<{
_config: RootConfig<{
ctx: {
user?: undefined;
} | {
user: {
uid: string;
email: string;
};
};
meta: {};
errorShape: DefaultErrorShape;
transformer: CombinedDataTransformer;
}>;
... 5 more ...;
_output_out: typeof unsetMarker;
}>) => MaybePromise<...>): BuildProcedure<...>
Mutation procedure
(method) ProcedureBuilder<{ _config: RootConfig<{ ctx: { user?: undefined; } | { user: { uid: string; email: string; }; }; meta: {}; errorShape: DefaultErrorShape; transformer: CombinedDataTransformer; }>; ... 5 more ...; _output_out: typeof unsetMarker; }>.mutation<{
id: string;
exists: boolean;
name: string | undefined;
email: string;
}>(resolver: (opts: ResolveOptions<{
_config: RootConfig<{
ctx: {
user?: undefined;
} | {
user: {
uid: string;
email: string;
};
};
meta: {};
errorShape: DefaultErrorShape;
transformer: CombinedDataTransformer;
}>;
... 5 more ...;
_output_out: typeof unsetMarker;
}>) => MaybePromise<...>): BuildProcedure<...>
Mutation procedure
julius
julius585d ago
Do you have strict mode? Are you using any data transformers?
volks
volks584d ago
Hey @julius, I am using strict mode and I am using superjson. I am currently debugging on a reproducable repo first, but with a stripped down setup the types are working, so I am super confused at the moment Do you maybe have any pointers at the top of your head that can break types between projects. I basically have a monorepo
apps/
- backend with trpc that exports app router
- nextjs site that imports the app router
apps/
- backend with trpc that exports app router
- nextjs site that imports the app router
I just import the type from ../apps/backend/src/trpc.ts I'll keep debugging and close this if I find the culprit
julius
julius583d ago
Not really, is the repo public?
volks
volks580d ago
I have a minimal repository that closely mimics my real project which is unfortunately commercial and private, but I cannot for the life of me replicate the issue I am having in the real project @julius For example
export const sessionContext = async ({
req,
}: NodeHTTPCreateContextFnOptions<IncomingMessage, ServerResponse>) => {
try {
if (
req.headers.authorization &&
req.headers.authorization.split(" ")[0] === "Bearer"
) {
const token = req.headers.authorization.split(" ")[1] as string;
const decodedToken = await firebaseAdmin.auth().verifyIdToken(token);

if (!decodedToken.email) {
return {};
}

return {
user: {
uid: decodedToken.uid,
email: decodedToken.email,
},
};
}
return {};
} catch (error) {
return {};
}
};

export type Context = inferAsyncReturnType<typeof sessionContext>;
export const sessionContext = async ({
req,
}: NodeHTTPCreateContextFnOptions<IncomingMessage, ServerResponse>) => {
try {
if (
req.headers.authorization &&
req.headers.authorization.split(" ")[0] === "Bearer"
) {
const token = req.headers.authorization.split(" ")[1] as string;
const decodedToken = await firebaseAdmin.auth().verifyIdToken(token);

if (!decodedToken.email) {
return {};
}

return {
user: {
uid: decodedToken.uid,
email: decodedToken.email,
},
};
}
return {};
} catch (error) {
return {};
}
};

export type Context = inferAsyncReturnType<typeof sessionContext>;
In my main project it has any types like displayed bellow but in my demo project it correctly has the uid and email as strings
(alias) type AppRouter = Router<RouterDef<RootConfig<{
ctx: {
user?: undefined;
} | {
user: {
uid: any;
email: any;
};
};
}>, {
...;
}, {
...;
}>> & {
...;
}
(alias) type AppRouter = Router<RouterDef<RootConfig<{
ctx: {
user?: undefined;
} | {
user: {
uid: any;
email: any;
};
};
}>, {
...;
}, {
...;
}>> & {
...;
}
So I thought that the types might be incorrect all together but if I do
export const sessionContext = async ({
req,
}: NodeHTTPCreateContextFnOptions<IncomingMessage, ServerResponse>) => {
return {
user: {
uid: "test",
email: "test",
},
};
};

export type Context = inferAsyncReturnType<typeof sessionContext>;
export const sessionContext = async ({
req,
}: NodeHTTPCreateContextFnOptions<IncomingMessage, ServerResponse>) => {
return {
user: {
uid: "test",
email: "test",
},
};
};

export type Context = inferAsyncReturnType<typeof sessionContext>;
It gets inferred to
(alias) type AppRouter = Router<RouterDef<RootConfig<{
ctx: {
user: {
uid: string;
email: string;
};
};
}
(alias) type AppRouter = Router<RouterDef<RootConfig<{
ctx: {
user: {
uid: string;
email: string;
};
};
}
The type is correct on the server but gets inferred to any in the client But as you can see the types do get across Just some are any I have absolutely no clue as to what is happening Also the inferred type of my mutation has the same issue
type test = {
id: any;
exists: any;
name: any;
email: string;
}
type test = {
id: any;
exists: any;
name: any;
email: string;
}
But on the server the types are all okay
(method) ProcedureBuilder<{ _config: RootConfig<{ ctx: { user?: undefined; } | { user: { uid: string; email: string; }; }; meta: {}; errorShape: DefaultErrorShape; transformer: CombinedDataTransformer; }>; ... 5 more ...; _output_out: typeof unsetMarker; }>.mutation<{
id: string;
exists: boolean;
name: string | undefined;
email: string;
}>(resolver: (opts: ResolveOptions<{
(method) ProcedureBuilder<{ _config: RootConfig<{ ctx: { user?: undefined; } | { user: { uid: string; email: string; }; }; meta: {}; errorShape: DefaultErrorShape; transformer: CombinedDataTransformer; }>; ... 5 more ...; _output_out: typeof unsetMarker; }>.mutation<{
id: string;
exists: boolean;
name: string | undefined;
email: string;
}>(resolver: (opts: ResolveOptions<{
julius
julius580d ago
might be invalid tsconfig? or do you use the same in the repro?
volks
volks580d ago
Both are the same, strict mode is on But the types are getting through to the client, just for some reason some types are lost and inferred to any Thats why I am super confused
julius
julius579d ago
yea if you cant provide a repro i really cant help you since ive never seen this before
volks
volks579d ago
Yeah I'll try to get it reproduced and push it to gh
volks
volks577d ago
Hey @julius, tried my best to create a simple reproducible repository that reflects my issue. I added a readme that clarifies the issue further, here is the repo https://github.com/Nikola-Milovic/monorepo-trpc-issue I know this is a tall ask to check out but thank you nonetheless
GitHub
GitHub - Nikola-Milovic/monorepo-trpc-issue
Contribute to Nikola-Milovic/monorepo-trpc-issue development by creating an account on GitHub.
volks
volks577d ago
Inside packages/config are the tsconfig files and they all inherit from the base.json which defines the strict: true
More Posts
Mobile app with tRPCWhat's the suggested way of working with tRPC when it comes to mobile apps? How do you ensure that yHow to use trpc react hooks from an external data sourceHi, I have a monorepo, nextjs and keystone cms. The cms has trpc running, and I managed to get it coNextJS & Keystone CMS, issues when connecting both in a monorepoHello everyone, so I have a monorepo with NextJS and keystone cms, both are running trpc v10beta.15Best practices for implementing an offline applicationHey there! I'm building a full stack react-native app with Expo and a tRPC backend. I'd like for thisomehow when move typed function out of the router files, frontend infer type to be any ?this is inferred corrected since they are in the same file. ``` getX: t.procedure.query(() => { retBig companies that use tRPC?Some of my fellow colleagues were wondering if there are any big companies that use tRPC and how matSSG on nextJS when appRouter is made with fastify adapter?```js export const getStaticProps: GetStaticProps = async () => { const ssg = await createSSGHelpeMigrating to V10 from V9If someone has some ideas on what I might have screwed up when trying to bump tRPC for this public sAuthentication broke after bump to v10 from v9Anyone that has any suggestions on what might have caused this? I get the following error when tryiShow a spinner when any mutation is loading?Looking to show an activity spinner in the header of our application whenever a mutation is in flighSharing schemas between server and clientIn a typical nextJs setup, what is the idiomatic way to share zod schemas between frontend and backev10 Migration interop, router doesnt have attributesHi, i've tried to migrate like stated in the docs, these are my routers. Question: Shouldn't appRoutRecommended file structure for next.js?Hey all - using tRPC heavily with next.js and it's great. Our main `[trpc].ts` file is getting huge Unhandled Runtime ErrorTRPCClientErrorCall Stack Function.from node_modules\@trpc\client\dist\TRPCClientError-09b8a26b.esm.js (57:0) transWeird error when running unit test`10.0.0-proxy-beta.5` works just fine, error occurs on `10.0.0-proxy-beta.6` with the introduction oSharing middleware between TRPC serversWe currently have *microservices* REST API's on Cloudflare Workers and I'm thinking about moving thiIs `trpc.withTRPC` for Next supposed to work with pages or only `_app`?I'd love to only have TRPC mount on certain pages of my Next.js app. Is this currently supported?What does the WebSocketHandler do?I'm not sure what this is doing on the background.Are there any example of subscriptions working with react native ?queries and mutations are working pretty well with react native, I'm unable however to get subscriptRecommended way to prefetch client-sideIn react-query, you can do ``` queryClient.prefetchQuery(['todos', input], queryFn) ``` In trpc, I