Typescript:在子方法中覆盖父类的静态工厂方法

2024-02-10

我在使用 Typescript 进行依赖注入时遇到了一些问题。在每个类上,我添加一个工厂静态方法,其中设置了所有依赖项。我这样做是出于测试目的,以便我仍然能够使用 TDD 方法。

现在我在子类中重写父类的工厂方法时遇到了一些问题。例子:

interface DepsA {
  a: string
}

interface DepsB extends DepsA {
  b: Child1
}

class Parent {
  constructor(protected deps: DepsA | DepsB) {}

  public static factory<T extends Parent>() {
    return new this({a: 'This is a nice Dependency'}) as T
  }
}

class Child1 extends Parent {}

class Child2 extends Parent {
  public static factory() {
    return new this({a: 'This is a nice Dependency', b: Child1.factory()})
  }
}

const child1 = Child1.factory<Child1>()
const child2 = Child2.factory()

我收到的错误是:

[ts]
Class static side 'typeof Child2' incorrectly extends base class static side 'typeof Parent'.
  Types of property 'factory' are incompatible.
    Type '() => Child2' is not assignable to type '<T extends Parent>() => T'.
      Type 'Child2' is not assignable to type 'T'.

我知道为什么会收到错误,但此时不知道如何修复它,除非重命名 Child2 中的工厂静态方法。

UPDATE:与此问题相关的错误报告自动解释了为什么我在工厂方法上使用泛型:#26298 https://github.com/Microsoft/TypeScript/issues/26298


首先,有一个预先定义的条件类型 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html called 实例类型这可以帮助您从静态成员推断类类型:

public static factory<T extends typeof Parent>(this: T) {
    return new this({ a: 'This is a nice Dependency' }) as InstanceType<T>
}

其次,如果您在子类中重写方法(无论是否静态),它应该具有兼容的签名,包括通用内容。

因此,您的代码块可能如下所示(请参阅打字稿游乐场 https://www.typescriptlang.org/play/#src=interface%20DepsA%20%7B%0D%0Aa%3A%20string%0D%0A%7D%0D%0A%0D%0Ainterface%20DepsB%20extends%20DepsA%20%7B%0D%0Ab%3A%20Child1%0D%0A%7D%0D%0A%0D%0Aclass%20Parent%20%7B%0D%0Aconstructor(public%20deps%3A%20DepsA%20%7C%20DepsB)%20%7B%7D%0D%0A%0D%0A%20%20%20%20public%20static%20factory%3CT%20extends%20typeof%20Parent%3E(this%3A%20T)%3A%20InstanceType%3CT%3E%20%7B%0D%0A%20%20%20%20%20%20%20%20return%20new%20this(%7B%20a%3A%20'This%20is%20a%20nice%20Dependency'%20%7D)%20as%20InstanceType%3CT%3E%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A%0D%0Aclass%20Child1%20extends%20Parent%20%7B%7D%0D%0A%0D%0Aclass%20Child2%20extends%20Parent%20%7B%0D%0Apublic%20static%20factory%3CT%20extends%20typeof%20Parent%3E(this%3A%20T)%3A%20InstanceType%3CT%3E%20%7B%0D%0A%20%20%20%20return%20new%20this(%7Ba%3A%20'This%20is%20a%20nice%20Dependency'%2C%20b%3A%20Child1.factory()%7D)%20as%20InstanceType%3CT%3E%0D%0A%7D%0D%0A%7D%0D%0A%0D%0Aconst%20child1%20%3D%20Child1.factory()%0D%0Aconst%20child2%20%3D%20Child2.factory()%0D%0Alet%20test2%20%3D%20child2.deps):

interface DepsA {
    a: string
}

interface DepsB extends DepsA {
    b: Child1
}

class Parent {
    constructor(public deps: DepsA | DepsB) {}

    public static factory<T extends typeof Parent>(this: T) {
        return new this({ a: 'This is a nice Dependency' }) as InstanceType<T>
    }
}

class Child1 extends Parent {}

class Child2 extends Parent {
    public static factory<T extends typeof Parent>(this: T) {
        return new this({a: 'This is a nice Dependency', b: Child1.factory()}) as InstanceType<T>
    }
}

const child1 = Child1.factory()  // Type: Child1
const child2 = Child2.factory()  // Type: Child2

从那里,返回正确的deps类型,而不是联合,也可以在非静态成员中使用as this["deps"]。但你必须修改一下你的代码。

希望能帮助到你 ;-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Typescript:在子方法中覆盖父类的静态工厂方法 的相关文章

随机推荐