Type Guards and Narrowing
In Operator Guard
The in operator checks whether an object has a property and narrows the union.
property guard
`"address" in value` narrows a union to the object shape that owns that property.
In Operator Guard
in_guard.ts
Replay: real traced execution (multi-file project)
type EmailContact = {
address: string;
};
type SmsContact = {
phone: string;
};
function routeContact(contact: EmailContact | SmsContact): string {
if ("address" in contact) {
return `email:${contact.address}`;
}
return `sms:${contact.phone}`;
}
const channel: string = "email";
const contact: EmailContact | SmsContact =
channel === "email"
? { address: "ada@example.com" }
: { phone: "555-0100" };
console.log(routeContact(contact));
type EmailContact = {
address: string;
};
type SmsContact = {
phone: string;
};
function routeContact(contact: EmailContact | SmsContact): string {
if ("address" in contact) {
return `email:${contact.address}`;
}
return `sms:${contact.phone}`;
}
const channel: string = "sms";
const contact: EmailContact | SmsContact =
channel === "email"
? { address: "ada@example.com" }
: { phone: "555-0100" };
console.log(routeContact(contact));
channel ← email, contact ← [object Object]
13 return `sms:${contact.phone}`;14}1516const channel→ email: string = "email"; //@channel="sms"17const contact→ [object Object]: EmailContact | SmsContact =18 channel === "email"19 ? { address: "ada@example.com" }20 : { phone: "555-0100" };2122console.log(routeContact(contact[object Object]));function routeContact(contact: EmailContact | SmsContact): string
6 phone: string;7};89function routeContact(contact[object Object]: EmailContact | SmsContact): string {10 if ("address" in contact) {if ("address" in contact)
9function routeContact(contact: EmailContact | SmsContact): string {10 if ("address" in contact[object Object]) {11 return `email:${contact.addressada@example.com}`;12 }console.log(routeContact(contact));
19 ? { address: "ada@example.com" }20 : { phone: "555-0100" };2122console.log(routeContact(contact[object Object]));outputemail:ada@example.com
channel ← sms, contact ← [object Object]
13 return `sms:${contact.phone}`;14}1516const channel→ sms: string = "sms";17const contact→ [object Object]: EmailContact | SmsContact =18 channel === "email"19 ? { address: "ada@example.com" }20 : { phone: "555-0100" };2122console.log(routeContact(contact[object Object]));function routeContact(contact: EmailContact | SmsContact): string
6 phone: string;7};89function routeContact(contact[object Object]: EmailContact | SmsContact): string {10 if ("address" in contact) {11 return `email:${contact.address}`;12 }13 return `sms:${contact.phone555-0100}`;14}console.log(routeContact(contact));
19 ? { address: "ada@example.com" }20 : { phone: "555-0100" };2122console.log(routeContact(contact[object Object]));outputsms:555-0100