0

I came across the following unusual scenario:

I have two models, for the purposes of this discussion, let them be Car and Spaceship.

I wrote a component with an input defined by the following constraint: This input is an array that can either be of type Car or Spaceship, but not both. Thus, producing the following code:

@Component({
    selector: 'app-stack-example',
    ...
})
export class StackExample{
    @Input() listOfVehicles: Array<Car> | Array<Spaceship> = [];

...
}

From my understanding this should be valid code, since I never want it to receive a mixed array. After doing some dev with the input set up as such, I ran into the following issue:

When modifying/accessing the array in any way (push(), splice(), indexOf(), find(), findIndex(), etc), eg:

this.listOfVehicles.push(new Car());

I get the following error:

TS2349: Cannot invoke an expression whose type lacks a call signature. Type '((...items: Car[]) => number) | ((...items: Spaceship[]) => number)' has no compatible call signatures.

Why does this occur?

5
  • 1
    I don't think that is valid. In order to be able to push an instance of type Car you need listOfVehicles to be of concrete type Array<Car>, which is not guaranteed by the type of listOfVehicles as you define it. Commented Mar 25, 2018 at 17:10
  • @EduardMalakhov that makes sense. As H.B. suggested, I guess I'll just have to do something like declare it as Array<any> and initialize it as either new Array<Car> or <Spaceship> by means of another input. Ty! Commented Mar 25, 2018 at 17:13
  • 1
    To make your code more type-safe, you could declare a base class, e.g. Vehicle and then have both Car and Spaceship extend it, and make listOfVehicles of type Array<Vehicle>. Commented Mar 25, 2018 at 17:18
  • Ah yes, I've been contemplating that too, I could just have them inherit from a parent class since they have common fields... Commented Mar 25, 2018 at 17:25
  • 1
    GO ahead, from the OOP standpoint that would be the right way to go. Commented Mar 25, 2018 at 17:34

1 Answer 1

1

It is not apparent to the compiler from the code what type the array currently has. So before using functions on the array, you probably would have to check types or cast the array to one of the two array types.

Essentially, your argument is not assignable to both possible types push(item: Car) and push(item: Spaceship) at the same time.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.