我有两个接口(interface),我想共享相同的键,但不共享相同的值。假设第一个接口(interface) (Thing
) 来自外部库,第二个接口(interface) (ThingOptions
) 在我的项目中。
interface Thing {
foo(value: number): void;
bar(value: string): void;
someOtherKey: null;
}
interface ThingOptions {
foo: number;
bar: string;
}
有没有办法断言 ThingOptions
的键是 Thing
的键的子集?
最佳答案
有几种方法可以对此进行一些编译时检查,但我认为所有这些方法都需要稍微重复 ThingOptions
姓名。
一种方法是制作 KeysFrom<T, U>
它采用类型 T
和候选类型 U
,仅与 U
兼容如果 U
的键是 T
的子集(这意味着 T
可以有 U
没有的键,但是 U
不能有 T
没有的键):
type KeysFrom<T, U> = { [K in keyof U]: K extends keyof T ? U[K] : never }
所以 KeysFrom<{a: string}, {a: number}>
就变成了{a: number}
,这{a: number}
延伸。但是KeysFrom<{a: string}, {b: number}
变成 {b: never}
,这{b: number}
不延伸。然后你声明 ThingOptions
延伸KeysFrom<Thing, ThingOptions>
.这是一个递归约束。让我们看看:
interface ThingOptions extends KeysFrom<Thing, ThingOptions> {
foo: number;
bar: string;
}
行得通。
interface BadThingOptions extends KeysFrom<Thing, BadThingOptions> { // error!
// ~~~~~~~~~~~~~~~ <-- properties of type "bap" are incompatible
foo: number;
bap: string;
}
而且编译失败,正如您可能希望的那样。
您可以做的另一件非递归的事情是将检查移动到它自己的行:
type KeysAreSubset<
T,
U extends { [K in keyof U]: K extends keyof T ? U[K] : never }
> = true;
在这里,KeysAreSubset<T, U>
评估为 true
总是,但是U
现在限制为 KeysFrom<T, U>
.如果你使用 KeysAreSubset<ThingOptions, U>
坏了U
,你会得到一个错误:
interface ThingOptions {
foo: number;
bar: string;
}
type ThingOptionsIsOkay = KeysAreSubset<Thing, ThingOptions>;
interface BadThingOptions {
foo: number;
bap: string;
}
type BadThingOptionsIsNotOkay = KeysAreSubset<Thing, BadThingOptions>; // error!
// Types of property 'bap' are incompatible. -----> ~~~~~~~~~~~~~~~
这两个都有效,但它们都需要您重写名称 ThingOptions
,它们都需要您跳过一些障碍才能正确使用。不过,它可能适用于您的用例。祝你好运!
关于typescript - 我可以指定一个接口(interface)将共享另一个接口(interface)的 key 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58438027/