检查穷举键联合的规范方法是什么

时间:2018-11-06 18:54:25

标签: typescript

我正在尝试转换和过滤类Source的实例的某些属性。为了重复执行尽可能少的代码,我决定从运行时可用的数据开始(我的键名放在数组中),然后从那里派生类型。

我希望对所有内容进行类型检查,以便在Source中添加新属性时TS会警告我我忘记处理它。这就是我现在正在做的事情:

class Source {
  data = "d";

  meta = "m";

  // if I un-comment this the compilation fails, that is what I want
  // meta2 = "m2";
}

const keysTuple = <T extends Array<keyof Source>>(...args: T) => args;

const dataProps = keysTuple("data");
const metaProps = keysTuple("meta");

这就是我检查完整“覆盖率”的方式:

const _exhaustiveCheck: keyof Source extends
  | typeof dataProps[number]
  | typeof metaProps[number]
  ? boolean
  : never = true;

仅仅为了对_exhaustiveCheck进行类型检查而不得不引入never变量似乎很奇怪,所以我想知道是否有更好的方法?

1 个答案:

答案 0 :(得分:1)

您不必引入变量,至少不必在运行时引入。纯粹在类型级别,您可以执行以下操作:

type MutuallyExtends<T extends U, U extends V, V=T> = true;
type ExhaustiveCheck = 
  MutuallyExtends<keyof Source, typeof dataProps[number] | typeof metaProps[number]>;

但是我可能更喜欢在添加了额外属性的Source类内部执行编译器错误的操作:

const keysTuple = <T extends Array<keyof any>>(...args: T) => args;
const dataProps = keysTuple("data");
const metaProps = keysTuple("meta");

type NoExtraKeys<T, K extends keyof T> = Record<Exclude<keyof T, K>, never>;
type DataMetaKeys = typeof dataProps[number] | typeof metaProps[number];
class Source implements NoExtraKeys<Source, DataMetaKeys>
{
  data = "d";

  meta = "m";

  // if you un-comment this the compilation fails right here
  //meta2 = "m2";
}

通过声明Source实现了NoExtraKeys<Source, DataMetaKeys>,诸如meta2之类的任何额外键都将评估为Source implements {meta2: never}之类的东西,这将失败。

希望有帮助。祝你好运!