【问题标题】:How do you extend a method's return type in typescript, without re-declaring the method?如何在 typescript 中扩展方法的返回类型,而不重新声明方法?
【发布时间】:2020-05-18 05:19:33
【问题描述】:

如果我有以下代码:

abstract class Base {
}

class Extended extends Base {
}

abstract class BaseService {
    protected static entity = Base

    public getEntity() {
        return (this.constructor as typeof BaseService).entity
    }
}

class ExtendedService extends BaseService {
    protected static entity = Extended
}

const entityClass = new ExtendedService().getEntity();

const entityClass 的类型是“typeof Base”,尽管它实际上是 Extended 类。有没有一种方法可以在 BaseService 中定义 getEntity,以便它的返回类型由用于创建服务实例的类中的静态实体确定(在本例中为 ExtendedService,但也适用于扩展 BaseService 的任何其他类?

【问题讨论】:

  • 哎呀,你可以得到something like what you want,但它不是特别漂亮。
  • 如果你没有使用static属性,我会告诉你使用polymorphic this。但是没有static polymorphic this,也没有strong typing for constructor,所以你不能直接这样做。如果你模拟constructor 的强类型,将protected 变成public,然后眯着眼睛,你可以得到你想要的行为。我应该写这个作为答案,还是你需要别的东西?
  • 感谢@jcalz 的解释!感谢您的帮助!我也在处理我有一个方法返回实体实例的情况(这里没有为实体使用抽象类),但我无法弄清楚这一点。我希望使用 InstanceType,但我得到“类型'Base'不可分配给类型'InstanceType'”
  • 我想我需要看到一个minimal reproducible example 来提供建议;不确定是要将其编辑到当前问题中还是创建一个新问题。
  • 当然可以。 something like this

标签: typescript


【解决方案1】:

感谢@jcalz 帮助解决这个问题。最后,我们提出了两个解决方案。第一个由@jcalz 提供,使用这种类型的多态,最终看起来像下面的代码:

type HeritableCtor<T> = Pick<T, keyof T>;

class Base {
}

class Extended extends Base {
    extendedProp = "hello";
}

abstract class BaseService {
    ["constructor"]: HeritableCtor<typeof BaseService>;

    static entity = Base

    public getEntity(): this['constructor']['entity'] {
        return this.constructor.entity
    }

    public getEntityInstance(): InstanceType<this['constructor']['entity']> {
        return new this.constructor.entity() as InstanceType<this['constructor']['entity']>;
    }
}


class ExtendedService extends BaseService {
    ["constructor"]: HeritableCtor<typeof ExtendedService>;
    static entity = Extended
}

const extended = new ExtendedService().getEntityInstance();

第二个,它使用泛型:

type HeritableCtor<T> = Pick<T, keyof T>;
type Constructor<T> = new(...args: any[]) => T;

class Base {
}

class Extended extends Base {
    extendedProp = "hello";
}

abstract class BaseService<Entity extends Base> {
    ["constructor"]: HeritableCtor<typeof BaseService>;

    static entity = Base

    public getEntity(): Constructor<Entity> {
        return this.constructor.entity as Constructor<Entity>;
    }

    public getEntityInstance(): Entity {
        return new this.constructor.entity() as Entity;
    }
}


class ExtendedService extends BaseService<Extended> {
    ["constructor"]: HeritableCtor<typeof ExtendedService>;
    static entity = Extended
}

const extended = new ExtendedService().getEntityInstance();

据我所知,两者都是有效的,这可能归结为个人喜好,但如果您发现不同之处,请发表评论,因为我很想听听它是什么。

【讨论】:

  • 多态this本质上一个在每个子类中自动缩小的泛型类型参数。我很确定它是这样实现的。
猜你喜欢
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
相关资源
最近更新 更多