TL;DR Differentiation between link1 (Operational) vs link2 (not functional)
TypeGuard
function validateAllProperties<T>(obj: any, props: (keyof T)[]): obj is T {
return props.every((prop) => obj.hasOwnProperty(prop))
}
Consider a variable msg
that can be of 2 varieties - kind1
or kind2
.
interface kind1 {
propertyA: number
}
interface kind2 {
propertyB: number
}
let msg: any = {
propertyA: 1
}
In link1 the type guard is accessed directly and functions correctly as expected.
In link2 a boolean variable isKind1
is initially set to false and only changes to true if the type guard check is passed.
let isKind1 = false
let isKind2 = false
// Check msg properties
if (
validateAllProperties<kind1>(msg, [
"propertyA",
])
) {
console.log("Type: Kind1")
isKind1 = true
} else if (
validateAllProperties<kind2>(msg, [
"propertyB",
])
) {
console.log("Type: Kind2")
isKind2=true
} else {
throw `invalid ❌`
}
console.log("Check passed ✅")
Hence in link2 , I cannot envision a scenario where if isKind1 === true
but msg
is not of type kind1
if (isKind1) {
// Why is msg not exclusively of type kind1
console.log(msg.propertyA)
}