Typescript交叉类型出现never的场景?

示例1 中交叉类型结果为never,是为啥呢?

// 示例1
type DataTypeNever = {
  d: true;
  e: number;
} & {
  d: false;
  e: number;
}

let data: DataTypeNever = (() => {
  throw new Error
})()

示例2 中交叉类型结果为{ d: false, e: never },为何和示例1不同呢?

// 示例2
type DataType = {
  d: false;
  e: number;
} & {
  d: false;
  e: string;
}

let data: DataType = {
    d: false,
    e: (() => {
      throw new Error
    })()
}
阅读 3.3k
2 个回答

我在stackoverflow里也提了相同的问题,根据有个朋友的回答找到了对应的Typescript的PR ,大家可以参考下
用百度翻译大概翻译了PR的描述部分,以下是翻译的部分:

长期以来,我们一直推测,如果对象类型中存在无法判定可以交叉的类型属性的交叉结果应该为never类型,因为这种类型的对象不可能构造。该PR最终实现了该功能。

除了在#31838中实现的交叉类型外,交叉类型T1 & T2 & ... & Tn在满足下述条件时相当于never类型

  • 两个或多个Tx类型具有相同名称的属性
  • 在至少一组具有相同名称的属性中,某些属性具有字面量(literal type)类型,并且该属性不具有never类型
  • 这组属性类型的交集是never类型

例子:

type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: string };
type C = { kind: number, foo: string };
type D = { kind: never, foo: string };
type E = { kind: 'a', foo: number };

type AB = A & B;  // never
type BC = B & C;  // never
type AD = A & D;  // { kind: never, foo: string }
type AE = A & E;  // { kind: never, foo: never }

因为赋值的这个函数中断了没有返回值,所以是never类型。
它赋值给谁,谁就是never类型。
第一个是整体赋值给了data,所以data是never,
第二个只是赋值给了data.e,所以data.e是never。

关于never的含义,与void区别,可以自行查一下。

补充

这类&符号的额意思是

An intersection type combines multiple types into one. This allows you to add together existing types to get a single type that has all the features you need. For example, Person & Serializable & Loggable is a Person and Serializable and Loggable. That means an object of this type will have all members of all three types.

第一个式子,d是常量,常量有2个不同的值,这是矛盾的。没有确定的类型,所以是never,如果把里面的字段改成不一样,就不会是never了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题