TypeScript:typeof T与{new():T}不兼容

TypeScript: typeof T not compatible with { new(): T }

我想知道为什么typeof Tnew() => T类型不兼容。 考虑一个getConstructor< T >函数:

1
2
3
4
5
6
7
8
9
function getConstructor< T >( instance: T )
{
    return instance.constructor as new() => T;
}

let instance = new MyClass();
let x: typeof MyClass;
let y = getConstructor( instance );
x = y; // type error

错误状态:类型new () => MyClass不能分配给类型typeof MyClass。 可能是因为我的MyClass具有new() => MyClass中缺少的一些静态功能。

因此,一种解决方案是使用typeof T

1
2
3
4
function getConstructor< T >( instance: T )
{
    return instance.constructor as typeof T; // type error
}

但是,这给了我另一个类型错误:T仅引用一种类型,但是在这里被用作值。

TypeScript语言规范在第4.18.6节中规定:
在需要类型的位置,也可以在类型查询中使用" typeof"来生成
表达式的类型。

那么,为什么会出现上述类型错误? 并且有某种方法可以使这项工作吗?


您感到困惑的原因是MyClass既是类型的名称(只有TypeScript知道并且在运行时将其删除)和值的名称(这是在运行时存在的JavaScript对象)。类型MyClass适用于该类的实例,而值MyClass是构造函数。

TypeScript允许您使用typeof运算符查询值的类型。因此,typeof MyClass指的是MyClass的构造函数的类型。您无法查询类型的类型,例如,typeof string是一个错误(除非巧合地有一个名为string的变量)。因此,您不能在T是某种类型的情况下执行typeof T

我还没有找到给您想要的东西的好方法。 TypeScript不知道如何从实例中推断constructor属性的确切类型。它只是认为它是Function。我能做的最好的事情就是将类声明显式标记为具有正确类型的constructor。像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface Constructable<T, C extends Constructor< T >> {
 "constructor": C
}

class MyClass implements Constructable<MyClass, typeof MyClass> {
 "constructor" = MyClass;
  // static methods, etc;
}

function getConstructor<C extends Constructor<{}>>(instance: Constructable<{},C> )
{
  return instance.constructor;
}

let instance = new MyClass();
let x: typeof MyClass;
let y = getConstructor(instance);
x = y; // no error

不知道是否可以对您的班级做到这一点。希望能有所帮助。祝好运!