TypeScript中如何通过泛型约束bar的键与foo的键一致?
实现TypeScript函数参数键的严格约束
你当前的写法无法生效,核心原因是foo被定义为Record<string, any>,这意味着keyof typeof foo等价于string,所以bar的Record<string, any>自然允许任意字符串键,TypeScript不会校验额外键。
通过泛型捕获foo的具体类型,可以实现严格的键约束,以下是两种常见方案:
方案1:强制bar包含foo的所有键,且无额外键
const myFn = <T extends Record<string, any>>( foo: T, bar: { [K in keyof T]: any } & { [key: string]: never } ) => { return { foo, bar } }
测试效果
- 合法调用(无错误):
myFn({ one: 'noghint', two: 'nothing' }, { one: 'test', two: 'test' }) - 传入额外键(触发错误):
// 错误提示:对象文字可以只指定已知属性,“three”不在约束类型中 myFn({ one: 'noghint', two: 'nothing' }, { three: 'nothing' }) - 缺少foo中的键(触发错误):
// 错误提示:缺少属性“two”,不满足约束类型 myFn({ one: 'noghint', two: 'nothing' }, { one: 'test' })
方案2:允许bar包含foo键的子集,禁止额外键
如果不需要强制bar包含foo的所有键,仅要求bar的键都是foo已有的,可以用Partial修饰:
const myFn = <T extends Record<string, any>>( foo: T, bar: Partial<{ [K in keyof T]: any }> & { [key: string]: never } ) => { return { foo, bar } }
测试效果
- 合法调用(无错误):
myFn({ one: 'noghint', two: 'nothing' }, { one: 'test' }) - 传入额外键(依然触发错误):
// 错误提示:“three”不在约束类型中 myFn({ one: 'noghint', two: 'nothing' }, { three: 'nothing' })
原理说明
- 泛型
T会自动捕获foo传入的具体对象结构,而非宽泛的Record<string, any>; { [K in keyof T]: any }约束bar的键必须是foo的键,且对应值可以是任意类型;& { [key: string]: never }通过交叉类型禁止任何额外的字符串键——额外键的类型会被推断为never,与传入的实际值类型冲突,从而触发TypeScript错误。
内容的提问来源于stack exchange,提问作者Syd Amir
相关产品推荐
相关产品推荐

