【问题标题】:Extending class type is not assignable to base class type in typescript扩展类类型不可分配给打字稿中的基类类型
【发布时间】:2022-01-26 15:14:58
【问题描述】:

我有以下代码:

class Base<TAttributes extends {} = {}> {
    constructor(attributes: TAttributes) {}
}

class Extended extends Base<{test: string}> {

}

function test(test: typeof Base) {};

test(Extended);

我想要实现的是创建一个函数,它需要 Base 类类型的构造函数,并且我试图将更具体(扩展)类型的构造函数传递给它。不幸的是,由于泛型,打字稿抱怨说:

“typeof Extended”类型的参数不能分配给“typeof Base”类型的参数。 构造签名的类型不兼容。 类型 'new (attributes: { test: string; }) => Extended' 不可分配给类型 'new (attributes: TAttributes) => Base'。 参数“属性”和“属性”的类型不兼容。 类型 'TAttributes' 不可分配给类型 '{ test: string; }'。 类型“{}”中缺少属性“测试”,但类型“{测试:字符串; }'

我不知道,我在这里做错了什么。如果我从基类中删除泛型参数,打字稿就不再抱怨了。有人可以为我指明方向,如何实现我想要的结果?

这里还有一个playground 链接。

【问题讨论】:

  • 扩展类的构造函数不一定可以分配给Base 的构造函数(它可以采用完全不同的参数)。你到底需要什么?
  • 为了清楚起见,请仔细阅读您的第一段。还有,函数中的参数怎么处理?
  • @GuerricP 我正在尝试创建一个可以使用基类的静态端的函数。
  • @AdamBaranyai 您应该将此信息添加到您的问题中,因为它实际上描述了您的全部问题。

标签: typescript


【解决方案1】:

尝试编写test()的实现。你怎么可能知道传递给构造函数的参数是什么?

在您的示例中,Base 可以通过以下方式实例化:

new Base()

但是Extended 需要{ test: string } 参数。

new Extended({ test: 'qwe' })

因此,您不能将 Extended 构造函数视为 Base 构造函数。它有不同的类型。

子类的实例总是可以分配给父类的类型,但对于可能发生巨大变化的构造函数不是也是如此。

你可以这样做:

function test<
  Args extends unknown[],
  Instance extends unknown
>(
  ctor: new (...args: Args) => Instance,
  ...args: Args
): Instance {
  return new ctor(...args)
}

在本例中,测试函数采用ctor(任何构造函数)和args(构造函数所需的参数)。然后返回构造函数生成的任何Instance 类型。

// works
test(Base, {});
test(Extended, { test: 'qwe' });

但这适用于任何构造函数,而不仅仅是 Base 是什么。

Playground

【讨论】:

    【解决方案2】:

    如果您只需要使用基类class 中的static 方法而不是它的constructor,则可以使用NoConstructor 帮助器类型以仅保留基类中的属性,并删除它的构造函数部分:

    class Base<TAttributes extends {} = {}> {
        static log() {
            console.log('log');
        }
        constructor(attributes: TAttributes) { }
    }
    
    class Extended extends Base<{ test: string }> {
    
    }
    
    type NoConstructor<T> = Pick<T, keyof T>;
    
    function test(test: NoConstructor<typeof Base>) {
        test.log(); // OK
    };
    
    test(Extended); // OK
    

    TypeScript playground

    【讨论】:

      猜你喜欢
      • 2021-10-11
      • 2020-06-29
      • 2019-09-25
      • 1970-01-01
      • 2022-08-14
      • 2016-10-25
      • 2018-02-02
      • 2021-06-17
      • 2018-01-04
      相关资源
      最近更新 更多