首页 > 解决方案 > 检查详尽的键联合的规范方法是什么

问题描述

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

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

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,所以我想知道是否有更好的方法?

标签: typescript

解决方案


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

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";
}

通过声明Sourceimplements NoExtraKeys<Source, DataMetaKeys>,任何额外的键,例如meta2将评估为类似的东西Source implements {meta2: never},这将失败。

希望有帮助。祝你好运!


推荐阅读