TypeScript特定泛型函数无法赋值给Record参数通用函数如何处理?
前置说明
你代码中存在一处笔误:Record<"string", unknown>代表仅包含名为string的固定属性的对象,如果你的诉求是表示「key为任意字符串的对象」,需要去掉string两侧的引号,修改为Record<string, unknown>。
报错根因
该报错是TypeScript函数参数的逆变特性导致的:
- 普通变量赋值遵循协变规则:子类型可以赋值给父类型,所以你验证时
AddNumberInput可以赋值给Record<string, unknown>没有问题 - 函数参数遵循逆变规则:如果要将函数A赋值给函数B,要求函数B的参数类型必须是函数A参数类型的子类型,刚好和协变规则相反。你当前的赋值方向是将接收窄参数(
AddNumberInput)的函数,赋值给接收宽参数(Record<string, unknown>)的函数类型,不符合逆变规则,所以报错。如果允许该赋值,后续你给fn2传入任意Record<string, unknown>类型的参数(比如没有number1/number2属性的对象),执行时就会出现运行时错误。
解决方案
方案1:类型断言(快速实现,适合可保证调用参数正确的场景)
如果你能确定后续从集合中取出函数调用时,传入的参数一定匹配对应函数的入参要求,可以直接用类型断言跳过编译检查:
const fns: { [id: string]: GenericFn<Record<string, unknown>, Record<string, unknown>> } = {}; fns["fn1"] = fn1 as GenericFn<Record<string, unknown>, Record<string, unknown>>;
方案2:调整泛型定义,兼容赋值
你可以在泛型接口中用in/out标记泛型的变型属性,或者用any做宽松约束:
// 用in标记输入参数为逆变、out标记输出参数为协变,支持窄类型函数赋值给宽类型接口 interface GenericFn<in TInput extends Record<string, unknown>, out TOutput extends Record<string, unknown>> { (input: TInput): TOutput; } // 集合类型用any做宽松约束 const fns: { [id: string]: GenericFn<any, any> } = {}; fns["fn1"] = fn1; // 无报错
方案3:类型映射表(全类型安全,无类型丢失)
如果你需要存储后调用函数时依然有完整的类型校验,可以提前定义函数类型映射表:
// 定义所有存储函数的入出参映射关系 type FnTypeMap = { fn1: { input: AddNumberInput; output: AddNumberOutput; }; // 后续新增函数直接在此处扩展即可 }; // 基于映射表生成集合类型 type FnsCollection = { [K in keyof FnTypeMap]: GenericFn<FnTypeMap[K]["input"], FnTypeMap[K]["output"]> }; const fns: FnsCollection = { fn1: fn1 }; // 调用时自动推导类型,参数错误会自动提示 fns.fn1({ number1: 1, number2: 2 });
内容的提问来源于stack exchange,提问作者Devwulf
相关产品推荐
相关产品推荐

