1

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?

2 Answers 2

3

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).

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

2 Comments

You are correct, but this behaviour is needed for me in angular 2. angular components accept an array of classes that are decoraterd with the directive decorator. But in my specific case, all of these directives im trying to give to angular are all implements the Validator interface. angular needs the class defeitions and not objects as it creates instances when he needs to. I was wondering if there was a way to achieve this behavior of an array of classes functions (and not objects) which all implement this interface (right now im using "any" which is not that all bad but I do like typing)
Very nice explanation:) Weird that the first code sample wont complain if you remove the implements but I guessthat if you remove the doAction from bar than it will complain which is good. The second example is not really useable for as I already inherit from some other class
3

If you expect the array items to satisfy the Foo[] interface, items need to satisfy an object with the properties of a Foo (i.e. the method fooAction). Until you instantiate an instance of Bar, it does not satisfy the interface.

var barInstance = new Bar();

let items: Foo[] = [ barInstance ];

If you want the array to contain Foo types, not instantiated classes, you can create a type to represent that - if you make Foo an abstract class.

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

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

type FooType = typeof Foo;

let arrayThatINeed : FooType[] = [Bar];

1 Comment

You are correct, but this behaviour is needed for me in angular 2. angular components accept an array of classes that are decoraterd with the directive decorator. But in my specific case, all of these directives im trying to give to angular are all implements the Validator interface. angular needs the class defeitions and not objects as it creates instances when he needs to. I was wondering if there was a way to achieve this behavior of an array of classes functions (and not objects) which all implement this interface (right now im using "any" which is not that all bad but I do like typing)

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.