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

TypeScript泛型自定义路由创建函数类型兼容问题求助

问题分析与解决方案

错误原因

你遇到的类型不匹配问题由两个核心原因导致:

1. Response 类型签名不匹配

你的 Response 类型定义只接受 data 单个参数:

export type Response<Data = unknown> = (data: Data) => RouteResponse<Data>;

但 Route.Response 静态方法返回的函数包含可选的 errors 参数:

static Response<Data = unknown>() {
  return (data: Data, errors?: RouteResponseError[]) => {
    return new RouteResponse(data, errors);
  };
}

两者签名不一致,导致TypeScript认为返回的函数不符合 Response 类型。

2. 泛型约束与类型推断限制

createRoutes 的泛型约束使用了 RouteData<HttpMethod> 的默认 Responses 类型(Record<PropertyKey, Response<unknown>>),而函数参数逆变的特性导致:

  • Response<{ success: true }> 要求传入 { success: true } 类型的参数
  • Response<unknown> 可以接受任意类型的参数
  • 逆变规则下,更具体的函数类型(Response<{ success: true }>)无法赋值给更宽泛的函数类型(Response<unknown>)

同时,createRoutes 返回类型的定义错误地将所有路由的 Method 和 Responses 合并为联合类型,而非每个路由对应各自的具体类型。


解决方法

步骤1:修正 Response 类型签名

更新 Response 类型,加入可选的 errors 参数,使其与 Route.Response 返回的函数签名一致:

export type Response<Data = unknown> = (data: Data, errors?: RouteResponseError[]) => RouteResponse<Data>;

步骤2:调整泛型定义以支持精确类型推断

修改 RouteData 的泛型定义,去掉 Responses 的默认值,确保它能捕获具体的响应类型:

interface RouteData<
  Method extends HttpMethod,
  Responses extends Record<PropertyKey, Response>
> {
  Method: Method;
  Path: string;
  Headers?: z.ZodSchema;
  Query?: z.ZodSchema;
  Body?: Method extends 'GET' | 'DELETE' ? never : z.ZodSchema;
  Responses: Responses;
}

步骤3:修复 createRoutes 的返回类型

使用映射类型确保每个路由键对应正确的 Route 类型,而非合并为联合类型:

export const createRoutes = <
  RoutesData extends Record<PropertyKey, RouteData<HttpMethod, any>>
>(
  routesData: RoutesData
) => {
  const routes = {} as {
    [K in keyof RoutesData]: Route<RoutesData[K]['Method'], RoutesData[K]['Responses']>
  };

  for (const key in routesData) {
    routes[key] = new Route(routesData[key]);
  }

  return routes;
};

可选优化:调整 Route 类的泛型默认值

如果需要保留默认的响应类型,可以更新 Route 类的泛型定义:

export class Route<
  Method extends HttpMethod,
  Responses extends Record<PropertyKey, Response> = Record<PropertyKey, Response<unknown>>
> {
  // ... 原有构造函数和属性定义不变
}

验证修改后的代码

调整后的代码可以正确推断 AuthRoutes 的类型,Success 响应的类型会被正确识别为 Response<{ success: true }>,不再抛出类型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:05:56