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

如何实现基于Zod的通用Fetch函数:校验查询参数与JSON返回结果

解决Zod Schema参数的类型标注问题

你的核心问题是泛型参数缺少Zod Schema的类型约束,导致TypeScript无法识别querySchema.parse和responseSchema.parse这些方法,同时z.infer的使用方式也有误(不能用typeof TQuerySchema,因为TQuerySchema本身就是泛型类型参数,不是值类型)。

修正后的代码方案

我们需要将泛型参数约束为Zod的Schema类型,让TypeScript明确这两个参数是具备Zod校验能力的Schema对象:

import { z } from 'zod';

// 泛型约束为ZodSchema,确保参数拥有parse方法
const zodFetch = async <
  TQuerySchema extends z.ZodSchema,
  TResponseSchema extends z.ZodSchema
>(
  url: string,
  querySchema: TQuerySchema,
  query: z.infer<TQuerySchema>,
  responseSchema: TResponseSchema
): Promise<z.infer<TResponseSchema>> => {
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'content-type': 'application/json;charset=UTF-8',
    },
    body: JSON.stringify({
      query: querySchema.parse(query),
    }),
  });

  return responseSchema.parse(await response.json());
};

const test = async () => {
  const fooSchema = z.number();
  const barSchema = z.string();

  // 此时response会被正确推断为string类型
  const response = await zodFetch('https://foobar', fooSchema, 1, barSchema);
  console.log(response);
};

void test();

关键变化说明

  • 给泛型TQuerySchema和TResponseSchema添加extends z.ZodSchema约束,告诉TypeScript这两个参数必须是Zod的Schema实例,确保parse方法存在且类型安全。
  • 移除了typeof操作符,直接使用z.infer<TQuerySchema>获取Schema对应的类型,因为TQuerySchema已经是Schema类型本身,不是值的类型。
  • 调用zodFetch时,TypeScript会自动根据传入的Schema推断出query参数的类型和返回值类型,比如示例中query必须是number,返回值response是string。

另一种更简洁的写法

如果你更关注最终的类型而非Schema本身,可以直接将泛型定义为Schema对应的类型,让TypeScript自动推断Schema:

import { z } from 'zod';

const zodFetch = async <TQuery, TResponse>(
  url: string,
  querySchema: z.ZodType<TQuery>,
  query: TQuery,
  responseSchema: z.ZodType<TResponse>
): Promise<TResponse> => {
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'content-type': 'application/json;charset=UTF-8',
    },
    body: JSON.stringify({
      query: querySchema.parse(query),
    }),
  });

  return responseSchema.parse(await response.json());
};

这种写法更直观,泛型TQuery和TResponse直接对应校验后的数据类型,TypeScript会自动匹配传入的Schema是否符合该类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 06:05:19