简体   繁体   English

如何在抽象父 class 中创建通用方法以实现 typescript?

[英]how make a generic method in a abstract parent class for implementation typescript?

What will be the best and (proper) approach to make this in TypeScript.在 TypeScript 中进行此操作的最佳和(正确)方法是什么。 $Foo.getInstance('uid') should return a FooInstance based on implementations? $Foo.getInstance('uid')应该根据实现返回一个FooInstance吗?

I want in the abstact class Entity a method to get a instance from a pool, for return the implemented EntityInstance .我想在抽象的 class 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'); 

So example here: const instance = $Foo.getInstance('uid') should be a FooInstance ;所以这里的例子: const instance = $Foo.getInstance('uid')应该是FooInstance ; But it actually a EntityInstance thats correct !但它实际上是一个EntityInstance那是正确的! 在此处输入图像描述

so i try change this method getInstance to something like this.所以我尝试将此方法getInstance更改为这样的东西。

    getInstance <t=this>(uid: string ): InstanceType<this['Instance']> {
        return this.instances[uid]
    }

It working:.) but make some error type, Am noob with ts documentations.它工作:.) 但会产生一些错误类型,我是新手,有 ts 文档。 what change i can made to make this logic work fine, I know ts is powerful.我可以做些什么改变来使这个逻辑正常工作,我知道 ts 很强大。 but am not sure how to make this work fine for intelisence in my ide.但我不确定如何使这项工作在我的 ide 中正常工作。

在此处输入图像描述


minimal reproductive demo typescript i want myInstance.__foo2;最小再现演示typescript我想要myInstance.__foo2; not produce error.不产生错误。

You could try changing the typings in Entity to the following:您可以尝试将Entity中的类型更改为以下内容:

abstract class Entity {
    abstract Instance: new () => EntityInstance;

    instances: Record<string,
        InstanceType<this["Instance"]> | undefined
    > = {};
}

The Instance property is a constructor that returns an EntityInstance (or a subtype of it). Instance属性是一个构造函数,它返回一个EntityInstance (或其子类型)。 And the instances property type depends on the type of Instance ;instances属性类型取决于Instance的类型; by using polymorphic this , we are saying for any subclass of Entity the instances property will depend on the type of Instance in the same subclass.通过使用多态this ,我们说对于Entity的任何子类, instances属性将取决于同一子类中Instance的类型。

This gives you the behavior you're looking for, at least for the example code:这为您提供了您正在寻找的行为,至少对于示例代码:

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

Note that polymorphic this types can be a bit of a pain to work with inside the subclasses themselves:请注意,在子类本身内部使用this多态类型可能会有点麻烦:

class Foo extends Entity {
    Instance = FooInstance;

    constructor() {
        super();
        this.instances.abc = new FooInstance(); // error!
        this.instances.abc = new this.Instance(); // error!
    }

}

I'm not sure if you need to do something like this, but trying to set a property on this.instances inside Foo fails because the compiler doesn't know what this will be if someone comes along and subclasses Foo .我不确定您是否需要做这样的事情,但是尝试在Foo内部的this.instances上设置属性失败,因为编译器不知道this有人出现并继承Foo会发生什么。 It treats this like an unspecified generic type and is not really able to verify that any particular value is assignable to it.它将this视为未指定的泛型类型,并且无法真正验证任何特定值是否可分配给它。 In such cases you might need to use type assertions to suppress errors.在这种情况下,您可能需要使用类型断言来抑制错误。


Another approach is to make Entity a generic class where the type parameter T corresponds to the particular subtype of EntityInstance in subclasses:另一种方法是使Entity成为通用 class ,其中类型参数T对应于子类中EntityInstance的特定子类型:

abstract class Entity<T extends EntityInstance> {
    abstract Instance: new () => T;
    instances: Record<string, T | undefined> = {};
}

Any particular subclass needs to specify what T should be (which is a bit redundant), but then everything works... both inside and outside the subclass:任何特定的子类都需要指定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

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM