TypeScript 的类型减法

在使用 TypeScript 开发的过程中,我们有时会遇到需要做类型减法的情况,例如 react-i18nexttranslate 方法会为组件的 Props 添加 i18n 等属性,而这个属性在通过 translate 生成的高阶组件的 Props 中是不应体现的。这时我们就需要用到类型减法。

具体实现:

// Diff / Omit taken from https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-311923766
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;

interface A {
  a: string;
  b?: string;
  c: number;
}

type B = Omit<A, 'c'>;

const a: A = {
  a: '5',
  c: 5,
};

const b: B = {
  a: '5',
};

// Note: typeof B is (correctly) Pick<A, 'a' | 'b'>

这里主要用到了 Pick 工具类,Pick 可以从一个类型中取出一组属性生成新的类型。


TypeScript 2.8 更新

在 TypeScript 2.8 中,新增了条件类型 Exclude<T, U>,它可以从T中排除那些可分配给U的类型。

所以上面的 Omit<T, K> 类型可以改写为 Pick<T, Exclude<keyof T, K>>

TypeScript 2.8 Release Notes