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

TypeScript接口需要两个属性之一才能存在

洪知
2023-03-14

我正在尝试创建一个可以

export interface MenuItem {
  title: string;
  component?: any;
  click?: any;
  icon: string;
}
  1. 是否有办法要求组件单击进行设置

共有3个答案

何禄
2023-03-14
匿名用户

有一个更简单的解决方案。无需依赖任何或复杂的条件类型(参见答案):

  1. 有没有办法要求设置组件或单击?(包含OR
type MenuItemOr = {
    title: string;
    icon: string;
} & ({ component: object } | { click: boolean }) 
// brackets are important here: "&" has precedence over "|"

let testOr: MenuItemOr;
testOr = { title: "t", icon: "i" } // error, none are set
testOr = { title: "t", icon: "i", component: {} } // ✔
testOr = { title: "t", icon: "i", click: true } // ✔
testOr = { title: "t", icon: "i", click: true, component: {} } // ✔

联合类型(|)对应于inclusive。它与非条件属性相交。

使用运算符中的将值缩小到其中一个成分:

if ("click" in testOr) testOr.click // works 
type MenuItemXor = {
    title: string;
    icon: string;
} & (
        | { component: object; click?: never }
        | { component?: never; click: boolean }
    )

let testXor: MenuItemXor;
testXor = { title: "t", icon: "i" } // error, none are set
testXor = { title: "t", icon: "i", component: {} } // ✔
testXor = { title: "t", icon: "i", click: true } // ✔
testXor = { title: "t", icon: "i", click: true, component: {} } //error,both set

基本上可以设置组件单击,不应同时添加另一个组件。TS可以从MenuItemXor中生成一个有区别的联合类型,它对应于XOR

这个XOR条件对于MenuItemXor来说是不可能的。

游戏场

1从技术上讲,prop?:从来没有被解析为prop?:未定义的,尽管前者经常用于说明。

严昊昊
2023-03-14

不使用单个接口,因为类型没有条件逻辑,也不能相互依赖,但您可以通过拆分接口:

export interface BaseMenuItem {
  title: string;
  icon: string;
}

export interface ComponentMenuItem extends BaseMenuItem {
  component: any;
}

export interface ClickMenuItem extends BaseMenuItem {
    click: any;
}

export type MenuItem = ComponentMenuItem | ClickMenuItem;
周麒
2023-03-14

借助于TypeScript 2.8中添加的Exclude类型,提供了一种要求至少一组属性中的一个属性的通用方法:

type RequireAtLeastOne<T, Keys extends keyof T = keyof T> =
    Pick<T, Exclude<keyof T, Keys>> 
    & {
        [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>
    }[Keys]

要求提供一个且仅提供一个的部分但非绝对方式是:

type RequireOnlyOne<T, Keys extends keyof T = keyof T> =
    Pick<T, Exclude<keyof T, Keys>>
    & {
        [K in Keys]-?:
            Required<Pick<T, K>>
            & Partial<Record<Exclude<Keys, K>, undefined>>
    }[Keys]

下面是一个TypeScript游乐场链接,显示了两者的作用。

RequireOnlyOne的警告是,TypeScript在编译时并不总是知道运行时存在的每个属性。所以很明显,RequireOnlyOne无法阻止它不知道的额外属性。我提供了一个示例,说明了RequireOnlyOne如何错过游乐场链接末尾的内容。

使用以下示例快速概述其工作原理:

interface MenuItem {
  title: string;
  component?: number;
  click?: number;
  icon: string;
}

type ClickOrComponent = RequireAtLeastOne<MenuItem, 'click' | 'component'>

>

  • 拾取

    {[K in Keys]-?:必需

    { 
        component: Required<{ component?: number }> & { click?: number }, 
        click: Required<{ click?: number }> & { component?: number } 
    }[Keys]
    

    这就变成了

    {
        component: { component: number, click?: number },
        click: { click: number, component?: number }
    }['component' | 'click']
    

    最终变成

    {component: number, click?: number} | {click: number, component?: number}
    

    上述步骤1和步骤2的交点

    { title: string, icon: string} 
    & 
    ({component: number, click?: number} | {click: number, component?: number})
    

    简化为

    { title: string, icon: string, component: number, click?: number} 
    | { title: string, icon: string, click: number, component?: number}
    

  •  类似资料:
    • 问题内容: 我认为这个问题已经存在,但是我找不到。 我不明白,为什么必须要有一个功能接口才能使用lambda。考虑以下示例: 这可以正常工作,但是如果您取消注释行,则不会。为什么?以我的理解,编译器应该能够区分这两种方法,因为它们具有不同的输入参数。为什么我需要一个功能接口并炸毁我的代码? 编辑:链接的重复项没有回答我的问题,因为我在询问不同的方法参数。但是在这里,我得到了一些非常有用的答案,这要

    • 我正在使用HIbernate core 3.6.2 final。我将注释类映射放在hibernate中。cfg。xml,例如 由于我使用3.6.2的Hibernate版本,所以我不需要创建注释配置类对象。因此,我将配置对象创建为私有静态最终SessionFactory SessionFactory; 但给我错误作为初始SessionFactory创建failed.org.hibernate.Map

    • 我试图让VSCode启动并使用TypeScript运行,但收效甚微。 我正在看以下内容: https://code.visualstudio.com/docs/languages/typescript 看起来,一旦安装了编译器VSCode,就应该可以正常工作,但考虑到以下情况: tsconfig.json 包裹json tasks.json 项目 你好世界ts 从终端运行构建任务或tsc会正确指示

    • 总之,是否可以有一个声明某些基属性但不限制其他属性的接口?这是我目前的情况: 我使用的是Flux模式,它定义了一个通用调度器: 然后,我用自己的有效负载类型创建一个调度程序,如下所示: 现在我有了一些动作代码,它应该分派一个带有一些附加数据的有效负载,但是< code>ActionPayload接口只允许< code>actionType。换句话说,这段代码: 给出编译错误,因为与接口不匹配。问题

    • 我只想问关于争论的事。方法名并不重要,但每个方法都采用不同参数的唯一顺序,因此Oracle可以实现这个特性,而不是让每个“lambda-interface”都有一个方法。

    • 而我用AndroidStudio2.3来调试,有什么问题吗?更重要的是,我的AndroidManifest是这样的。