Hint
The "in" type guard narrows a union by checking if a property exists. After "meow" in animal, TypeScript knows the value is the Cat variant because only Cat has meow. This works for both discriminated and non-discriminated unions.
// Simulate union type narrowing via 'in' operator
// type Animal = Cat | Dog
// Cat has meow(), Dog has bark()
function makeSound(animal) {
if ('meow' in animal) {
console.log('Cat says: ' + animal.meow());
} else if ('bark' in animal) {
console.log('Dog says: ' + animal.bark());
} else {
console.log('Unknown animal');
}
}
const cat = { meow: () => 'meow', lives: 9 };
const dog = { bark: () => 'woof', breed: 'Labrador' };
const fish = { swim: () => 'splash' };
makeSound(cat);
makeSound(dog);
makeSound(fish);Cat says: meow Dog says: woof Unknown animal
Explanation: "in" operator checks property existence at runtime. TypeScript uses the same pattern to narrow union types in conditional blocks.
Key Insight: The "in" type guard narrows a union by checking if a property exists. After "meow" in animal, TypeScript knows the value is the Cat variant because only Cat has meow. This works for both discriminated and non-discriminated unions.