TypeScript泛型函数输入参数类型推断失效问题
TypeScript泛型函数类型推断问题解决方案
问题核心
你的代码里,Objs类型使用了索引签名,导致所有属性被统一推断为最宽泛的类型(比如FnObj<any>),所以func的参数input被识别为any,访问不存在的属性不会触发类型错误。要让每个对象键的input和func参数类型一一对应,需要调整泛型约束的写法。
无Zod场景解决方案
修改createFormDef的泛型约束,让TypeScript为每个属性单独推断input的类型:
type FnObj<I> = { input: I, func: (input: I) => void } function createFormDef<T extends Record<string, { input: any; func: (input: any) => void }>>( formObject: { [K in keyof T]: { input: T[K]['input']; func: (input: T[K]['input']) => void; }; } ) { return formObject; } // 测试代码:此时input会被正确推断为{ hello: number },访问dsf会报错 createFormDef({ test: { input: { hello: 10 }, func: (input) => { input.dsf // ❌ 类型错误:属性“dsf”在类型“{ hello: number; }”上不存在 }, }, });
带Zod场景解决方案
利用Zod的z.infer<I>工具类型获取Schema对应的TS类型,同样通过映射类型让每个属性独立推断:
import z from 'zod'; type FnObj<I extends z.ZodType> = { input: I, func: (input: z.infer<I>) => void } function createFormDef<T extends Record<string, FnObj<any>>>(formObject: { [K in keyof T]: FnObj<T[K]['input']> }) { return formObject; } // 测试代码:input被推断为{ d: number },访问dsf会报错 createFormDef({ test: { input: z.object({ d: z.number(), }), func: (input) => { input.dsf // ❌ 类型错误:属性“dsf”在类型“{ d: number; }”上不存在 }, }, });
原因说明
之前的索引签名写法([key: string]: FnObj<I>)会强制所有属性共享同一个泛型参数I,或者因为默认值退化为any,导致TypeScript无法为每个键单独推导input的具体类型。改用映射类型({[K in keyof T]: ...})后,TS会遍历对象的每个键,为每个属性单独推断对应的input类型,并自动约束func的参数类型,从而实现类型安全检查。
内容的提问来源于stack exchange,提问作者Hafil Latheef
相关产品推荐
相关产品推荐

