【问题标题】:TypeScript factory method on parent class return child class type父类上的 TypeScript 工厂方法返回子类类型
【发布时间】:2021-07-28 13:35:47
【问题描述】:

我正在尝试在由多个子类扩展的父类上创建工厂方法。

我想做的是在父级上定义工厂方法,因为它不需要更改,并让它为扩展它的子级返回正确的类型。

这是我想要的一个例子:

class Parent {
    constructor(protected foo: string) {}

    static create<T extends Parent>(fooProvider: {foo: string}): T {
        return this.constructor(fooProvider.foo)
    }
}

class Child extends Parent {
    logFoo() {
        console.log(this.foo);
    }
}

const instance = Child.create({foo: 'bar'});
instance.logFoo();

但是,这不起作用,因为“类型 'Parent' 上不存在属性 'logFoo'。(2339)”。

我想我需要一些方法来指定被调用的构造函数方法存在于子类类型上,但我不确定如何。

我想我可以专门输入 if,例如 Child.create&lt;Child&gt;(foo),但这似乎是多余的。如果 TypeScript 可以推断出这种类型,那就最好了。

类泛型参数也不起作用,因为这是一个静态方法。

我已经检查了Typescript return type of factory method in base class,这是相似的,但是正在尝试解决对我不起作用的不同用例。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    几乎可以工作的例子:

    class Parent {
        constructor(protected foo: string) { }
    
        static create(fooProvider: { foo: string }) {
            return new this(fooProvider.foo)
        }
    }
    
    class Child extends Parent {
        logFoo() {
            console.log(this.foo);
        }
    }
    
    const instance = Child.create({ foo: 'bar' });
    
    instance.logFoo();
    

    编译后的代码按预期工作,但是 TS 不喜欢它)

    我相信你应该为工厂方法使用一些函数,因为 TS 不允许在静态方法中输入this

    class Parent {
        constructor(protected foo: string) { }
    
        static create(fooProvider: { foo: string }) {
            return new this(fooProvider.foo)
        }
    }
    
    type ClassParameters<T> = T extends new (...args: infer P) => any ? P : never
    
    const factory = <T extends typeof Parent>(clas: T, args: { foo: ClassParameters<T>[0] }) =>
        clas.create(args) as InstanceType<T>
    
    class Child extends Parent {
        logFoo() {
            console.log(this.foo);
        }
    }
    
    
    const instance = Child.create({ foo: 'bar' });
    
    const result = factory(Child, { foo: 'bar' }).logFoo()
    
    const expectedError = factory(class A { }, { foo: 'bar' }).logFoo()
    
    

    Playgroud

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-05
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-10
      相关资源
      最近更新 更多