将静态类引用传递给泛型参数会导致错误

时间:2018-02-21 22:20:40

标签: typescript generics

好吧,在我在github开票之前,我想确保我没有做错任何事。我希望问题是自我解释的:

class A {}

class B {
  static A = A;
}

function a<T>(a: T) {}

// this is fine
const b = new B.A;

// "B" refers only to a type but is used as a namespace.
a<B.A>(1);

我不能以这种方式引用某种类型吗?

此外,虽然实例化将类型推断为:

b = A
B.A = typeof A
B = B

它推断最后一行:

B = any

因此,VS Code可以跳转到第一个的定义,但是不能找到第二个的引用。

是的,这看起来很奇怪。

更新: 我收到的第一个答案证明是错误的,因为这种语法将导致typeof的类型:

// arguments of type "A" cannot be assigned to parameters of type "typeof A", property "prototype" is missing.
a<(typeof B)['A']>(b);

即使我添加了一个显式的构造函数类型,事情也会变得更糟:

// this will make things worse
class B {
  static A: { new (): A } = A;
}

1 个答案:

答案 0 :(得分:2)

  

我不应该以这种方式引用某种类型吗?

不,不是在TypeScript中。

当你有

class A {}

class B {
  static A = A;
}

您可以仅使用B.A作为值,而不是类型。这可能会令人困惑,因为TypeScript中的类既可以用作值也可以用作类型,但只有类的行为类似,其他任何东西都不同。

因此B.A是一个值,它的值为class A,此值的类型为typeof Atypeof A是您在使用类时获得的值类型位置,而不是价值位置)。

如果您需要使用B.A类型作为泛型类型参数,则可以执行以下操作:

a<(typeof B)['A']>(A);

说明:A是B类static part的成员。您使用typeof B引用类的静态部分,并引用[]的成员类型indexed access type operator

上面的这个函数a接受类A的构造函数。如果您确实希望函数a接受A的实例,则应以不同方式声明B.A

class A {}

class B {
  static A: A;
}

现在编译

a<(typeof B)['A']>(new A());

<强>更新

如果您希望将B.A初始化为A的构造函数,但仍然能够访问A的实例端,则必须等到TypeScript 2.8。它will have a feature that enables obtaining instance type from constructor type - 此代码在npm i typescript@next之后编译:

class A {}

class B {
  static A = A;
}

function a<T>(a: T) { }

const b = new B.A;

type Constructor<T> = { new(...args: any[]): T };

type Instance<C> = C extends Constructor < infer T > ? T : never;

a<Instance<(typeof B)['A']>>(b);