Ziv Glazer Ziv Glazer - 17 days ago 5
TypeScript Question

array with interface as type (polymorphism with interfaces)

I'm trying to create an array of objects, where all objects implement the interface Foo. Here is a simplified example to demonstrate the problem:

interface Foo {
fooAction(): any;
}

class Bar implements Foo
{
public fooAction() {
return "nothing important";
}
}

let arrayThatINeed : Foo[] = [Bar]; // Type error: Type Bar[] is not
// assigable to type 'Foo[]'


Shouldn't this behavior be supported? If not, what are the alternatives to code such behavior?

Answer

You're adding the class to your array instead of the instance of that class.
Should be:

let arrayThatINeed : Foo[] = [new Bar()];

This will also work:

let arrayThatINeed : Foo[] = [{
    fooAction: () => { console.log("yo"); }
}];

Edit

I'm not an angular developer so I can't relate to that, but if I understand you correctly then you need an array of classes and not instances, which in javascript means that you need an array of constructors.

That's easy to do in typescript:

interface FooConstructor {
    new (): Foo;
}

interface Foo {
    fooAction(): any;
}

class Bar implements Foo {
    public fooAction() {
        return "nothing important";
    }
}

let arrayThatINeed : FooConstructor[] = [Bar];

You'll see that this code doesn't result in errors, but it's not correct either because that it won't complain even if you remove the implements part from the Bar class.
I can find reasons for why that's the case, but I think that the compiler should complain about it none the less.

You can solve that if you make Foo a class, for example:

interface FooConstructor {
    new (): Foo;
}

abstract class Foo {
    abstract fooAction(): any;
    fn() {}
}

class Bar extends Foo {
    public fooAction() {
        return "nothing important";
    }
}

let arrayThatINeed : FooConstructor[] = [Bar];

Now if you remove the extends part from Bar you'll get an error.
But you must have at least one non-abstract method/member in Foo for it to work (that is, it will complain if what's in the array isn't a class extending Foo).