我想将类型定义为两个接口的联合.两个接口中的一个应该是可选的,这意味着联合类型应该具有可选接口的all or none个属性.现在应该允许联合类型仅包括可选接口的属性子集.

也就是说,大概是这样的:

interface A {
  a1: string
  a2: string
}

interface B {
  b1: string
  b2: string
}

type C = A | (A & B)

然而,这并不是quite%的工作,如我所期望的.

  1. 禁止部分包含接口A属性,例如
const c: C = {
  // a1: 'a1',
  a2: 'a2',
  b1: 'b1',
  b2: 'b2',
}

导致此错误,如预期的那样:"类型‘{a2:字符串;b1:字符串;b2:字符串;}’中缺少属性‘a1’."

  1. 但是,允许部分包含接口B的属性,例如
const c: C = {
  a1: 'a1',
  a2: 'a2',
  // b1: 'b1',
  b2: 'b2',
}

不会导致错误.

What am I missing? How can I "fix" my types to achieve what I want?


我试过的其他 Select

type C = A & (B | {}) // Same as above.

type C = A & (B | undefined) // This catches { a1: 'a1', a2: 'a2', b2: 'b2' }, but doesn't allow for { a1: 'a1', a2: 'a2' }, i.e. it requires the union to have all of the interface B properties always.

推荐答案

打字脚本中的对象类型是extendible,而不是"精确的"(如microsoft/TypeScript#12936中所要求的).因此,值{ a1: 'a1', a2: 'a2', b2: 'b2'}是类型A | (A & B)的完全有效的值,因为它可以赋值给A.通常情况下,excess property checking会警告您b2,但由于b2A & B的一部分,编译器不会将其视为多余的属性.

一种 idea 是用mapped type来表示"没有T的特性的东西",就像这样:

type NoneOf<T> = { [K in keyof T]?: never };

the impossible never type处房产中有Optional properties处已经接近于禁止房产.它们是可选的,所以您可以省略它们(或者根据编译器选项将它们设置为undefined)……但如果不go 掉它们,它们需要是never,而你找不到这种类型的值.

那么NoneOf<B>就是{b1?: never, b2?: never}了.那么你要找的类型应该是

type C = A & (B | NoneOf<B>)

您可以验证它是否有效:

let c: C;
c = { a1: 'a1', a2: 'a2' }; // okay
c = { a1: 'a1', a2: 'a2', b1: 'b1', b2: 'b2' }; // okay
c = { a1: 'a1', a2: 'a2', b2: 'b2' } // error!

Playground link to code

Typescript相关问答推荐

net::BER_RECTION_REUSED和Uncatch使用Axios和TanStack-Query useMutation时未捕获错误(DelivercMutation)

处理API响应中的日期对象

`((PrevState:NULL)=>;NULL)|null`是什么意思?

如何为父类构造函数中的修饰属性赋值?

输入元素是类型变体的对象数组的正确方法是什么?'

具有泛型类方法的类方法修饰符

使用动态主体初始化变量

是否使用非显式名称隔离在对象属性上声明的接口的内部类型?

有没有可能产生输出T,它在视觉上省略了T中的一些键?

Angular文件上传到Spring Boot失败,多部分边界拒绝

如何在NX工作区项目.json中设置类似angular.json的两个项目构建配置?

类型脚本可以推断哪个类型作为参数传递到联合类型中吗?

如何在typescript中为this关键字设置上下文

如何在省略一个参数的情况下从函数类型中提取参数类型?

如何通过转换器类继承使用多态将对象从一种类型转换为另一种类型

如何使函数参数数组不相交?

组件使用forwardRef类型脚本时传递props

如何在TypeScript中将元组与泛型一起使用?

Typescript 子类继承的方法允许参数中未定义的键

将对象数组传递给 Typescript 中的导入函数