以接口为类型的数组(带接口的多态性)
array with interface as type (polymorphism with interfaces)
我正在尝试创建一个对象数组,其中所有对象都实现接口 Foo。这是一个演示问题的简化示例:
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[]'
不应该支持这种行为吗?如果不是,有什么替代方法可以对此类行为进行编码?
您正在将 class 添加到您的数组而不是 class 的实例。
应该是:
let arrayThatINeed : Foo[] = [new Bar()];
这也有效:
let arrayThatINeed : Foo[] = [{
fooAction: () => { console.log("yo"); }
}];
编辑
我不是 angular 开发人员,所以我无法理解这一点,但如果我对你的理解正确,那么你需要一个 class 数组而不是实例,它在 javascript 意味着你需要一个构造函数数组。
这在打字稿中很容易做到:
interface FooConstructor {
new (): Foo;
}
interface Foo {
fooAction(): any;
}
class Bar implements Foo {
public fooAction() {
return "nothing important";
}
}
let arrayThatINeed : FooConstructor[] = [Bar];
您会看到此代码不会导致错误,但它也不正确,因为即使您从 Bar
中删除 implements
部分,它也不会报错 class.
我可以找到为什么会这样的原因,但我认为编译器应该抱怨它 none 更少。
如果将 Foo
设为 class 就可以解决这个问题,例如:
interface FooConstructor {
new (): Foo;
}
abstract class Foo {
abstract fooAction(): any;
fn() {}
}
class Bar extends Foo {
public fooAction() {
return "nothing important";
}
}
let arrayThatINeed : FooConstructor[] = [Bar];
现在,如果您从 Bar
中删除 extends
部分,则会出现错误。
但是你必须在 Foo
中至少有一个非抽象的 method/member 才能工作(也就是说,如果数组中的内容不是 class 扩展 Foo
).
如果您希望数组项满足 Foo[]
接口,则项需要满足具有 Foo
属性的对象(即方法 fooAction
)。直到你实例化一个Bar
的实例,它才不满足接口
var barInstance = new Bar();
let items: Foo[] = [ barInstance ];
如果您希望数组包含 Foo
类型,而不是实例化的 classes,您可以创建一个类型来表示它 - 如果您将 Foo
设为抽象 class.
abstract class Foo {
abstract fooAction(): any;
}
class Bar extends Foo {
public fooAction() {
return "nothing important";
}
}
type FooType = typeof Foo;
let arrayThatINeed : FooType[] = [Bar];
我正在尝试创建一个对象数组,其中所有对象都实现接口 Foo。这是一个演示问题的简化示例:
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[]'
不应该支持这种行为吗?如果不是,有什么替代方法可以对此类行为进行编码?
您正在将 class 添加到您的数组而不是 class 的实例。
应该是:
let arrayThatINeed : Foo[] = [new Bar()];
这也有效:
let arrayThatINeed : Foo[] = [{
fooAction: () => { console.log("yo"); }
}];
编辑
我不是 angular 开发人员,所以我无法理解这一点,但如果我对你的理解正确,那么你需要一个 class 数组而不是实例,它在 javascript 意味着你需要一个构造函数数组。
这在打字稿中很容易做到:
interface FooConstructor {
new (): Foo;
}
interface Foo {
fooAction(): any;
}
class Bar implements Foo {
public fooAction() {
return "nothing important";
}
}
let arrayThatINeed : FooConstructor[] = [Bar];
您会看到此代码不会导致错误,但它也不正确,因为即使您从 Bar
中删除 implements
部分,它也不会报错 class.
我可以找到为什么会这样的原因,但我认为编译器应该抱怨它 none 更少。
如果将 Foo
设为 class 就可以解决这个问题,例如:
interface FooConstructor {
new (): Foo;
}
abstract class Foo {
abstract fooAction(): any;
fn() {}
}
class Bar extends Foo {
public fooAction() {
return "nothing important";
}
}
let arrayThatINeed : FooConstructor[] = [Bar];
现在,如果您从 Bar
中删除 extends
部分,则会出现错误。
但是你必须在 Foo
中至少有一个非抽象的 method/member 才能工作(也就是说,如果数组中的内容不是 class 扩展 Foo
).
如果您希望数组项满足 Foo[]
接口,则项需要满足具有 Foo
属性的对象(即方法 fooAction
)。直到你实例化一个Bar
的实例,它才不满足接口
var barInstance = new Bar();
let items: Foo[] = [ barInstance ];
如果您希望数组包含 Foo
类型,而不是实例化的 classes,您可以创建一个类型来表示它 - 如果您将 Foo
设为抽象 class.
abstract class Foo {
abstract fooAction(): any;
}
class Bar extends Foo {
public fooAction() {
return "nothing important";
}
}
type FooType = typeof Foo;
let arrayThatINeed : FooType[] = [Bar];