Typescript: Property ‘prop’ does not exist on type ‘A | B’

Issue:

I am fetching data from an url and if a certain condition is met, the data is loaded inside a type B or its superclass A. When the data is loaded in B, typescript does not recognise its properties. I get the following error with the code below:

Property ‘doB’ does not exist on type ‘A’

class A {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    doA() {
        return "Hello, " + this.greeting;
    }
}
class B  extends A{
    greeting: string;
    constructor(message: string) {
        super(message)
        this.greeting = message;
    }
    doB() {
        return "Hello, " + this.greeting;
    }
}

let greeter: A|B  = new B("world");
greeter.doB()

Answer 1:

The error makes sense. How can you call doB with certainty if the defined type for var greeter is A or B (and A does not have member doB() defined)?

greeter is of type either A or B I am assuming. So why typescript does not allow me to call a method of B ?

Because greeter could also be an instance of A which would break type safety if the transpiler did allow it.

Having a type of A | B only allows you do access properties that exist on both.

Answer 2:

When you define a type as A|B, this is a Union Type in TypeScript.

When using a union type, typescript by default would only allow you to use the properties that are present on both the types. In this case, an example of that would be doA.

But if we can only access those, then the type won’t make much sense. To access a property that is only present on one of the instances, all you have to do is to make sure it has the correct instance type or Type Gaurd. In this case, that can be done with:

let greeter: A|B  = new B("world");
if(greeter instanceof B) {
    // Do just B things
} else if(greeter instanceof A) {
   // Do only A things
}

Leave a Reply

Your email address will not be published. Required fields are marked *