使用联合类型
提供与联合类型匹配的值很容易 - 只需提供与联合的任何成员匹配的类型即可。 如果你有一个联合类型的值,你如何处理它?
It's easy to provide a value matching a union type - simply provide a type matching any of the union's members. If you have a value of a union type, how do you work with it?
TypeScript 只有在对联合的每个成员都有效的情况下才允许操作。
例如,如果您有联合 string | number
,则不能使用仅在 string
上可用的方法:
TypeScript will only allow an operation if it is valid for every member of the union.
For example, if you have the union string | number
, you can't use methods that are only available on string
:
function printId(id: number | string) {
console.log(id.toUpperCase());
}
解决方案是用代码缩小联合,就像在没有类型注释的 JavaScript 中一样。 当 TypeScript 可以根据代码的结构为某个值推断出更具体的类型时,就会发生缩小。
The solution is to narrow the union with code, the same as you would in JavaScript without type annotations. Narrowing occurs when TypeScript can deduce a more specific type for a value based on the structure of the code.
例如,TypeScript 知道只有 string
值才会有 typeof
值 "string"
:
For example, TypeScript knows that only a string
value will have a typeof
value "string"
:
function printId(id: number | string) {
if (typeof id === "string") {
// In this branch, id is of type 'string'
console.log(id.toUpperCase());
} else {
// Here, id is of type 'number'
console.log(id);
}
}
另一个例子是使用像 Array.isArray
这样的函数:
Another example is to use a function like Array.isArray
:
function welcomePeople(x: string[] | string) {
if (Array.isArray(x)) {
// Here: 'x' is 'string[]'
console.log("Hello, " + x.join(" and "));
} else {
// Here: 'x' is 'string'
console.log("Welcome lone traveler " + x);
}
}
请注意,在 else
分支中,我们不需要做任何特别的事情——如果 x
不是 string[]
,那么它一定是 string
。
Notice that in the else
branch, we don't need to do anything special - if x
wasn't a string[]
, then it must have been a string
.
有时你会有一个联合,所有成员都有共同点。
例如,数组和字符串都有一个 slice
方法。
如果联合中的每个成员都有一个共同的属性,则可以使用该属性而不会缩小类型:
Sometimes you'll have a union where all the members have something in common.
For example, both arrays and strings have a slice
method.
If every member in a union has a property in common, you can use that property without narrowing:
// Return type is inferred as number[] | string
function getFirstThree(x: number[] | string) {
return x.slice(0, 3);
}
类型的联合似乎具有这些类型的属性的交集,这可能会令人困惑。 这不是偶然的——联合这个名字来源于类型论。 联合
number | string
是通过取每种类型的值的联合组成的。 请注意,给定两个具有关于每个集合的相应事实的集合,只有这些事实的交集适用于集合本身的并集。 例如,如果我们有一个房间里有戴帽子的高个子,而另一个房间里有戴帽子的说西班牙语的人,在组合这些房间后,我们对每个人的唯一了解就是他们必须戴帽子。It might be confusing that a union of types appears to have the intersection of those types' properties. This is not an accident - the name union comes from type theory. The union
number | string
is composed by taking the union of the values from each type. Notice that given two sets with corresponding facts about each set, only the intersection of those facts applies to the union of the sets themselves. For example, if we had a room of tall people wearing hats, and another room of Spanish speakers wearing hats, after combining those rooms, the only thing we know about every person is that they must be wearing a hat.