当前位置: 首页 > 知识库问答 >
问题:

有没有办法在Typescript中定义两个互斥的属性?[重复]

董嘉祯
2023-03-14

问题描述

我想在Type cript中的接口中定义两个可选属性。这两个属性中的一个并且只有一个必须存在于此接口的实例对象中。

我试过什么

interface ISidebarCommon {
  /**
   * The label to be used in sidebar
   */
  label: string;
  /**
   * Icon class in string format for the icon of the sidebar image
   */
  icon: string;
}

interface IRoutableSidebarItem extends ISidebarCommon {
  /**
   * Role number to determine which route to redirect the user to
   * This property is mutually exclusive with children
   */
  role: number;
}

interface ITreeSidebarItem<SI> extends ISidebarCommon {
  /**
   * An array of children sidebar items.
   * This property is mutually exclusive with role
   */
  children: SI[];
}

interface ISidebar {
  [index: number]: IRoutableSidebarItem | ITreeSidebarItem<IRoutableSidebarItem
    | ITreeSidebarItem<IRoutableSidebarItem>
  >;
}

当前解决方案的问题

虽然当前解决方案确保必须存在两个属性之一,即角色,但它不会使它们相互排斥。也就是说,角色都可能存在于实例对象中,它仍然会通过当前接口检查。

问题示例

以下是 ISidebar 接口实例的示例,其中对象同时包含角色子项,并且 linter 仍然不显示任何错误:

const sidebarBroken: ISidebar = [
  {
    label: 'l1',
    icon: 'c1',
    role: 5,
    children: [
      {
        label: 'l2',
        icon: 'c2',
        role: 6,
        children: [
          {
            label: 'l3',
            icon: 'c3',
            role: 7,
          },
        ],
      },
    ],
  },
];

共有1个答案

方斌
2023-03-14

我通过使用打字稿中的从不类型和可选属性找到了解决方案。

我必须做的是更新我的接口声明,以便IRoutableSidebarItem的实例永远不会有属性,而ITreeSidebarItem的实例永远不会有角色属性。

使用上述解决方法更新了示例:

interface ISidebarCommon {
  /**
   * The label to be used in sidebar
   */
  label: string;
  /**
   * Icon class in string format for the icon of the sidebar image
   */
  icon: string;
}

interface IRoutableSidebarItem extends ISidebarCommon {
  /**
   * Role number to determine which route to redirect the user to
   * This property is mutually exclusive with children
   */
  role: number;
  children?: never;
}

interface ITreeSidebarItem<SI> extends ISidebarCommon {
  /**
   * An array of children sidebar items.
   * This property is mutually exclusive with role
   */
  children: SI[];
  role?: never;
}

interface ISidebar {
  [index: number]: IRoutableSidebarItem | ITreeSidebarItem<IRoutableSidebarItem
    | ITreeSidebarItem<IRoutableSidebarItem>
  >;
}

/*
  Throws a linting error
*/
const sidebarBroken: ISidebar = [
  {
    label: 'l1',
    icon: 'c1',
    role: 5,
    children: [
      {
        label: 'l2',
        icon: 'c2',
        role: 6,
        children: [
          {
            label: 'l3',
            icon: 'c3',
            role: 7,
          },
        ],
      },
    ],
  },
];

/*
  Doesn't throw a linting error
*/
const sidebarWorking: ISidebar = [
  {
    label: 'l1',
    icon: 'c1',
    children: [
      {
        label: 'l2',
        icon: 'c2',
        children: [
          {
            label: 'l3',
            icon: 'c3',
            role: 7,
          },
        ],
      },
    ],
  },
  {
    label: 'l1',
    icon: 'c1',
    role: 12,
  },
];
 类似资料:
  • 问题内容: 有没有办法用TypeScript语言进行方法重载? 我想实现以下目标: 这是我不想做的一个例子(我真的很讨厌JS中重载hack的那一部分): 问题答案: 根据规范,TypeScript确实支持方法重载,但是它很笨拙,并且包含许多手动检查参数类型的工作。我认为这主要是因为在纯JavaScript中最接近方法重载的地方还包括检查,并且TypeScript尝试不修改实际的方法主体,以避免任何

  • 假设有一个类库X的输入文件,其中包含一些接口。 为了使用这个库,我需要传递一个与。当然,我可以在源文件中创建相同的接口: 但这样一来,我就有了让它和库中的一个保持最新的负担,而且它可能非常大,并导致大量代码重复。 因此,有没有办法“提取”接口的这个特定属性的类型?类似于(这不起作用,导致“找不到名称I2”错误)。 编辑:在TS操场上玩了一会儿后,我注意到以下代码完全实现了我想要的: 但是,它需要声

  • 我想检查启用宏的页面中标签的名称及其子项。这是否可以使用自定义宏?我遵循了这个教程:https://developer.atlassian.com/server/framework/atlassian-sdk/create-a-confluence-hello-world-macro/ 查看了一些其他文件,但无法验证。

  • 问题内容: 有没有办法在Go中执行重复的后台任务?我在想类似Java 的东西。我知道我可以使用goroutine和来做到这一点,但是我想要一些容易停止的东西。 这就是我得到的,但是对我来说看起来很丑。有没有更清洁/更好的方法? 问题答案: 该功能使通道发送定期消息,并提供了一种停止该消息的方法。使用它像这样(未经测试): 您可以通过关闭频道来停止工作人员:。

  • 我们使用PHP7.0运行XAMPP是因为我们的新产品需要PHP7。 但是有些老项目使用等函数,这些函数在PHP7.0中被删除。 那么,有没有办法在XAMPP中轻松更改PHP版本呢? 注意:请不要建议将旧项目升级到与新版本兼容,因为我不能这样做,因为作为一个开发人员(只是一个员工),我不能得到这些决定。

  • 假设您有一个包含3个值的枚举: 你用某种方法转换它的所有值,认为你已经处理了所有的情况: 然后,稍后向枚举添加新值: 一切仍然编译正常,除了你在方法中默默地错过了的案例。有没有办法在这种情况下引发编译时错误? 编辑:不明白为什么这被标记为在Java中运行时添加和删除枚举元素的重复。由于答案是“否”,这意味着在编译时应该知道枚举的所有值,因此我所要求的应该是编译器/某些代码分析工具实现的,对吧?