-
-
Notifications
You must be signed in to change notification settings - Fork 8
Description
Question
After being inspired by this template and liking how the routes are organized, I tried to implement the following routing structure.
export interface IRouter {
path: string;
getRoutes: (fastify: FastifyInstance, options: RouteOptions) => Promise<void>;
}It's used to implement "routers" containing multiple route like so:
import { FastifyInstance as Instance, RouteOptions as Options } from "fastify";
import { FastifyRequest as Request, FastifyReply as Reply } from "fastify";
import type { IRouter } from "../types.js";
export class GreetRouter implements IRouter {
public path = "/greet";
public async getRoutes(fastify: Instance, options: Options) {
fastify.post(this.path, async function (request: Request<{ Body: { name: string } }>, reply: Reply) {
const { name } = request.body;
const message = `Hello ${name}`;
return reply.send({ message });
});
}
}That interface allows me to define implementations, which contain multiple routes defined with a shorthand such as fastify.post and fastify.get and later collect them and register them all at once, with options such as the prefix.
import { FastifyInstance as Instance, FastifyPluginOptions as Options } from "fastify";
import fp from "fastify-plugin";
import { IndexRouter } from "./routers/index.js";
import { GreetRouter } from "./routers/greet.js";
import type { IRouter } from "./types.js";
const routes = fp(async (fastify: Instance, options: Options) => {
const routers: Array<IRouter> = [new IndexRouter(), new GreetRouter()];
routers.forEach((router: IRouter) => {
fastify.log.info(`registering router for ${router.path}`);
fastify.register(router.getRoutes.bind(router), { prefix: "/api/v1" });
});
});
export default routes;All the code in the MRE runs perfectly fine in watch mode when using bun run dev
However, when attempting to build the project with tsc I get the following
Error log when transpiling the project with tsc
$ tsc --build .
src/router.ts:21:22 - error TS2769: No overload matches this call.
Overload 1 of 6, '(plugin: FastifyPluginCallback): FastifyInstance<...> & ... 1 more ... & { ...; }', gave the following error.
Argument of type '(fastify: FastifyInstance, FastifyBaseLogger, FastifyTypeProviderDefault>, options: RouteOptions<...>) => Promise<...>' is not assignable to parameter of type 'FastifyPluginCallback'.
Types of parameters 'options' and 'opts' are incompatible.
Type 'FastifyPluginOptions' is missing the following properties from type 'RouteOptions, RouteGenericInterface, unknown, FastifySchema, FastifyTypeProviderDefault, FastifyBaseLogger>': method, url, handler
Overload 2 of 6, '(plugin: FastifyPluginAsync): FastifyInstance<...> & ... 1 more ... & { ...; }', gave the following error.
Argument of type '(fastify: FastifyInstance, FastifyBaseLogger, FastifyTypeProviderDefault>, options: RouteOptions<...>) => Promise<...>' is not assignable to parameter of type 'FastifyPluginAsync'.
Types of parameters 'options' and 'opts' are incompatible.
Type 'FastifyPluginOptions' is missing the following properties from type 'RouteOptions, RouteGenericInterface, unknown, FastifySchema, FastifyTypeProviderDefault, FastifyBaseLogger>': method, url, handler
Overload 3 of 6, '(plugin: FastifyPluginCallback | FastifyPluginAsync<...> | Promise<...> | Promise<...>): FastifyInstance<...> & ... 1 more ... & { ...; }', gave the following error.
Argument of type '(fastify: FastifyInstance, FastifyBaseLogger, FastifyTypeProviderDefault>, options: RouteOptions<...>) => Promise<...>' is not assignable to parameter of type 'FastifyPluginCallback | FastifyPluginAsync<...> | Promise<...> | Promise<...>'.
Type '(fastify: FastifyInstance, FastifyBaseLogger, FastifyTypeProviderDefault>, options: RouteOptions<...>) => Promise<...>' is not assignable to type 'FastifyPluginCallback'.
Types of parameters 'options' and 'opts' are incompatible.
Type 'FastifyPluginOptions' is missing the following properties from type 'RouteOptions, RouteGenericInterface, unknown, FastifySchema, FastifyTypeProviderDefault, FastifyBaseLogger>': method, url, handler
21 fastify.register(router.getRoutes.bind(router));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To my understanding, I'm providing the correct signature when registering the route, but according to this error, RouteOptions and FastifyPluginOptions are incompatible (which I'm not arguing against).
I don't exactly know how to merge or make these types overlap to make this work even when building and I don't really want to cast the plugin callback to any. I'd love to know where have I gone wrong with types.
MRE
note that in the MRE the { prefix: "/api/v1" } was not added to the options, but the error remains the same.
available here: https://github.com/ClayCore/fastify-type-error
Your Environment
- node version: 24.6.0
- bun version: 1.2.19
- fastify version: ^5.5.0
- typescript version: ^5
- os: Linux CachyOS (6.16.3-2-cachyos)