TypeScript函数泛型推断问题:兼顾类型推导与返回类型精准性
TypeScript泛型推断问题的原因分析与解决方案
问题原因分析
初始代码的类型推断失效:
你定义了多层独立的泛型参数(TUnionOptions、TUnionSchema、TNewFieldInput),这些参数之间没有建立明确的关联逻辑。TypeScript无法自动关联TUnionSchema与input.validationSchema的类型,导致options.value无法正确继承validationSchema的推断类型。调整后代码的类型窄化失效:
调整后的代码将输入定义为联合类型,但未通过泛型捕获传入的具体分支类型。函数返回值的input被推断为完整的联合类型("select" | "text"),而非根据实际传入参数窄化到具体分支。
解决方案
通过将输入类型本身作为泛型参数,让TypeScript捕获传入的具体输入分支,同时直接从input.validationSchema推断options.value的类型:
import { z } from "zod"; const addInput = < TNewFieldName extends string, TInput extends | { type: "select"; label: string; validationSchema: z.ZodUnion<any>; options: { name: string; value: z.infer<TInput["validationSchema"]> }[]; } | { type: "text"; label: string; validationSchema: z.ZodString; } >(name: TNewFieldName, input: TInput) => { return { name, input }; }; // 测试select类型 const currencyUnionSchema = z.union([z.literal("USD"), z.literal("AUD")]); const selectResult = addInput("someName", { type: "select", label: "Currency", validationSchema: currencyUnionSchema, options: [ { name: "America", value: "USD" }, { name: "Australia", value: "AUD" } // { name: "Test", value: "US" } // 此处会触发类型错误,符合预期 ] }); selectResult.input.type; // 类型为 "select",精准推断 // 测试text类型 const textResult = addInput("username", { type: "text", label: "Username", validationSchema: z.string().min(3) }); textResult.input.type; // 类型为 "text",精准推断
方案说明
- 泛型捕获具体输入类型:
TInput泛型参数会自动捕获传入的具体输入分支(select或text),确保返回值的input.type被窄化到对应的字面量类型。 - 关联
options.value与validationSchema:使用z.infer<TInput["validationSchema"]>直接从input.validationSchema中推断value的类型,消除了泛型参数之间的歧义。
内容的提问来源于stack exchange,提问作者Reuben Drummond
相关产品推荐
相关产品推荐

