NodeJS 如何键入Fastify Reply有效负载?

yshpjwxd  于 2023-01-30  发布在  Node.js
关注(0)|答案(4)|浏览(171)

我刚刚进入Fastify与 typescript ,并真正享受它。
然而,我正在尝试弄清楚我是否可以输入响应负载。我有序列化工作的响应模式,这可能足够了,但我有内部类型化的对象(如IUser),最好有Typescript检查。
下面的代码很好用,但是我想返回一个TUser,如果我返回了不同的东西,我会使用typescript。

interface IUser {
    firstname: string,
    lastname: string
} // Not in use in example

interface IUserRequest extends RequestGenericInterface {
  Params: { username: string };
}

const getUserHandler = async (
  req: FastifyRequest<IUserRequest, RawServerBase, IncomingMessage | Http2ServerRequest>
) => {
  const { username } = req.params;
  return { ... }; // Would like to return instance of IUser
};

app.get<IUserRequest>('/:username', { schema }, helloWorldHandler);

是否有可以为响应扩展的RequestGenericInterface的等效接口?
小更新:看起来reply.send()可以用来添加类型,但是为了自文档化起见,最好提供更高的T。

agxfikkp

agxfikkp1#

documentation
使用这两个接口,定义一个新的API路由并将它们作为泛型传递。简写路由方法(即. get)接受一个包含五个命名属性的泛型对象RouteGenericInterface:一个月一次,一个月一次,一个月二次,一个月三次和一个月四次。
您可以使用Reply类型。

interface MiscIPAddressRes {
  ipv4: string
}
server.get<{
  Reply: MiscIPAddressRes
}>('/misc/ip-address', async (req, res) => {
  res
    .status(_200_OKAY)
    .send({
      ipv4: req.ip // this will be typechecked
  })
})
wnavrhmk

wnavrhmk2#

在查看了类型定义之后,我发现还有一种替代方法可以只对处理程序进行类型检查(如Julien TASIN的回答),如下所示:

import { FastifyReply, FastifyRequest, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from "fastify";
import { RouteGenericInterface } from "fastify/types/route";

interface IUser {
  firstname: string;
  lastname: string;
}

interface IUserRequest extends RouteGenericInterface {
  Params: { username: string };
  Reply: IUser; // put the response payload interface here
}

function getUserHandler(
  request: FastifyRequest<IUserRequest>,
  reply: FastifyReply<
    RawServerDefault,
    RawRequestDefaultExpression,
    RawReplyDefaultExpression,
    IUserRequest // put the request interface here
  >
) {
  const { username } = request.params;

  // do something

  // the send() parameter is now type-checked
  return reply.send({
    firstname: "James",
    lastname: "Bond",
  });
}

您还可以使用generic创建自己的接口,以保存编写重复行的工作,如下所示:

import { FastifyReply, FastifyRequest, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from "fastify";
import { RouteGenericInterface } from "fastify/types/route";

export interface FastifyReplyWithPayload<Payload extends RouteGenericInterface>
  extends FastifyReply<
    RawServerDefault,
    RawRequestDefaultExpression,
    RawReplyDefaultExpression,
    Payload
  > {}

然后使用如下界面:

function getUserHandler(
  request: FastifyRequest<IUserRequest>,
  reply: FastifyReplyWithPayload<IUserRequest>
) {
  const { username } = request.params;

  // do something

  // the send() parameter is also type-checked like above
  return reply.send({
    firstname: "James",
    lastname: "Bond",
  });
}
e3bfsja2

e3bfsja23#

如果只想键入处理程序,可以按以下方式执行

import { RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault, RouteHandler, RouteHandlerMethod } from "fastify";

const getUserHandler: RouteHandlerMethod<
    RawServerDefault,
    RawRequestDefaultExpression,
    RawReplyDefaultExpression,
    { Reply: IUser; Params: { username: string } }
> = async (
  req: FastifyRequest<IUserRequest, RawServerBase, IncomingMessage | Http2ServerRequest>
) => {
  const { username } = req.params;
  return { ... }; // Would like to return instance of IUser
};
tjrkku2a

tjrkku2a4#

尝试输入这些是一个真正可怕的经验。感谢其他答案,这就是我结束的地方。有点代码转储,使其他人的生活更容易。

    • 请求类型. ts**

有了这个,我将我的响应标准化为可选的datamessage

import {
    FastifyReply,
    FastifyRequest,
    RawReplyDefaultExpression,
    RawRequestDefaultExpression,
    RawServerDefault,
} from 'fastify';

type ById = {
    id: string;
};

type ApiRequest<Body = void, Params = void, Reply = void> = {
    Body: Body;
    Params: Params;
    Reply: { data?: Reply & ById; message?: string };
};

type ApiResponse<Body = void, Params = void, Reply = {}> = FastifyReply<
    RawServerDefault,
    RawRequestDefaultExpression,
    RawReplyDefaultExpression,
    ApiRequest<Body, Params, Reply>
>;

type RouteHandlerMethod<Body = void, Params = void, Reply = void> = (
    request: FastifyRequest<ApiRequest<Body, Params, Reply>>,
    response: ApiResponse<Body, Params, Reply>
) => void;

export type DeleteRequestHandler<ReplyPayload = ById> = RouteHandlerMethod<void, ById, ReplyPayload>;
export type GetRequestHandler<ReplyPayload> = RouteHandlerMethod<void, ById, ReplyPayload>;
export type PostRequestHandler<Payload, ReplyPayload> = RouteHandlerMethod<Payload, void, ReplyPayload>;
export type PatchRequestHandler<Payload, ReplyPayload> = RouteHandlerMethod<Payload, ById, ReplyPayload>;
export type PutRequestHandler<Payload, ReplyPayload> = RouteHandlerMethod<Payload, ById, ReplyPayload>;

用法

    • 获取帐户. ts**-GetRequestHandler
export const getAccount: GetRequestHandler<AccountResponseDto> = async (request, reply) => {
    const { id } = request.params;
    ...
    const account = await Account.findOne.... 
    ...
    if (account) {
        return reply.status(200).send({ data: account });
    }

    return reply.status(404).send({ message: 'Account not found' });
};
    • 删除实体. ts**-DeleteRequestHandler
export const deleteEntity: DeleteRequestHandler = async (request, reply) => {
    const { id } = request.params;
    ...
    // Indicate success by 200 and returning the id of the deleted entity
    return reply.status(200).send({ data: { id } });
};
    • 更新帐户. ts**-PatchRequestHandler
export const updateAccount: PatchRequestHandler<
    UpdateAccountRequestDto, 
    AccountResponseDto
> = async (request, reply) => {
    const { id } = request.params;
    ...
    return reply.status(200).send({ data: account });
};
    • register-account-routes. ts**-提供的处理程序没有错误。
export const registerAccountRoutes = (app: FastifyInstance) => {
    app.get(EndPoints.ACCOUNT_BY_ID, getAccount);
    app.patch(EndPoints.ACCOUNT_BY_ID, updateAccount);
    app.post(EndPoints.ACCOUNTS_AUTHENTICATE, authenticate);
    app.put(EndPoints.ACCOUNTS, createAccount);
};

相关问题