首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可以选择对象的限号键

可以选择对象的限号键
EN

Stack Overflow用户
提问于 2020-05-09 22:18:54
回答 2查看 104关注 0票数 1

我有一个接口(如下所示)。目前,它需要所有的属性。如何使它只需要一个属性。基本上,这些属性是互斥的,因此,例如,选择了ff 'top‘属性,然后就不能选择其他属性。

代码语言:javascript
复制
interface PaddingOptions {
    'top': number;
    'bottom': number;
    'left': number;
    'right': number;
}
代码语言:javascript
复制
const foo: PaddingOptions = {top: 20, bottom: 20} //this should give error as both top and bottom can not be used
const foo: PaddingOptions = {right: 20}; // ok as only one property is selected
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-10 00:13:12

也许是我,但@Zafar的答案并不合适,因为XOR<,>就像他所定义的那样,只被限制为两种类型的参数。

将该XOR<,>类型扩展到更多类型参数将非常冗长,甚至不灵活。

不过,在使用相同的文章 ( XOR<,>类型)之后,还有一种看起来更加灵活的选择,即OneOf<,>

OneOf<,>定义了与XOR<,>相同的解决方案,但只需要一种类型定义,而不需要递归类型(如XOR<,>需要)。

为了通过使用XOR<,>来适应这个问题,我们需要这样的东西

代码语言:javascript
复制
type PaddingOptions = XOR<{right: number}, 
                          XOR<{left: number}, 
                              XOR<{bottom: number}, {top: number}>>>;

读起来真的很不舒服。

OneOf<,>变得非常难读,但易于实现。

代码语言:javascript
复制
type OneOf<T, K extends keyof T> = {
    [Key in K]: Pick<Required<T>, Key> & { 
        [InnerKey in Exclude<K, Key>]?: never; 
    };
}[K];

好的,我刚刚删除了Omit<T, K> & ...,在我们的例子中,这将导致never & ... (冗余),因为我们要从T传递所有的密钥。

因此,在问题案例中嵌入OneOf<,>是非常容易的。

代码语言:javascript
复制
type PaddingOptionKeys = 'top' | 'right' | 'bottom' | 'left';
type PaddingOptions = OneOf<{ [Key in PaddingOptionKeys]: number; }, PaddingOptionKeys>;

const option: PaddingOptions = { left: 9 }; // OK
const option2: PaddingOptions = { right: 9 }; // Still OK
const option3: PaddingOptions = { right: 9, left: 0 }; // Throws error

因此,通过使用OneOf<,>,我们可以轻松地约束多个键,易于阅读和灵活。

希望能帮上忙。

票数 5
EN

Stack Overflow用户

发布于 2020-05-09 22:33:14

代码语言:javascript
复制
// XOR implementation
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;

// Usage
type PaddingOptions = XOR<{ top: number } , { bottom: number }, { right: number }, { left: number }>

const foo: PaddingOptions = {top: 20, bottom: 20} // Will throw error
const bar: PaddingOptions = {bottom: 20}; // Won't throw error

这应该能起作用。

演示

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61704528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档