The playground hover type annotation says aOrB is `A | B` at declaration and if you hover over aOrB in `if (hasTypeName(aOrB, "A"))` it produces `const aOrB: B`. Two types for 1 variable with no operations between. Not clear what operation is being performed on `aOrB`'s type that transforms it or if the playground type hover is just wrong.
> It would make more sense for TS to treat the body of the if-statement as unreachable and give a warning based on that, but I guess they figured that this kind of thing - doing a type guard on a value that is already known to be of a different type - is a very narrow corner case that isn't worth improving diagnostics for.
That does not seem to be the case, the type guard is not guarding what is in the if block, at least not consistently. It is not about the value being known at least, it is about the property being missing from what I can tell and the guards not being able to guard against it. If you have a top level `a` and `b` in both `A` and `B` there are no errors triggered:
type A = {
type: {
name: "A"
}
a: number,
b: undefined,
}
type B = {
type: {
name: "B"
}
b: number,
a: undefined,
}
const aOrB: A | B = {
type: {
name: "A"
},
a: 1,
b: undefined
};
// error as expect
if (aOrB.type.name === "B") {
console.log(aOrB.b) // Error
}
function hasTypeName<Name extends string>(a: { type: { name: string }}, name: Name): a is { type: { name: Name }} {
return a.type.name === name
}
if (hasTypeName(aOrB, "B")) {
console.log(aOrB.b) // no error
}
if (hasTypeName(aOrB, "A")) {
console.log(aOrB.a) // no error here as well
}
The guards not working or premature type narrowing(the inability to set a variable to a type and have typescript treat it as that type with the above type annotations).