如何解决如何在抽象父类中为实现打字稿创建通用方法?
在 TypeScript 中实现这一点的最佳和(适当)方法是什么?
$Foo.getInstance('uid')
应该根据实现返回 FooInstance
吗?
我希望在抽象类 Entity
中有一个从池中获取实例的方法,
用于返回已实现的 EntityInstance
。
abstract class Entity {
abstract Instance: Partial<typeof EntityInstance>;
instances: { [uid: string]: EntityInstance } = {};
getInstance (uid: string ) {
return this.instances[uid]
}
}
abstract class EntityInstance {
prop='';
}
class Foo extends Entity {
Instance = FooInstance // @implementation
}
class FooInstance extends EntityInstance {
}
const $Foo = new Foo();
// need return InstanceType<FooInstance>
const instance = $Foo.getInstance('uid');
这里的例子:
const instance = $Foo.getInstance('uid')
应该是 FooInstance
;
但它实际上是一个 EntityInstance
是正确的!
所以我试着把这个方法 getInstance
改成这样。
getInstance <t=this>(uid: string ): InstanceType<this['Instance']> {
return this.instances[uid]
}
它可以工作!:)但会产生一些错误类型。 我是 ts 文档的菜鸟,我可以进行哪些更改以使此逻辑正常工作。 我知道 ts 很强大,但我不知道如何在我的 ide 中使这个工作正常进行智能。
最小繁殖演示typescript
我希望 myInstance.__foo2;
不产生错误。
解决方法
您可以尝试将 Entity
中的类型更改为以下内容:
abstract class Entity {
abstract Instance: new () => EntityInstance;
instances: Record<string,InstanceType<this["Instance"]> | undefined
> = {};
}
Instance
属性是一个 constructor,它返回一个 EntityInstance
(或其子类型)。而 instances
属性类型取决于 Instance
的类型;通过使用 polymorphic this
,我们表示对于 Entity
的任何子类,instances
属性将取决于同一子类中 Instance
的类型。
这为您提供了您正在寻找的行为,至少对于示例代码:
class Foo extends Entity {
Instance = FooInstance;
}
class FooInstance extends EntityInstance {
__foo2 = 2;
}
const $Foo = new Foo();
$Foo.instances['myUid'] = new $Foo.Instance();
const myInstance = $Foo.instances['myUid'];
myInstance.__foo2; // okay
请注意,在子类本身内部使用多态 this
类型可能有点麻烦:
class Foo extends Entity {
Instance = FooInstance;
constructor() {
super();
this.instances.abc = new FooInstance(); // error!
this.instances.abc = new this.Instance(); // error!
}
}
我不确定您是否需要做这样的事情,但是尝试在 this.instances
内的 Foo
上设置属性失败,因为编译器不知道 this
会做什么如果有人出现并子类 Foo
。它将 this
视为未指定的泛型类型,并且无法真正验证是否可以为其分配任何特定值。在这种情况下,您可能需要使用 type assertions 来抑制错误。
另一种方法是使 Entity
成为 generic class,其中类型参数 T
对应于子类中 EntityInstance
的特定子类型:
abstract class Entity<T extends EntityInstance> {
abstract Instance: new () => T;
instances: Record<string,T | undefined> = {};
}
任何特定的子类都需要指定 T
应该是什么(这有点多余),但随后一切正常......子类内部和外部:
class Foo extends Entity<FooInstance> {
Instance = FooInstance;
constructor() {
super();
this.instances.abc = new FooInstance(); // okay
this.instances.abc = new this.Instance(); // okay
}
}
myInstance.__foo2; // still okay
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。