TypeScript:Zod Schema验证下泛型函数返回类型推断异常
解决Zod Schema验证中函数返回类型推断为any的问题
你的问题核心在于原函数的泛型推导逻辑存在缺陷:selectFormFactorDevice的泛型T依赖FormFactorDevice<T>的返回类型,但TypeScript无法从传入的formFactorDevice反向推导出T,最终导致z.infer<T>被推断为any。
修改方案一:直接定义字段类型结构
先抽离FormFactorDevice的类型结构,让函数泛型直接对应字段的实际类型,TypeScript就能自动完成推导:
import { z } from 'zod'; export const FormFactorDevice = <T extends z.ZodTypeAny>(fieldSchema: T) => z.object({ all: z.optional(fieldSchema), phone: z.optional(fieldSchema), smalltablet: z.optional(fieldSchema), tablet: z.optional(fieldSchema), laptop: z.optional(fieldSchema), desktop: z.optional(fieldSchema), }); export const FormFactor = <Z extends z.ZodTypeAny>(fieldSchema: Z) => z.object({ isFormFactor: z.literal(true).default(true), all: z.optional(fieldSchema), landscape: z.optional(FormFactorDevice(fieldSchema)), portrait: z.optional(FormFactorDevice(fieldSchema)), }); // 抽离FormFactorDevice的类型结构 type FormFactorDeviceStructure<T> = { all?: T; phone?: T; smalltablet?: T; tablet?: T; laptop?: T; desktop?: T; }; export const selectFormFactorDevice = <T>( formFactorDevice: FormFactorDeviceStructure<T>, deviceType: keyof FormFactorDeviceStructure<T> ): T | undefined => { return formFactorDevice[deviceType]; }; // 测试 const b = FormFactorDevice(z.string()).parse({ all: '100', smalltablet: '200', phone: '300', }); const d = selectFormFactorDevice(b, 'all'); // 类型自动推断为 string | undefined
修改方案二:基于Zod推断类型调整泛型
如果不想额外定义类型结构,可以让泛型参数直接对应FormFactorDevice的推断类型,再从中提取字段类型:
import { z } from 'zod'; // 保留原有的FormFactorDevice和FormFactor定义 export const FormFactorDevice = <T extends z.ZodTypeAny>(fieldSchema: T) => z.object({ all: z.optional(fieldSchema), phone: z.optional(fieldSchema), smalltablet: z.optional(fieldSchema), tablet: z.optional(fieldSchema), laptop: z.optional(fieldSchema), desktop: z.optional(fieldSchema), }); export const FormFactor = <Z extends z.ZodTypeAny>(fieldSchema: Z) => z.object({ isFormFactor: z.literal(true).default(true), all: z.optional(fieldSchema), landscape: z.optional(FormFactorDevice(fieldSchema)), portrait: z.optional(FormFactorDevice(fieldSchema)), }); export const selectFormFactorDevice = <FFD extends z.infer<ReturnType<typeof FormFactorDevice<any>>>>( formFactorDevice: FFD, deviceType: keyof FFD ): FFD[keyof FFD] => { return formFactorDevice[deviceType]; }; // 测试 const b = FormFactorDevice(z.string()).parse({ all: '100', smalltablet: '200', phone: '300', }); const d = selectFormFactorDevice(b, 'all'); // 类型自动推断为 string | undefined
两种方案都能让函数自动推断出正确的返回类型,无需手动指定泛型参数。
内容的提问来源于stack exchange,提问作者Viet Hoang Do
相关产品推荐
相关产品推荐

