假设定义了以下类型:

type A = {
  a: string,
}

type B = {
  a: number,
  b: number,
}

这两个赋值会产生错误:

// Not assignable to A because 'b' doesn't exist on A
const x: A = {
  a: 'hello',
  b: 10
}

// Not assignable to B because 'a' expects type 'string'
const x: B = {
  a: 'hello',
  b: 10
}

TypeScrip的文档将联合类型定义为:

联合类型是由两个或多个其他类型组成的类型,表示的值可以是这些类型中的任何一个.

基于此,我本以为下面的声明会产生错误:

const x: A | B = {
  a: 'hello',
  b: 10
}

但事实并非如此.从字面上看,该对象不能赋值给类型A,也不能赋值给类型B,但它却可以赋值给A | B.

我如何才能以一种使这个结果有意义的方式来考虑类型联合呢?

编辑:当然,我搜索了半天,找不到记录这件事的信息,但我一发帖,就发现这里有很多其他帖子在谈论同样的事情.

根据我所发现的,对象文本在被分配为类型联合时可以具有额外的属性,只要其中一个成员具有该属性.

如果我理解正确的话,我的对象字面量满足类型A,属性b是多余属性,这是允许的,因为联合的另一个成员(B)包括该属性.

为什么TypeScript的 struct 类型(即"鸭子类型")需要非严格类型联合?从我看到的与此相关的SO帖子的数量来看,似乎大多数人都希望类型联盟是严格的.我敢肯定,有一个令人信服的理由,非严格的unions 是默认的,有人能提供一些直觉,为什么会这样?

推荐答案

从类型理论的Angular 来看,TypeScrip使用 struct 类型("如果它的行为像一只鸭子,它就是一只鸭子"),并允许附加属性.结果是:

const x = {
  a: 'hello',
  b: 10
}
function doSomethingWithA(a: A) {}
// Works: x has shape type A = { a: string }
doSomethingWithA(x);
// Also works: Same reason
const y: A = x;

你的A | B任务也有类似的原因:

// Works: has shape { a: string } | { a: number, b: number }
const x: A | B = {
  a: 'hello',
  b: 10
}

对于定义了显式类型的对象文字的特定情况,TypeScrip有额外的处理:因为这是常见的潜在错误来源,所以它会在该特定情况下引发错误.见Microsoft/TypeScript/#3755,其中提供了安德斯·海尔斯伯格关于理由的更深入的解释:

关于对象文字(和数组文字)的一个有趣事实是,文字生成的对象引用是对该对象的唯一引用.因此,当将对象文字赋给变量或为其属性少于对象文字的类型的参数传递对象文字时,我们知道该信息将不可挽回地丢失.这是一个强烈的迹象,表明有些地方出了问题--可能比允许它所带来的好处更强烈.

有一个广受欢迎的功能请求为exact types,这可能有助于更严格地执行所有这些,但它还没有实现.

现在,如果我理解正确的话,TypeScript可以将其"不可赋值"的特殊情况从Microsoft/TypeScript/#3755扩展到union literals:它可能不是由于缺乏需求,实现复杂性或编译器性能影响的某种组合.(我还没有搜索GitHub问题,看看是否有人要求这样做.

Typescript相关问答推荐

Angular -使用Phone Directive将值粘贴到控件以格式化值时验证器不工作

使Typescribe强制所有对象具有相同的 struct ,从两个选项

rxjs forkJoin在错误后不会停止后续请求

在动态对话框中使用STEP组件实现布线

如何在TypeScrip中从字符串联合类型中省略%1值

如何根据特定操作隐藏按钮

编剧错误:正在等待Expect(Locator).toBeVisible()

我可以为情态车使用棱角形的路由守卫吗?

TypeScrip 5.3和5.4-对`Readonly<;[...number[],字符串]>;`的测试版处理:有什么变化?

在Typescript 中,有没有`index=unfined的速记?未定义:某个数组[索引]`?

根据类型脚本中的泛型属性 Select 类型

确保对象列表在编译时在类型脚本中具有唯一键

有没有办法防止类型交集绕过联合类型限制?

如何按属性或数字数组汇总对象数组

TYPE FOR ARRAY,其中每个泛型元素是单独的键类型对,然后在该数组上循环

Typescript,如何在通过属性存在过滤后重新分配类型?

如何避免多个类型参数重复?

基于泛型的类型脚本修改类型

类型脚本中函数重载中的类型推断问题

我应该使用服务方法(依赖于可观察的)在组件中进行计算吗?