代码之家  ›  专栏  ›  技术社区  ›  David Mulder

具有泛型父类的异步构造模式

  •  0
  • David Mulder  · 技术社区  · 6 月前

    如何键入 constructWhenReady 方法,返回类型只是 Child ,而不更改“调用”代码或Child类。基本上我是 just searching for a solution to have an async constructor ,但是当Parent类是泛型的时,所提出的解决方案就失败了。

    class Parent<PropType extends any> {
        static isReadyForConstruction = new Promise(r => setTimeout(r, 1000));
    
        static async constructWhenReady<T extends typeof Parent>(this: T): Promise<InstanceType<T>> {
            await this.isReadyForConstruction;
            return new this() as InstanceType<T>;
        }
    
        get something(): PropType {
           // ...
        }
    }
    
    class Child extends Parent<{ a: 'b' }> { }
    
    // Error: '{ a: "b"; }' is assignable to the constraint of type 
    // 'PropType', but 'PropType' could be instantiated with a different 
    // subtype of constraint 'unknown'.
    const x = await Child.constructWhenReady(); 
    
    

    理由: 小孩 类和使用的代码 小孩 类将由经验不足的开发人员编写,并且需要尽可能干净(这是测试自动化代码)。最简单的解决方案是只要求每个人都将代码编写为 await new Child().init() ,这很好,但我更希望在他们键入代码时弹出一条错误消息,而不是在运行时弹出。

    1 回复  |  直到 6 月前
        1
  •  1
  •   Bergi    6 月前

    这个 constructWhenReady 方法不关心泛型参数的类型 PropType 用实例化。它应该明确说明:

    class Parent<PropType> {
        static isReadyForConstruction = new Promise(r => setTimeout(r, 1000));
    
        static async constructWhenReady<T extends typeof Parent<unknown>>(this: T): Promise<InstanceType<T>> {
        //                                                     ^^^^^^^^^
            await this.isReadyForConstruction;
            return new this() as InstanceType<T>;
        }
    
        get something(): PropType {
           // ...
        }
    }
    

    注意,你甚至可以摆脱 as InstanceType<T> 写作时选角

        static async constructWhenReady<T extends Parent<unknown>>(this: {new(): T; isReadyForConstruction: Promise<unknown>}): Promise<T> {
            await this.isReadyForConstruction;
            return new this();
        }