TypeScript类型挑战 - implement Diff<A, B>

Implement DiffKeys<A, B> to return the keys either in A or B, but not in both.

题目出处:https://bigfrontend.dev/zh/typescript/implement-Diff-A-B

type A = DiffKeys<{a: 1, b: 2}, {b: 1, c: 2}> // 'a' | 'c'

1.实现思路分析

获取对象类型的keys,可以通过keyof 操作符去实现。

用数学集合的角度去分析,我们把keyof Left,获取的联合类型看成集合A。keyof Right获取的联合类型看成集合B。那么我们最终要得到的集合,其实是A和B的差集,并上B和A的差集。

// keyof Left A = "a" | "b"
// keyof Right B = "b" | "c"

// A 和 B 的差集C = (A \ B) = "a"
// B 和 A 的差集D = (B \ A) = "c"

// C和D求并集 
//  (A \ B) ∪ (B \ A)

并集在ts中的概念,就是或运算 |

差集的运算,可以通过Exclude这个内置的类型去实现

/**
 * Exclude from T those types that are assignable to U
 */
type Exclude<T, U> = T extends U ? never : T;

2. 实现

所以,通过ts的方式去实现:

type DiffKeys<
  Left extends Record<string, any>,
  Right extends Record<string, any>
> = Exclude<keyof Left, keyof Right> | Exclude<keyof Right, keyof Left>;

type R = DiffKeys<{ a: 1; b: 2 }, { a: 1; c: 3 }>;
// type R = "b" | "c"