打字稿:调用具有“this”参数的静态函数

时间:2021-04-13 21:03:19

标签: typescript

我目前正在打字稿中碰壁。

基本上,我想从扩展特定抽象类的类中调用静态函数。

我收到以下错误

The 'this' context of type 'typeof A' is not assignable to method's 'this' of type 'AStatic<AStatic<unknown>>'. Cannot assign an abstract constructor type to a non-abstract constructor type.

这是一个指向 Typescript playground

的链接

代码如下:

type AStatic<S extends A> = { new(): S };

abstract class A {
  static callStatic<S extends AStatic<S>>(this: AStatic<S>) {
    console.log('hey')
  }
}

class B extends A {
}


class D extends A {
}

class C {
  aType: typeof A;
  constructor(type: typeof A) {
    this.aType = type;
    this.aType.callStatic(); // error is here
  }
}

const c = new C(B);
const c_2 = new C(D);

我设法让它在打字稿中构建的唯一方法是像传递 any 而不是 typeof A。很遗憾,因为我的 IDE 不支持 A 的功能。

请注意,我无法控制 A 类和 AStatic 类型,因为它们来自外部库。

2 个答案:

答案 0 :(得分:1)

您正在尝试调用 A 的显式实例,但这是不必要的。

type AStatic<S extends A> = { new(): A };

abstract class A {
    static callStatic<S extends AStatic<S>>(this: AStatic<S>) {
        console.log('hey')
    }
}

class B extends A {

}

class C {
    aType: typeof A;
    constructor(type: typeof A) {
        this.aType = type;
        B.callStatic()
    }
}

const c = new C(B);

因为callStatic方法是静态的,你可以直接在B中调用这个方法的实现。

答案 1 :(得分:1)

你就在附近!看看你对 A 的伪定义:

abstract class A {
  static callStatic<S extends AStatic<S>>(this: AStatic<S>) {
  //                                      ^^^^^^^^^^^^^^^^
  //           the `this` parameter must be type AStatic<A>

看着AStatic

type AStatic<S extends A> = { new(): A };
//                            ^^^^^ - type must have a constructor, 
//                                      which rules out abstract classes.

这排除了 typeof A 作为 this 参数,因为它是 abstract。我们可以尝试直接使用 AStatic

class C {
  aType: AStatic<A>;
  constructor(type: AStatic<A>) {
    this.aType = type;
    this.aType.callStatic();
    //         ^^^^^^^^^^ - Property 'callStatic' does not exist on type 'AStatic<A>'
  }
}

但是 callStatic 没有在 AStatic 上定义。解决方案是交叉类型:

class C {
  aType: AStatic<A> & typeof A
  constructor(type: AStatic<A> & typeof A) {
    this.aType = type;
    this.aType.callStatic() // works!
  }
}

正如 MunsMan 指出的那样,除非您在派生类型上覆盖 callStatic,否则您根本不需要传递 typeof A

const c = new C(B);
c.callStatic(); // hey
B.callStatic(); // hey
D.callStatic(); // hey

换句话说,只要您有 A 的非抽象版本,您就可以在该类型上调用 callStatic(或任何静态方法/属性),它的工作方式相同每次!

相关问题