Ammar Ahmed
Ammar Ahmed

Reputation: 474

How can I assign types for an array of objects that extend the same class?

This might be a stupid question as I'm new to typescript, however, I have the following scenario. I have an array that contains objects that all extend the same class. For example:

class Body{
 // implementation
}

class Rectangle extends Body{
 // implementation
}

class Circle extends Body{
 // implementation
}

const box: Rectangle = new Rectangle()
const circle: Circle = new Circle()

const world: Array<Body> = [box, circle]

The problem I have is that when I am accessing methods on the elements in the array, I'm getting an error that they don't exist on the Body class (which they don't). I'm wondering if there is a correct way to do this or if I am doing something completely wrong?

Upvotes: 0

Views: 746

Answers (3)

Alexey Romanov
Alexey Romanov

Reputation: 170745

Though in most cases you do want either Alex Wayne's or Uroš Anđelić's approaches, there is also

const world = [box, circle] as const;

in which case the type of world will be inferred as [Box, Circle] and you can call Box's methods on world[0].

Upvotes: 0

Uroš Anđelić
Uroš Anđelić

Reputation: 1174

You should try to create abstract methods in the Body class that can be implemented by subclasses. This way you would have different behaviour but same methods - polymorphism. F.e.:

abstract class Body {
  abstract area(): number;
}

and then subclasses can have the implementation.

If it does not make sense to have same method names in different classes, then you must check the object's class with instanceof as Alex Wayne said.

Upvotes: 1

Alex Wayne
Alex Wayne

Reputation: 187034

Array<Body> says that the array elements are only guaranteed to implement the Body interface.

If you want to have an array of Body instances that might be subclasses, then you have to do a runtime check first to make sure the object is what you expect it to be.

const world: Array<Body> = [box, circle]

if (world[0] instanceof Rectangle) {
    world[0].someRectangleOnlyMethod()
}

This is required because this would crash since that method wouldn't exist on Circle instances:

world[1].someRectangleOnlyMethod() // crash

Playground

Upvotes: 1

Related Questions