https://www.typescriptlang.org/docs/handbook/advanced-types.html
Union types are useful for modeling situations when values can overlap in the types can take on. What happens when we need to know specifically whether we have a Fish
? A common idiom in JavaScript to differentiate between two possible values is to check for the presence of a member. As we mentioned, you can only access members that are guaranteed to be in all the constituents of a union type.
[*// Try it out on TypeScript Playground*](<https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgELCgE2QbwFDKHIwA2AngBQCUAXMgG4D2wmA3AUSXGQKIDmfAM7U6TFuwC+ePKEixEKAGLBBAC1wdCggO7AAtiIbM2m5F14DhtI+LxS8mCAi5QUMAK4gEYYIxDI+CDAAZT04EhIABSDDZTVkAB80DBM8BD9BMGQAByDkAF4AoNDwqJiqdjxcsAA6c34hakrgGAocoLruBsFkKg0iZHSQQUYSCDrGPjaARl7JaWrOi0aKhY6dfSbpFraAcg29XeRQdqy+-AHFg637HdOa0jJe-qJFx5vpIcziFVVorMK1WQcB6cVUlRgv3+NWuqxkrR+amhB2eFyIkKR610BlWEiAA>)
interface Bird {
fly(): void;
layEggs(): void;
}
interface Fish {
swim(): void;
layEggs(): void;
}
declare function getSmallPet(): Fish | Bird;
const pet = getSmallPet();
pet.layEggs();
// This condition will always return true since the function is always defined. Did you mean to call it instead?(2774)
if( pet.layEggs ) {
console.log( 1 );
}
pet.layEggs();
// Property 'swim' does not exist on type 'Bird | Fish'.
// Property 'swim' does not exist on type 'Bird'.(2339)
pet.swim();
if( 'swim' in pet ) {
pet.swim();
}
// Property 'fly' does not exist on type 'Bird | Fish'.
// Property 'fly' does not exist on type 'Fish'.(2339)
if( pet.fly ) {
// Property 'fly' does not exist on type 'Bird | Fish'.
// Property 'fly' does not exist on type 'Fish'.(2339)
pet.fly();
}
const fishPet = pet as Fish;
fishPet.swim();
if( fishPet.swim ) {
fishPet.swim();
}
It just so happens that TypeScript has something called a type guard . A type guard is some expression that performs a runtime check that guarantees the type in some scope.
function isFish( pet: Fish | Bird ): pet is Fish {
return ( pet as Fish ).swim !== undefined;
}
export default ( x: unknown ): x is Error => ( {} ).toString.call( x ) === '[object Error]';
if( 'swim' in pet ) {
return pet.swim)(;
}
if( typeof x === 'number' ) {
x.slice( 1 );
}
if( pet instanceof Birt ) {
pet.fly();
}
The right side of the instanceof
needs to be a constructor function, and TypeScript will narrow down to:
prototype
property if its type is not any
.in that order.