You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何及何时正确使用Handler与Handlers类型?

关于Fresh框架中Handler和Handlers类型的正确用法

基础区别

  • Handler:单函数形式的处理器,会捕获所有HTTP请求方法,适合需要统一处理所有请求类型的场景。
  • Handlers:对象形式的处理器,每个属性对应一个HTTP方法(如GET/POST/PUT),仅处理对应方法的请求,适合按请求类型拆分逻辑的场景。

类型定义参考:

export type Handler<T = any, State = Record<string, unknown>> = (
  req: Request,
  ctx: FreshContext<State, T>,
) => Response | Promise<Response>;

export type Handlers<T = any, State = Record<string, unknown>> = {
  [K in router.KnownMethod]?: Handler<T, State>;
};

泛型参数 <T, State> 的实际含义

这两个参数和处理器返回的Response类型无关,而是绑定到FreshContext的两个核心属性:

  1. T:约束ctx.data的类型,即传递给页面组件的数据类型。如果你的页面组件需要接收特定结构的数据,通过T可以让ctx.data获得类型提示,避免类型错误。
  2. State:约束ctx.state的类型,用于在中间件和处理器之间共享请求上下文状态(如用户认证信息、请求追踪ID等)。默认类型为Record<string, unknown>,可自定义更具体的结构来规范状态数据。

正确用法示例

假设页面组件需要接收{ title: string; content: string }类型的数据,同时要在ctx.state中存储用户ID:

// 定义数据类型和状态类型
type ArticleData = { title: string; content: string };
type RequestState = { userId: number };

// Handlers对象形式(仅处理GET/POST请求)
export const handler: Handlers<ArticleData, RequestState> = {
  async GET(_req, ctx) {
    // ctx.data 自动推导为 ArticleData 类型
    ctx.data = {
      title: "Fresh框架教程",
      content: "Handler和Handlers类型详解"
    };
    // ctx.state 自动推导为 RequestState 类型
    ctx.state.userId = 456;
    const resp = await ctx.render();
    resp.headers.set("X-Author-Id", ctx.state.userId.toString());
    return resp;
  },
  async POST(req, ctx) {
    // 处理POST请求逻辑
    return new Response("文章创建成功", { status: 201 });
  }
};

// Handler单函数形式(处理所有HTTP方法)
export const handler: Handler<ArticleData, RequestState> = async (req, ctx) => {
  if (req.method === "GET") {
    ctx.data = { title: "Fresh框架教程", content: "Handler和Handlers类型详解" };
    ctx.state.userId = 456;
    return ctx.render();
  } else if (req.method === "POST") {
    return new Response("文章创建成功", { status: 201 });
  }
  return new Response("方法不支持", { status: 405 });
};

关于测试代码无报错的说明

你测试的Handlers<number>代码没有报错,是因为T对应的ctx.data在处理器中未被使用,TypeScript不会强制校验未使用的泛型参数。但这种用法不符合设计意图,应该根据实际需要传递给页面组件的数据类型来设置T,才能发挥类型系统的作用。

内容的提问来源于stack exchange,提问作者Ooker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:57:34