问题描述
我想在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,
},
],
},
],
},
];
我通过使用打字稿中的从不
类型和可选属性找到了解决方案。
我必须做的是更新我的接口声明,以便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中运行时添加和删除枚举元素的重复。由于答案是“否”,这意味着在编译时应该知道枚举的所有值,因此我所要求的应该是编译器/某些代码分析工具实现的,对吧?