TypeScript如何确保对象数组包含泛型T的每一个key值?
TypeScript 实现双向校验的方案
首先你原实现中自定义的Object接口会和全局Object类型冲突,建议重命名为NameItem这类自定义名称。
要实现「数组name均为T的合法key」+「T的所有key都在数组name中出现」的双向约束,可以通过引入第二个泛型推导实际传入的name集合,再做全量匹配校验,代码实现如下:
// 数组元素类型定义 interface NameItem<T> { name: T } // 函数泛型约束 function f<T, K extends keyof T>( arr: Exclude<keyof T, K> extends never ? NameItem<K>[] : never ) { // 你的业务逻辑 }
测试用例
// 示例目标类型 interface User { id: number name: string age: number } // ✅ 校验通过:覆盖了User所有key,且没有非法key f<User>([ { name: 'id' }, { name: 'name' }, { name: 'age' } ]) // ❌ 校验失败:缺少key "age" f<User>([ { name: 'id' }, { name: 'name' } ]) // ❌ 校验失败:存在不属于User的非法key "gender" f<User>([ { name: 'id' }, { name: 'name' }, { name: 'age' }, { name: 'gender' } ])
实现原理
- 泛型
T为你指定的目标类型,泛型K用于自动推导传入数组所有name属性的字面量联合类型 K extends keyof T保留了原有的校验逻辑,保证所有name都是T的合法key,避免传入不存在的属性Exclude<keyof T, K> extends never约束K必须包含T的所有key,如果存在遗漏的key,Exclude返回的类型不为never,就会触发类型报错
如果你使用的是TS 5.0及以上版本,可以给泛型增加const修饰符,进一步优化字面量类型推导效果:
function f<T, const K extends keyof T>( arr: Exclude<keyof T, K> extends never ? NameItem<K>[] : never ) { // 业务逻辑 }
内容的提问来源于stack exchange,提问作者ICW
相关产品推荐
相关产品推荐

