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

TypeScript:如何在嵌套配置对象中推断Zod Schema类型?

解决方案

要让getNextStep能感知对应步骤的Schema数据类型,核心是要在类型定义中捕获每个步骤Schema的具体泛型类型,而不是笼统地用z.ZodType。下面是修改后的完整代码:

import { z } from "zod";

function createConfig<TSteps extends Record<string, { id: string; schema?: z.ZodType }>>(
  config: {
    [K in keyof TSteps]: {
      id: TSteps[K]["id"];
      // 保留原步骤的Schema定义
      schema?: TSteps[K]["schema"];
      // 根据当前步骤的Schema自动推断data类型,无Schema则为unknown
      getNextStep?: (
        data?: TSteps[K]["schema"] extends z.ZodType<infer TData> ? TData : unknown
      ) => Exclude<keyof TSteps, K> | null;
    };
  }
) {
  return config;
}

// 测试示例
const Config = createConfig({
  Step1: {
    id: "Step1",
    schema: z.object({ name: z.string() }),
    // 此时data参数会自动推断为 { name: string } | undefined
    getNextStep: (data) => {
      console.log(data?.name); // 类型提示正常
      return "Step2";
    },
  },
  Step2: {
    id: "Step2",
    schema: z.object({ enabled: z.boolean() }),
    // 添加getNextStep后,data会推断为 { enabled: boolean } | undefined
    getNextStep: (data) => {
      console.log(data?.enabled);
      return null;
    },
  },
});

关键修改说明

  1. 泛型捕获完整配置结构:
    将原有的createConfig<TKey extends string>改为createConfig<TSteps extends Record<string, { id: string; schema?: z.ZodType }>>,让TSteps自动推断整个配置对象的详细类型,包括每个步骤Schema的具体泛型参数。

  2. 条件类型提取Schema数据类型:
    在getNextStep的参数定义中,通过TSteps[K]["schema"] extends z.ZodType<infer TData> ? TData : unknown实现类型推断——如果当前步骤存在Schema,就提取其泛型参数TData作为data的类型;无Schema则 fallback 到unknown。

  3. 保留原有返回值约束:
    继续使用Exclude<keyof TSteps, K> | null确保getNextStep只能返回其他步骤的键或null,维持原有的类型校验逻辑。

原代码无法推断类型的原因

原Config<TKey>类型中,schema?: z.ZodType未指定具体泛型参数,TypeScript无法从抽象的z.ZodType中提取对应的数据类型,只能将data解析为unknown。修改后通过泛型捕获每个步骤的Schema具体类型,再用条件类型提取数据类型,即可实现自动推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:35:03