It was my understanding that a type guard handling multiple types
instanceOfA(arg: A | B | C): arg is A
, would narrow the type to either A
(if the guard returns true
) or B | C
(if it returns false
)
However, in the case of instanceOfB
below, when returning false
the type seems to be narrowed to never
, while returning true
doesn't narrow it at all. Do type guards really only narrow the type if true
is returned? Or am I misinterpreting the outcomes, and if so, why does the narrowing to never
occur?
// 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')
}