typescript - 为什么 TypeScript 中的 & 运算符过滤联合类型但连接对象类型?
问题描述
我在学习 TypeScript 时遇到了下面的代码,我不明白为什么&
运算符仅在与联合类型一起使用时才返回'apple'
,但似乎连接对象类型,这可以通过它"name" | "age" | "address" | "year"
在从结果类型中获取键时返回联合来证明。
type fruits = 'apple' | 'pear' | 'tomato'
type vegetables = 'spinach' | 'cabbage' | 'tomato';
type gardenPlants = fruits & vegetables;
type Employee = { name: string; age: number }
type Company = { name: string, address: string, year: number}
type Info = keyof (Employee & Company);
解决方案
如果您有两种类型A
和B
,那么交集类型 A & B
的值必须是类型的值,A
也是类型的值B
。这是一个交集,因为如果您将所有类型的值A
和所有类型的值想象为欧拉图(通常称为“维恩图”,尽管有点用词不当)中的B
圆圈,那么类型的值将是那些在圆圈重叠的交叉点。A & B
这在 TypeScript 中产生了一些有趣的结果,因为根据您是在考虑原语还是对象,还是对象键或值,在某些人看来,它可能会倒退。(这可能是由于运算符是keyof
逆变的,但我离题了。)
type Fruits = 'apple' | 'pear' | 'tomato'
type Vegetables = 'spinach' | 'cabbage' | 'tomato';
type GardenPlants = Fruits & Vegetables;
// type GardenPlants = "tomato"
在这里,您的Fruits
类型和Vegetable
类型包含有限数量的特定字符串文字元素,它们之间只有一个是共同的。交点是这样"tomato"
。
对于对象类型,这可能会更令人困惑。重要的是要注意 TypeScript 中的对象类型是开放和可扩展的;like 类型的值{a: string}
必须包含string
-valueda
属性,但它可以包含任何其他未提及的属性。这通常很有用,因为否则继承层次结构interface A { x: string }; interface B extends A { y: number }
将无法形成类型层次结构。对象类型不是封闭的或精确的(请参阅microsoft/TypeScript#12936以了解引入精确类型的功能请求,以及多余的属性检查有时会欺骗人们认为对象类型是精确的特征)。
那么,给定
type Employee = { name: string; age: number }
type Company = { name: string, address: string, year: number }
考虑他的交叉点:
type CorporationsArePeopleToo = Employee & Company;
type 的值CorporationsArePeopleToo
必须同时是 anEmployee
和a Company
。对象类型是开放的,所以语言中没有说 anEmployee
不能有 anaddress
和 a year
,也没有说 aCompany
不能有 an age
。因此,如果某事物具有 的所有属性Employee
和 的所有属性Company
,则它既是Employee
又是Company
,因此也是CorporationsArePeopleToo
。您可以使用映射类型让编译器为您拼写出来:
type Expanded = { [K in keyof CorporationsArePeopleToo]:
CorporationsArePeopleToo[K] };
/* type Expanded = {
name: string;
age: number;
address: string;
year: number;
} */
因此 a具有和的CorporationsArePeopleToo
所有键:Company
Employee
type Info = keyof CorporationsArePeopleToo;
// type Info = "name" | "age" | "address" | "year"
如果您经历过这种“嘿,那是倒退”的想法,那是因为您正在考虑属性而不是值。和keyof (A & B)
是一样的(keyof A) | (keyof B)
。由于keyof
是逆变的,它将交集变成并集,反之亦然。
推荐阅读
- smalltalk - 在 Centos 7.4x 上将 OSSubprocess 添加到我的 Pharo 6.1 时出错
- c# - 如何从配置文件加载统一设置?
- docker - Docker ubuntu cron 尾部日志不可见
- javascript - 使用 CSS API 在 Material UI Stepper 中覆盖 CSS 样式
- c++ - c++ strftime 我不知道的东西
- wordpress - 图像未在 wordpress 中加载
- mysql - 如何仅在 mysql 中将此日期转换为 unix 时间戳?
- ruby - Erc20 代币在 ruby 上存款/取款
- python-3.x - 在 Python 中附加到合并的异步生成器
- python - pyODBC 语句似乎正在运行但不影响表