我有可选属性列表的接口.

export interface OptionalIds {
  entityA_Id?: number;
  entityB_Id?: number;
  entityC_Id?: number;
}

我有一个要求,那就是定义其中的EXACTLY个.大概是这样的:

export interface RequiredBId {
  entityA_Id?: undefined;
  entityB_Id: number;
  entityC_Id?: undefined;
}

export interface RequiredCId {
  entityA_Id?: undefined;
  entityB_Id?: undefined;
  entityC_Id: number;
}

export interface OptionalIds {
  entityA_Id?: number;
  entityB_Id?: number;
  entityC_Id?: number;
}

export type RestrictedOptionalIds = OptionalIds & (RequiredAId | RequiredBId | RequiredCId)

The question is:有没有其他方法可以在没有奇怪 struct 的情况下实现所描述的行为?

推荐答案

更新答案

感谢这篇RequireOnlyOne:https://stackoverflow.com/a/49725198/4529555的帖子

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]

export interface OptionalIds {
  entityA_Id?: number;
  entityB_Id?: number;
  entityC_Id?: number;
}

const exampleA: RequireOnlyOne<OptionalIds> = {
  entityA_Id: 1
}
const exampleB: RequireOnlyOne<OptionalIds> = {
  entityB_Id: 1
}

const exampleC: RequireOnlyOne<OptionalIds> = {
  entityC_Id: 1
}

// Error
const exampleMultiple: RequireOnlyOne<OptionalIds> = {
  entityA_Id: 1,
  entityB_Id: 2,
}

// Error: {} not assignable to RequireAtLeastOne<OptionalIds, keyof OptionalIds>
const exampleTsError: RequireOnlyOne<OptionalIds> = {

}

原始答案

感谢这篇RequireAtLeastOne:https://stackoverflow.com/a/49725198/4529555的帖子

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]

export interface OptionalIds {
  entityA_Id?: number;
  entityB_Id?: number;
  entityC_Id?: number;
}

const exampleA: RequireAtLeastOne<OptionalIds> = {
  entityA_Id: 1
}
const exampleB: RequireAtLeastOne<OptionalIds> = {
  entityB_Id: 1
}

const exampleC: RequireAtLeastOne<OptionalIds> = {
  entityC_Id: 1
}

const exampleMultiple: RequireAtLeastOne<OptionalIds> = {
  entityA_Id: 1,
  entityB_Id: 2
}

// Error: {} not assignable to RequireAtLeastOne<OptionalIds, keyof OptionalIds>
const exampleTsError: RequireAtLeastOne<OptionalIds> = {

}

Typescript相关问答推荐

如何缩小变量访问的对象属性范围?

类型脚本中没有接口的中间静态类

React Typescript项目问题有Redux-Toolkit userSlice角色问题

如何在深度嵌套的Reaction路由对象中隐藏父级?

一个打字类型可以实现一个接口吗?

限制返回联合的TS函数的返回类型

推断从其他类型派生的类型

刷新页面时,TypeScrip Redux丢失状态

重载函数的T helper参数

正确使用相交类型的打字集

TypeScrip-根据一个参数值验证另一个参数值

S,为什么我的T扩展未定义的条件在属性的上下文中不起作用?

重写返回任何

获取类属性的类型';TypeScript中的getter/setter

如何在TypeScript中描述和实现包含特定属性的函数?

通过辅助函数获取嵌套属性时保留类型

传入类型参数<;T>;变容函数

为什么我的 Typescript 函数中缺少 void 隐式返回类型?

使用 TypeScript 在 SolidJS 中绘制 D3 力图

如果组件需要本地状态(typescript)上的 setState,如何从组件中提取 axios http 请求?