如果我具有联合类型,则如何构造控制流以对该值进行操作,使其作为它包含的实际具体类型?有时我可以在运行时进行instanceof测试,然后将其强制转换,但这似乎既笨拙,不安全,也不总是可能的(您不能实例化类型数组)。当实际类型为并集时,如何安全地对值进行运算?
在下面的示例中,food.value
导致类型错误。有没有什么方法可以使编译器无需显式强制转换就可以理解这是{value:string}类型?
type FoodSet = (string | { value: string })[]
const myValues : FoodSet = [
"hamburger",
"cheeseburger",
{value: "salad"},
"fish",
{value: "quinoa"}
]
myValues.forEach(food => {
if (food instanceof String) {
console.log(food)
} else {
console.log(food.value) // <-- error here
}
})
我会喜欢
switch(typeof food) {
case string:
console.log(food)
case {value:string}:
console.log(food.value)
}
答案 0 :(得分:3)
您的初次尝试非常接近!问题是food instanceof String
不是完全正确:如果FoodSet
是(String | { value: string })[]
(请注意大写字母S
),这将是可行的。>
要检查food
是否为string
,应改用typeof food === "string"
。这样可以将else
分支中的类型正确地缩小为{ value: string }
:
type FoodSet = (string | { value: string })[]
const myValues : FoodSet = [
"hamburger",
"cheeseburger",
{value: "salad"},
"fish",
{value: "quinoa"}
]
myValues.forEach(food => {
if (typeof food === "string") {
console.log(food)
} else {
console.log(food.value)
}
})
答案 1 :(得分:1)
Javascsript很奇怪,而且TypeScript在设计上甚至没有尝试在运行时进行任何改进。在Javascript中,有两种字符串值-基本值和对象(or boxed strings)。
因此,您必须同时检查两者,或仅在代码中只使用一种字符串。通常的建议是完全避免使用String
类。您可以在javascript控制台中看到不同之处:
let primitiveString = 'a';
>
typeof primitiveString === 'string'
> true // note that the result of runtime `typeof` is a string
primitiveString instanceof String
> false // primitiveString was not created with the String() constructor, of course
let objectString = new String('a');
>
typeof objectString === 'string'
> false // typeof objectString returns 'object'
primitiveString instanceof String
> true
objectString === primitiveString
> false
objectString == primitiveString
> true
我会喜欢
switch(typeof food) {
case string:
console.log(food)
case {value:string}:
console.log(food.value)
}
TypeScript中有两个不同的typeof
运算符。
一个仅是编译时,它允许引用某些变量或函数的类型。
另一个是运行时typeof
,它是the same as in javascript,它返回的信息量非常有限,因为TypeScript不会在运行时生成任何类型的类型信息。
因此,每次要在运行时检查对象的类型时,都需要编写一系列if
语句,并根据情况进行不同类型的检查:
typeof
,如果您要检查诸如string
,number
,booelan
,function
或{{ 1}}(object
的意思是“其他”)
object
,如果您想知道使用哪个构造函数创建对象(请注意,如果该值是作为对象文字创建的,它将是instanceof
的实例,但是可能很好地与某些类兼容,因为对象文字也可以具有方法)
Object
运算符,如果要检查对象has some property or method
in
检查某物是否为数组
以此类推。
编译器在您的代码中检测到错误
Array.isArray()
因为对于原始字符串myValues.forEach(food => {
if (food instanceof String) {
console.log(food)
} else {
console.log(food.value) // <-- error here
}
})
将为false,所以将执行instanceof String
分支以尝试访问字符串上不存在的false
属性。检查字符串类型的常用方法是
value
如另一个答案所述。
答案 2 :(得分:1)
https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
我想要的是用户定义的类型警卫
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}