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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:22:36