TypeScript 2.8:如何从一个对象类型中移除另一个的属性?
实现
ObjectDiff<T, U>移除对象中存在于U的属性 这问题问得太实用了!刚好我之前做项目时也遇到过类似需求,咱们用TypeScript的类型工具就能轻松搞定,给你两种实现方式:
方式一:用Pick + Exclude组合(兼容性更好)
其实TypeScript已经内置了Pick和Exclude这两个工具类型,把它们组合起来就能直接实现你的需求,代码简洁还兼容更早的TS版本:
type ObjectDiff<T, U> = Pick<T, Exclude<keyof T, keyof U>>;
原理拆解:
Exclude<keyof T, keyof U>:先筛选出所有属于T但不在U里的属性键。拿你的例子来说,keyof A是"one" | "two" | "three",keyof Stuff是"three",所以这一步会得到"one" | "two"。Pick<T, ...>:从原类型T里挑出前面得到的这些属性键,最终就得到了去掉U中存在属性的新类型。
测试你的例子:
type A = { one: string; two: number; three: Date; }; type Stuff = { three: Date; }; type AWithoutStuff = ObjectDiff<A, Stuff>; // 实际类型:{ one: string; two: number; }
完全符合你的预期!
方式二:用映射类型键重映射(TS 4.1+)
如果你用的是TypeScript 4.1及以上版本,还可以用键重映射的方式来写,逻辑和你提到的联合类型Diff更相似,更直观:
type ObjectDiff<T, U> = { [K in keyof T as K extends keyof U ? never : K]: T[K]; };
原理拆解:
- 遍历
T的每个属性键K,通过as子句做条件判断:如果K是U的属性键,就把这个键替换成never(相当于排除该属性);否则保留原键K。 - 最终只保留那些不在
U中的属性,值类型和T中对应属性完全一致。
补充说明
- 这两种方式都只判断属性键是否存在,不管属性值类型是否匹配。比如就算
Stuff里的three是string而不是Date,依然会移除A中的three属性。 - 如果需要同时判断键和值类型都匹配才移除,可以调整条件,但你的需求里只需要根据键来移除,上面的实现完全够用。
内容的提问来源于stack exchange,提问作者Rico Kahler
相关产品推荐
相关产品推荐

