挑战
获取两个接口类型中的差值属性。
type Foo = {
a: string;
b: number;
};
type Bar = {
a: string;
c: boolean;
};
type Result1 = Diff<Foo, Bar>; // { b: number, c: boolean }
type Result2 = Diff<Bar, Foo>; // { b: number, c: boolean }解答
要找到差值属性,我们首先要得到两个对象的所有属性。
type Diff<O, O1> = {
[P in keyof (O & O1)]: never;
};接下来我们筛选差值属性。
对于任意一个属性,有三种可能:
- 只存在于
O中 - 只存在于
O1中 - 既存在于
O中,也存在于O1中
我们可以先判断该属性是不是在 O 中。如果不在,肯定只属于 O1,是我们想要的属性;如果在 O 中,再判断是不是在 O1 中,如果不在,说明只存在于 O 中,也是我们想要的属性,否则舍弃掉。
type Diff<O, O1> = {
[P in keyof (O & O1) as P extends keyof O
? P extends keyof O1
? never
: P
: P]: never;
};现在我们得到了所有差值属性,接下来给属性加上对应的类型。
type Diff<O, O1> = {
[P in keyof (O & O1) as P extends keyof O
? P extends keyof O1
? never
: P
: P]: P extends keyof O ? O[P] : P extends keyof O1 ? O1[P] : never;
};这道题在 Issue 区还有一个更精妙的答案,这里直接贴出来。
// O&O1 - O|O1
// & means 'either has', | means 'both have'
type Diff<O, O1> = {
[K in keyof (O & O1) as K extends keyof (O | O1) ? never : K]: (O & O1)[K];
};核心就是 keyof (O | O1) 会得到两者都有的属性,具体的解释大家可以去 GitHub 查看。