Reputation: 826
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?
Upvotes: 1
Views: 2067
Reputation: 164417
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"); }
}];
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
).
Upvotes: 3
Reputation: 251242
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];
Upvotes: 3