TypeScript如何用映射类型实现含至少一个原属性且无额外属性的类型
实现方案
你可以通过自定义TypeScript工具类型实现需求,完整代码如下:
// 原类型定义 type A = { foo: string; bar: number; baz: boolean; } // 通用工具类型:要求至少包含T的一个属性,且不允许出现T以外的属性,兼容string/number/symbol类型的键 type StrictAtLeastOnePartial<T> = { [K in keyof T]: Pick<T, K> }[keyof T] & Record<Exclude<keyof any, keyof T>, never> // 最终的B类型 type B = StrictAtLeastOnePartial<A>
校验效果测试
// 编译正常 const b1: B = { foo: "yeah" } // 多属性同时存在也编译正常 const b11: B = { foo: "yeah", bar: 123 } // 报错:空对象不符合要求 const b2: B = {} // 报错:存在A以外的属性lala const b3: B = {lala: "lala"} // 报错:存在A以外的属性but_not_this const b4: B = {foo: "foo is allowed", but_not_this: false}
实现原理
- 至少一个属性约束:
{ [K in keyof T]: Pick<T, K> }[keyof T]会遍历T的所有键,为每个键生成仅包含该键的对象类型,再取所有这些类型的联合。TypeScript的联合类型采用鸭子类型检测,只要对象符合联合中的任意一个分支(即包含至少一个对应属性)就会通过校验,同时也允许多个属性同时存在。 - 禁止额外属性约束:
Record<Exclude<keyof any, keyof T>, never>会将所有不属于T的键的类型设为never,一旦赋值了额外属性,TypeScript会检测到属性值和never类型不兼容,直接抛出错误。
内容的提问来源于stack exchange,提问作者robkuz
相关产品推荐
相关产品推荐

