我的印象是,接受多个类型instanceOfA(arg: A | B | C): arg is A的类型保护会将类型限制为A (当保护返回true时)或B | C (当保护返回false时)。
然而,对于下面的instanceOfB,返回false似乎会将类型缩小到never,而true根本不会缩小。类型保护实际上是否只在返回true时缩小类型范围?或者我误解了结果,在这种情况下,为什么会缩小到never?
// Structures
interface A {
value: string
children: B[]
}
interface B {
value: string
}
// Example functions
function doSomething1(arg: A | B) {
if (instanceOfA(arg)) {
console.log(`A: ${arg.value}`) // Type of arg is A
} else {
console.log(`B: ${arg.value}`) // Type of arg is B
}
}
function doSomething2(arg: A | B) {
if (instanceOfB(arg)) {
console.log(`B: ${arg.value}`) // Type of arg is A | B
} else {
console.log(`A: ${arg.value}`) // Type of arg is never
}
}
// Typeguards
function instanceOfA(ab: A | B): ab is A {
return ab.hasOwnProperty('children')
}
function instanceOfB(ab: A | B): ab is B {
return !ab.hasOwnProperty('children')
}发布于 2021-09-29 15:50:59
问题是,这是一个理论问题,还是你有一个现实世界的问题?如果是第二个,我会说通过没有什么属性来识别一个类型是错误的。
如果你阅读the narrowing section in the typescript book,他们有一个例子,他们使用类型保护来通过检查宠物是否会游泳来区分Fish和Bird (这本身就是一个相当宽松的假设)。但你所做的(转换成鸟,鱼的例子)基本上是在说:“如果它不会游泳,它一定是一只鸟”。这样做似乎不是特别合乎逻辑(正如评论中指出的那样,如果只有鱼和鸟可供选择,这个假设是有效的)。
我不认为instanceOfB是明智的。TypeScript允许将不同的类型分配给彼此,如果它们有足够的重叠,并且A总是可以分配给B,因为它完全覆盖了它拥有的所有属性。一旦你给B添加了一些A没有的属性,这个问题就会消失。
例如,这将是非常好的typescript:
const a: A = {value: 'this is a', children: []};
const b: B = {value: 'this is b'};
function printValue(subject: {value: string}) {
console.log(subject.value);
}如果你这样做(例如),你的支票就会开始工作:
interface B {
value: string
other: string;
}https://stackoverflow.com/questions/69379200
复制相似问题