我猜你已经致力于写出 enum 和 interface,然后希望 TypeScript 会警告你 interface 缺少来自 enum 的键(或者如果它有额外的键)?
假设你有
enum E { A = "a", B = "b", C="c"};
interface ISomething { a: string, b: number, c: OtherType};
您可以使用conditional types 让 TypeScript 找出E 的任何成分是否从ISomething 的键中丢失:
type KeysMissingFromISomething = Exclude<E, keyof ISomething>;
如果ISomething 中没有缺少任何键,则此类型应为never。否则,它将是E 的值之一,如E.C。
您还可以让编译器确定 ISomething 是否有任何 非 组成 E 的键,也使用条件类型...虽然这更复杂,因为 you can't quite manipulate enums programmatically in expected ways .这里是:
type ExtraKeysInISomething = {
[K in keyof ISomething]: Extract<E, K> extends never ? K : never
}[keyof ISomething];
同样,如果您没有额外的密钥,这将是 never。然后,如果其中任何一个不是never,您可以通过使用generic constraints 和default type parameters 来强制编译时错误:
type VerifyISomething<
Missing extends never = KeysMissingFromISomething,
Extra extends never = ExtraKeysInISomething
> = 0;
VerifyISomething 类型本身并不有趣(它始终是0),但是如果它们各自的默认值不是never,泛型参数Missing 和Extra 会报错。
让我们试试吧:
enum E { A = "a", B = "b", C = "c" }
interface ISomething { a: string, b: number, c: OtherType }
type VerifyISomething<
Missing extends never = KeysMissingFromISomething,
Extra extends never = ExtraKeysInISomething
> = 0; // no error
和
enum E { A = "a", B = "b", C = "c" }
interface ISomething { a: string, b: number } // oops, missing c
type VerifyISomething<
Missing extends never = KeysMissingFromISomething, // error!
Extra extends never = ExtraKeysInISomething
> = 0; // E.C does not satisfy the constraint
和
enum E { A = "a", B = "b", C = "c" }
interface ISomething { a: string, b: number, c: OtherType, d: 1} // oops, extra d
type VerifyISomething<
Missing extends never = KeysMissingFromISomething,
Extra extends never = ExtraKeysInISomething // error!
> = 0; // type 'd' does not satisfy the constraint
所以所有这些都有效......但它并不漂亮。
另一种骇人听闻的方法是使用假人class,其唯一目的是在您不添加正确的属性时责骂您:
enum E { A = "a", B = "b" , C = "c"};
class CSomething implements Record<E, unknown> {
a!: string;
b!: number;
c!: boolean;
}
interface ISomething extends CSomething {}
如果你遗漏了其中一个属性,你会得到一个错误:
class CSomething implements Record<E, unknown> { // error!
a!: string;
b!: number;
}
// Class 'CSomething' incorrectly implements interface 'Record<E, unknown>'.
// Property 'c' is missing in type 'CSomething'.
它不会警告你有额外的属性,尽管你可能不在乎?
无论如何,希望其中一个对你有用。祝你好运。