Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if property exists if obj is one of types

Tags:

typescript

Let's say I have few interfaces A, B, C implementing common Base.

interface Base {
    x: number;
    y: number;
    z: number;
}

interface A extends Base {
    a: true;
}

interface B extends Base {
    b: true;
}

interface C extends Base {
    C: true;
}

And function with if statements:

function foo(arg: A|B|C){
    if(arg.a!==undefined){//throws type error
        //do stuff for type a
    } else if(arg.b !== undefined){//throws type error
        //do stuff for type b
    } else if(arg.c !== undefined){ //throws type error
        //do stuff for type c
    }
}

How to correctly check if property exists? I don't wan't to use any type. Is //@ts-ignore only option?

like image 448
Zydnar Avatar asked Apr 11 '19 20:04

Zydnar


People also ask

How can I check if object obj has property prop?

The hasOwnProperty() method will check if an object contains a direct property and will return true or false if it exists or not. The hasOwnProperty() method will only return true for direct properties and not inherited properties from the prototype chain.

How do you find whether an object has property or not?

The hasOwnProperty() method returns true if the specified property is a direct property of the object — even if the value is null or undefined . The method returns false if the property is inherited, or has not been declared at all.

How do you check if a property exists in an array of objects?

Using includes() Method: If array contains an object/element can be determined by using includes() method. This method returns true if the array contains the object/element else return false. Example: html.

How many types of object property exists?

Objects have two types of properties: data and accessor properties.


2 Answers

Typescript will only allow access to common properties. Since the properties you test are not common to all members of the union, typescript will not let you access them.

You can use an in type guard instead to test for the presence of the property.

interface Base {
    x: number;
    y: number;
    z: number;
}

interface A extends Base {
    a: true;
}

interface B extends Base {
    b: true;
}

interface C extends Base {
    C: true;
}

function foo(arg: A|B|C){
    if('a' in arg){
        arg.a
    } else if('b' in arg){
        arg.b
    } else { 
        arg.C
    }
}
like image 108
Titian Cernicova-Dragomir Avatar answered Nov 15 '22 11:11

Titian Cernicova-Dragomir


You can use a type guard:

function isA(arg: A | B | C): arg is A {
    return (<A>arg).a !== undefined;
}

function isB(arg: A | B | C): arg is B {
    return (<B>arg).b !== undefined;
}

function foo(arg: A | B | C) {
    if (isA(arg)) {
        // do stuff for type a
    } else if (isB(arg)) {
        // do stuff for type b
    } else {
        // do stuff for type c
    }
}
like image 38
jo_va Avatar answered Nov 15 '22 11:11

jo_va