打字稿检查类型 A === 类型 B | C型

Typescript check if type A === type B | type C

在一个文件中我有这样的东西:

export const _all = {
  a: '',
  b: '',
  c: '',
  d: '',
  e: '',
  f: '',
}
type AllKeysType = typeof _all;
export type AllKey = keyof AllKeysType;

在另一个文件中我有这样的东西:

export const _keep = {
  a: '',
  b: '',
  d: '',
  e: '',
}
type KeepKeysType = typeof _keep;
export type KeepKey = keyof KeepKeysType;

export const _ignore = {
  c: '',
  f: '',
}
type IgnoreKeysType = typeof _ignore;
export type IgnoreKey = keyof IgnoreKeysType;

如何使用 Typescript 断言 _all 中定义的键始终等于 _keep_ignore 的并集。换句话说,AllKey 应该总是等于 KeepKey | IgnoreKey.

如果开发人员通过添加新值(例如 z)更新 _all 但忘记将 z 添加到 _keep_ignore.

这可以通过定义接受两种类型并在输入类型相等时解析为 true 或否则解析为 false 的条件类型来实现。然后编写一些代码,当该类型不是 true.

时会抛出编译错误

当任何一种类型发生变化时,您都会收到一个编译错误,这将确保您记得更新任何不同步的类型。当您希望收到有关不同库中类型更改的通知时,这尤其有用。

例如:

type IsExact<T, U> = [T] extends [U] ? [U] extends [T] ? true : false : false;
function assert<T extends true | false>(expectTrue: T) {}

// this will throw a compile error when the two types get out of sync
assert<IsExact<AllKey, KeepKey | IgnoreKey>>(true);

更健壮的代码稍微长一些(例如处理 any 类型),但它已在我的库中汇总 here

import { assert, IsExact } from "conditional-type-checks";

// define or import AllKey, KeepKey, IgnoreKey

assert<IsExact<AllKey, KeepKey | IgnoreKey>>(true);

另一种选择

另一种不太好的方法是创建两种类型的两个对象并将它们分配给彼此。

() => {
  let allKeys: AllKey;
  let otherKeys: KeepKey | IgnoreKey;

  // do this in lambdas to prevent the first assignment from changing
  // the type of the variable being assigned to
  () => allKeys = otherKeys;
  () => otherKeys = allKeys;
};