DangerZone
DangerZone
TtRPC
Created by DangerZone on 4/2/2023 in #❓-help
How can I generate trpc Generic Types?
@Nick Lucas Yes, I am building an implementation for trpc in nestjs, a full opinionated one, for example here is how you'll define a route:
import { Inject } from '@nestjs/common';
import { Router, Query, Mutation } from 'nestjs-trpc';
import { z } from 'zod';
import { UserService } from './user.service';

@Router()
export class UserRouter {
constructor(@Inject(UserService) private readonly userService: UserService) {}

@Query({ output: z.string() })
authors() {
return this.userService.test();
}

@Mutation({ input: z.string(), output: z.string() })
createAuthor(input: string) {
return input;
}
}
import { Inject } from '@nestjs/common';
import { Router, Query, Mutation } from 'nestjs-trpc';
import { z } from 'zod';
import { UserService } from './user.service';

@Router()
export class UserRouter {
constructor(@Inject(UserService) private readonly userService: UserService) {}

@Query({ output: z.string() })
authors() {
return this.userService.test();
}

@Mutation({ input: z.string(), output: z.string() })
createAuthor(input: string) {
return input;
}
}
I have managed to get it all to work, but it is littered with any types since trpc doesn't really give us actual types, for example, if I want the Router() decorator to be able to accept meta, I don't really have a way to type it since its typed dynamically. Here is an example of how I generate the routers:
generateRoutes(
router,
mergeRoutes: MergeRouters<any>,
publicProcedure: ProcedureBuilder<any>,
): MergeRouters<any> {
const routers = this.getRouters();
console.log(routers);
const routerSchema = routers.map((route) => {
const { instance } = route;
const prototype = Object.getPrototypeOf(instance);
const procedures = this.getProcedures(instance, prototype);

const producersSchema = procedures.reduce((obj, procedure) => {
const { name, input, output, type } = procedure;
// Call the method on the instance with proper dependency injection handling
const instanceMethodImplementation = ({ input }) =>
instance[name](input);

let procedureSchema =
input != null ? publicProcedure.input(input) : publicProcedure;

procedureSchema =
output != null ? procedureSchema.output(output) : procedureSchema;

procedureSchema =
type === Procedure.Query
? procedureSchema.query(instanceMethodImplementation)
: (procedureSchema.mutation(instanceMethodImplementation) as any);

obj[name] = procedureSchema;
return obj;
}, {});

return router(producersSchema);
});

return mergeRoutes(...routerSchema);
}
}
generateRoutes(
router,
mergeRoutes: MergeRouters<any>,
publicProcedure: ProcedureBuilder<any>,
): MergeRouters<any> {
const routers = this.getRouters();
console.log(routers);
const routerSchema = routers.map((route) => {
const { instance } = route;
const prototype = Object.getPrototypeOf(instance);
const procedures = this.getProcedures(instance, prototype);

const producersSchema = procedures.reduce((obj, procedure) => {
const { name, input, output, type } = procedure;
// Call the method on the instance with proper dependency injection handling
const instanceMethodImplementation = ({ input }) =>
instance[name](input);

let procedureSchema =
input != null ? publicProcedure.input(input) : publicProcedure;

procedureSchema =
output != null ? procedureSchema.output(output) : procedureSchema;

procedureSchema =
type === Procedure.Query
? procedureSchema.query(instanceMethodImplementation)
: (procedureSchema.mutation(instanceMethodImplementation) as any);

obj[name] = procedureSchema;
return obj;
}, {});

return router(producersSchema);
});

return mergeRoutes(...routerSchema);
}
}
as you can see, it is really difficult to actually use types here, and I am forced to use any for most of the parts in this function, I would love to just pass t and use it throughout the function but t doesn't really lends itself with a generic type that I can actually use. And yes, I know I will lose the compile time benefits of trpc, but as you can see by my answer here: https://github.com/macstr1k3r/trpc-nestjs-adapter/issues/1#issuecomment-1483129949 The best solution for integrating trpc with nestjs is taking the @nestjs/graphql approach and generating the schema in build-time.
4 replies