【问题标题】:Typescript return type of factory method in base class基类中工厂方法的打字稿返回类型
【发布时间】:2018-07-01 01:10:21
【问题描述】:

来自 Python 背景,我在尝试使 Typescript 对以下继承模型感到满意时遇到了一些问题。

给定以下基类:

// model.ts
export class Model {

    serialize() {}
    static deserialize(dbRow) {}

    static async filter(options) {
        const dbRows = await getData(options);

        return dbRows.map(row => this.deserialize(row));
    }
}

以及以下扩展它的类:

// user.ts
export class User extends Model {
    serialize() {......}

    static deserialize(dbRow) {......return new User(......)}

    someOtherMethod() {.....}
}

如何定义 Model.filter 以便const users = await User.filter({.....}) 自动推断用户类型为 User[]?现在,推断的类型是 Model[]。

我知道我可以做到const users = <User[]> await User.filter({....}),但我想知道是否有任何方法建议将 Model.filter 的返回类型作为类构造函数,以便正确推断子类的实例。

【问题讨论】:

    标签: class typescript oop inheritance


    【解决方案1】:

    您可以使用以下解决方法(在this thread 中多次提及):

    type ModelContructor<T> = new () => T;
    
    class Model {
        // ...
        static async filter<T extends Model>(this: ModelContructor<T> & typeof Model, options): Promise<T[]> {
            const dbRows = await getData(options);
    
            return dbRows.map(row => this.deserialize(row));
        }
    }
    

    这里我们使用了假的this参数,当User.filter被调用时,它强制T被解析为User

    【讨论】:

    • 谢谢!您链接的线程确实有助于了解其他人正在做什么来解决这个问题。我现在将继续使用类型提示,因为我从该线程尝试的解决方案也迫使我以类似的方式定义 Model.deserialize。如果deserialize 在子类中没有实现,这不会那么痛苦,但这正是将会发生的事情。对此类的所有用户强制执行此操作似乎有点苛刻。
    • 为什么需要用类似的方式定义Model.deserialize?按原样为我工作
    【解决方案2】:

    您可以将Model 设为通用:

    // model.ts
    export class Model<T> {
        ...
        static async filter(options): Array<T> {
            const dbRows = await getData(options);
    
            return dbRows.map(row => this.deserialize(row));
        }
    }
    

    然后:

    // user.ts
    export class User extends Model<User> {
       ... 
    }
    

    你可以阅读更多关于 Typescript 的泛型here

    【讨论】:

    • 来自 Typescript 的文档:“泛型类仅在其实例方面而非静态方面是通用的,因此在使用类时,静态成员不能使用类的类型参数。”
    • 好的,我假设这是一个存储库模式 (OOP),filter 是一个实例方法。我明白为什么 deserialize 是静态方法,但不明白为什么过滤器必须是静态的。
    猜你喜欢
    • 2021-05-16
    • 1970-01-01
    • 2019-12-06
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 2020-06-29
    • 2021-07-28
    相关资源
    最近更新 更多