【问题标题】:Type XXX is not assignable to type 'T' when using generic in typescript在打字稿中使用泛型时,类型 XXX 不可分配给类型“T”
【发布时间】:2021-07-23 10:33:07
【问题描述】:

我想创建一个可以在子类中引用的静态函数。 BaseClass 的示例如下

export abstract class BaseEntity {
    public static of<T>(params: Partial<T>, type: new () => T): T {
        const item = new type();

        Object.assign(type, params);

        return item;
    }
}

然后我用 User 类扩展了 BaseEntity,如下所示

export class User extends BaseEntity{
    public static of(params: Partial<User>): User {
        return super.of<User>(params, User);
    }
}

这对我来说似乎是一个合法的代码,因为我提供 User 作为泛型类型,并且我已经明确编码 BaseEntity 静态函数应该返回相同类型的函数(不会引发错误)。但是,编写此代码会产生以下错误

TS2417:类静态端“typeof User”错误地扩展了基类 静态端'typeof BaseEntity'。 'of(...)' 返回的类型 这些类型之间不兼容。类型“用户”不可分配给 键入“T”。 'T' 可以用任意类型实例化 与“用户”无关。

似乎是说不能返回类型 User 因为父类返回的类型 T 与 User 类型不兼容。这对我来说毫无意义,因为我明确地向泛型类型提供了 T 应该是 User。我做错了什么,我该如何克服这个问题?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    嗯。你想在这里覆盖静态方法吗?恐怕这行不通。 ;) 静态方法绑定到类的构造函数而不是其原型。您只能在类本身上调用它们,而不能在类的实例上调用它们。所以你的BaseEntity.of()方法和User.of()方法其实是两个完全不相关的函数。

    您的 BaseEntity.of() 方法似乎是您的实体的工厂方法。或许您可以考虑使用BaseEntity.of() 方法并放弃User.of() 方法。下面的示例代码仅在BaseEntity 类中创建静态of() 方法,并使用它来初始化两个User 变量。 (出于演示目的,我还在User 类中添加了一个name 属性。)

    不过还有一些补充说明:

    • 交换of() 函数的参数可能很有用:首先是type 参数(应始终提供),其次是params 参数(如果您需要,它可以是可选的创建一个默认实例)。
    • 我注意到在您的BaseEntity.of() 方法中,您将params 对象的内容分配给type,但我假设您想将它们分配给item

    BaseEntity.ts:

    export abstract class BaseEntity {
      static of<T extends BaseEntity>(type: new () => T, params?: Partial<T>) {
        const item = new type();
        Object.assign(item, params);
        return item;
      }
    
      //...
    }
    

    User.ts:

    import { BaseEntity } from 'BaseEntity';
    
    export class User extends BaseEntity {
      name?: string;
    }
    

    main.ts:

    import { BaseEntity } from 'BaseEntity';
    import { User } from 'User';
    
    const user1 = BaseEntity.of(User, { name: 'John Doe' });
    const user2 = BaseEntity.of(User);
    
    console.log(user1.name); // John Doe
    console.log(user2.name); // undefined
    

    我假设您的 BaseEntity 类包含额外的(与基本实体相关的)逻辑。但如果不是这种情况,您可能希望从BaseEntity 类中提取实体创建逻辑并将其放入“全局”工厂函数中。这样做时,您可以完全删除 BaseEntity 类。因此,您的具体实体类将少一个依赖项。

    createEntity.ts:

    export function createEntity<T>(type: new() => T, params?: Partial<T>) {
      const item = new type();
      Object.assign(item, params);
      return item;
    }
    

    User.ts:

    export class User {
      name?: string;
    }
    

    main.ts:

    import { createEntity } from 'createEntity';
    import { User } from 'User';
    
    const user1 = createEntity(User, { name: 'John Doe' });
    const user2 = createEntity(User);
    
    console.log(user1.name); // John Doe
    console.log(user2.name); // undefined
    

    【讨论】:

    • 完美。正是我想要的。
    猜你喜欢
    • 2021-12-05
    • 2019-08-11
    • 1970-01-01
    • 2021-10-11
    • 2018-09-19
    • 2021-11-10
    • 2020-06-29
    • 2018-04-27
    • 2020-03-09
    相关资源
    最近更新 更多