Typescript class extends from other class 不能用作接口属性
Typescript class extends from other class cannot be used as interface attributes
我正在写一个对象接口,其中一个是一个属性值是一个class。但是当这个 class extends other classes.
时,ts 编译器会 抛出异常
这是一个简单的例子:
class Base {
key: string
}
class Foo extends Base { }
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: Foo // < Throws error here
}
错误内容:
Property 'key' is missing in type 'typeof Foo' but required in type 'Base'.ts(2741)
test.ts(39, 5): 'key' is declared here.
test.ts(51, 12): Did you mean to use 'new' with this expression?
当我删除 Foo
中的扩展时,错误消失了:
class Foo { } // < delete extends here
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: Foo // < No error throw
}
在我的理解中,Foo
扩展自Base
,所以它应该包含Base
中的相关属性,但编译器告诉我它没有。
那么有什么办法可以解决这个问题吗?
泛型错误
还有一个问题。当我在 Obj
上使用泛型时,因为有多个类型扩展 Base
。像这样:
class Foo extends Base { }
class Bar extends Base { }
interface Obj<T extends Base> {
list: Foo[]
value: typeof T // < Throws error here
}
const obj: Obj<Foo> = {
list: [new Foo()],
value: Foo
}
编译器会抛出如下异常:
'T' only refers to a type, but is being used as a value here.
有没有办法使通用定义更完整一些?
我使用的版本
- 节点
12.16.1
- typescript
3.8.3
和 4.3.4
key
是 class Base
中的必填字段。这就是那个错误的原因。您可以使 属性 key
可选或在 Base
和 Foo
.
中编写构造函数
使 key
属性 可选:
class Base {
key?: string
}
class Foo extends Base { }
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: new Foo()
}
强制执行 key
属性:
class Base {
key: string
constructor(key: string) {
this.key = key;
}
}
class Foo extends Base {
constructor(key: string) {
super(key);
}
}
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: new Foo()
}
此外,obj
初始化应该为 属性 value
做 new Foo()
或者 Obj
接口中 value
的类型应该是typeof Foo
.
value
在您的 Obj
界面中是 实例 Foo
class,而不是 class 本身。因此,将 value
属性 是 Foo
class 的对象分配给接口类型的变量是错误的。您应该将 value
设置为 Foo
的实例(例如 new Foo()
,这是编译器错误消息所建议的),或者如果您真的打算使用 Foo
,请声明value: typeof Foo
在 Obj
.
当 Foo
不扩展 Base
时它起作用的原因是 TypeScript 的结构类型:Foo
没有任何属性,所以 any 对象,包括 class,可以分配给该类型的变量,即使它在运行时可能不是 Foo
的实际实例。
回答关于泛型的附加问题:
当 T
是类型参数时,typeof T
无效,因为 T
不一定是 class。它可以是一个在结构上与 Base
兼容的接口,并且接口没有可以用 typeof
检索类型的“接口对象”。您可以使用 Obj
的这个定义,它有效但需要在使用站点使用 typeof
:
interface Obj<T extends new (...args: any[]) => Base> {
list: Foo[],
value: T
}
const obj: Obj<typeof Foo> = {
list: [new Foo()],
value: Foo
}
我正在写一个对象接口,其中一个是一个属性值是一个class。但是当这个 class extends other classes.
时,ts 编译器会 抛出异常这是一个简单的例子:
class Base {
key: string
}
class Foo extends Base { }
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: Foo // < Throws error here
}
错误内容:
Property 'key' is missing in type 'typeof Foo' but required in type 'Base'.ts(2741)
test.ts(39, 5): 'key' is declared here.
test.ts(51, 12): Did you mean to use 'new' with this expression?
当我删除 Foo
中的扩展时,错误消失了:
class Foo { } // < delete extends here
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: Foo // < No error throw
}
在我的理解中,Foo
扩展自Base
,所以它应该包含Base
中的相关属性,但编译器告诉我它没有。
那么有什么办法可以解决这个问题吗?
泛型错误
还有一个问题。当我在 Obj
上使用泛型时,因为有多个类型扩展 Base
。像这样:
class Foo extends Base { }
class Bar extends Base { }
interface Obj<T extends Base> {
list: Foo[]
value: typeof T // < Throws error here
}
const obj: Obj<Foo> = {
list: [new Foo()],
value: Foo
}
编译器会抛出如下异常:
'T' only refers to a type, but is being used as a value here.
有没有办法使通用定义更完整一些?
我使用的版本
- 节点
12.16.1
- typescript
3.8.3
和4.3.4
key
是 class Base
中的必填字段。这就是那个错误的原因。您可以使 属性 key
可选或在 Base
和 Foo
.
使 key
属性 可选:
class Base {
key?: string
}
class Foo extends Base { }
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: new Foo()
}
强制执行 key
属性:
class Base {
key: string
constructor(key: string) {
this.key = key;
}
}
class Foo extends Base {
constructor(key: string) {
super(key);
}
}
interface Obj {
list: Foo[]
value: Foo
}
const obj: Obj = {
list: [new Foo()],
value: new Foo()
}
此外,obj
初始化应该为 属性 value
做 new Foo()
或者 Obj
接口中 value
的类型应该是typeof Foo
.
value
在您的 Obj
界面中是 实例 Foo
class,而不是 class 本身。因此,将 value
属性 是 Foo
class 的对象分配给接口类型的变量是错误的。您应该将 value
设置为 Foo
的实例(例如 new Foo()
,这是编译器错误消息所建议的),或者如果您真的打算使用 Foo
,请声明value: typeof Foo
在 Obj
.
当 Foo
不扩展 Base
时它起作用的原因是 TypeScript 的结构类型:Foo
没有任何属性,所以 any 对象,包括 class,可以分配给该类型的变量,即使它在运行时可能不是 Foo
的实际实例。
回答关于泛型的附加问题:
当T
是类型参数时,typeof T
无效,因为 T
不一定是 class。它可以是一个在结构上与 Base
兼容的接口,并且接口没有可以用 typeof
检索类型的“接口对象”。您可以使用 Obj
的这个定义,它有效但需要在使用站点使用 typeof
:
interface Obj<T extends new (...args: any[]) => Base> {
list: Foo[],
value: T
}
const obj: Obj<typeof Foo> = {
list: [new Foo()],
value: Foo
}