I'm trying to build a REST API using Fastify and I'm facing this TypeScript error:
Type '(request: FastifyRequest<{ Body: IGenerateQRCode;}>, reply: FastifyReply) => Promise<never>' is not assignable to type 'RouteHandlerMethod<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown, FastifySchema, FastifyTypeProviderDefault, unknown, ResolveFastifyRequestType<...>, FastifyLoggerInstance>'.
Types of parameters 'request' and 'request' are incompatible.
Type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, FastifySchema, FastifyTypeProviderDefault, unknown, ResolveFastifyRequestType<...>, FastifyLoggerInstance>' is not assignable to type 'FastifyRequest<{ Body: IGenerateQRCode; }, Server, IncomingMessage, FastifySchema, FastifyTypeProviderDefault, unknown, ResolveFastifyRequestType<...>, FastifyLoggerInstance>'.
Type 'RouteGenericInterface' is not assignable to type '{ Body: IGenerateQRCode; }'.
Types of property 'Body' are incompatible.
Type 'unknown' is not assignable to type 'IGenerateQRCode'.ts(2322)
route.d.ts(140, 3): The expected type comes from property 'handler' which is declared here on type 'RouteOptions<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown, FastifySchema, FastifyTypeProviderDefault, unknown, ResolveFastifyRequestType<...>, FastifyLoggerInstance>'
The error when I add in the handler for the generateQrCode
route:
import { RouteOptions } from "fastify";
import pingServer from "../controllers/pingServer";
import generateQRCode from "../controllers/generateQrCode";
const ping: RouteOptions = {
method: "GET",
url: "/ping",
handler: pingServer,
};
const generateQrCode: RouteOptions = {
method: "POST",
url: "/generate",
handler: generateQRCode,
};
const routes = [ping];
export default routes;
The code for that route controller is:
import { FastifyRequest, FastifyReply } from "fastify";
import { encodeURL, TransactionRequestURLFields } from "@solana/pay";
import { nanoid } from "nanoid";
import QrCodes from "../models/qrCodes";
import Users from "../models/users";
import { networks, rpcUrls } from "../constants/constants";
import { IGenerateQRCode } from "../types/IGenerateQRCode";
const generateQRCode = async (
request: FastifyRequest<{
Body: IGenerateQRCode;
}>,
reply: FastifyReply
) => {
if (!networks.includes(request.body.network)) {
return reply.status(400).send({
error: "Invalid network. ",
});
}
const qrCodeId = nanoid();
const user = await Users.findOne({
apiKey: request.headers.authorization,
});
const transactionRequestURLFields: TransactionRequestURLFields = {
link: new URL(
`https://${process.env.RAILWAY_STATIC_URL}/api/v1/mint?id=${qrCodeId}`
),
label: request.body.label,
message: request.body.message,
};
const solanaUrl = encodeURL(transactionRequestURLFields);
try {
const qrCode = new QrCodes({
qrCodeId,
candyMachineId: request.body.candyMachineId,
user,
network: request.body.network || "mainnet",
rpcUrl: request.body.rpcUrl || rpcUrls.get(request.body.network),
label: request.body.label || "Made with <3 by CandyPay",
icon:
request.body.icon ||
"https://www.downloadclipart.net/large/candy-png-free-download.png",
});
await qrCode.save();
return reply.status(200).send({
qrCodeId,
solanaUrl,
});
} catch (err) {
console.log(err);
return reply.status(500).send({
message: "Internal server error",
error: err,
});
}
};
export default generateQRCode;
The interface which I have used in the code of that route's controller:
export interface IGenerateQRCode {
candyMachineId: string;
network: string;
rpcUrl: string;
label: string;
icon: string;
message: string;
}
I am pretty sure it is the issue with the generics but I am unable to solve it
CodePudding user response:
If you change the RouteOptions
type to include the generics as follows, the error is gone:
import { IncomingMessage, Server, ServerResponse } from "http";
const generateQrCode: RouteOptions<Server, IncomingMessage, ServerResponse, { Body: IGenerateQRCode; }> = {
method: "POST",
url: "/generate",
handler: generateQRCode,
};
This works because the type containing the body definition should be assigned to the RouteGeneric
generic.