【问题标题】:Using a class expression/value as a type使用类表达式/值作为类型
【发布时间】:2021-02-16 01:07:55
【问题描述】:

如果我以通常的方式声明一个类,我可以使用类名作为类型:

class Foo {
  foo: number
  constructor(x: number) {
    this.foo = x
  }
}
let foo : Foo // all fine

但是如果我通过将类表达式分配给变量来声明一个类,我就不能将该名称用作类型:

const Bar = class Bar {
  bar: string
  constructor(x: string) {
    this.bar = x
  }
}
let b: Bar // 'Bar' refers to a value, but is being used as a type here. Did you mean 'typeof Bar'?

按照建议使用typeof Bar 不起作用,因为我想要Bar 的实例类型,而不是类本身的类型。

typescript playground example

如何获取第二种方式定义的类的实例类型?

基本原理

我对以这种方式定义类感兴趣的原因是我希望有一个接口来描述某些类将具有的静态方法,如 in the handbook here 所述(该部分中的第三个示例)。

Here's that example with a single line added showing the problem again

【问题讨论】:

    标签: typescript


    【解决方案1】:

    Typescript 有两个命名空间,一个值空间和一个类型空间(阅读更多 here)。类声明在声明它的上下文中的值空间和类型空间中都添加了一个名称。一个类表达式,只在类范围内添加这些。所以你可以使用BarExpression作为类中的构造函数和类型。

    const Bar = class BarExpression {
      bar: BarExpression // Valid in the class
      constructor(x: BarExpression) { 
        this.bar = x
      }
    }
    

    在封闭作用域中,您只剩下名为Barconst,您可以将其用作构造函数,但未添加到封闭作用域中的类型( const 声明没有理由将类型添加到封闭范围)。

    您可以使用InstanceType 条件类型获取构造函数的实例类型。您还可以添加类型别名声明,以便获得与类声明类似的效果:

    const Bar = class Bar {
      bar: string
      constructor(x: string) {
        this.bar = x
      }
    }
    type Bar = InstanceType<typeof Bar>
    let a : Foo = new Foo(42)
    let b : Bar = new Bar("hello")
    

    Playground Link

    【讨论】:

    • 谢谢!在回头看这里之前,我自己只是在尝试更多的东西,type Bar = typeof Bar.prototype 似乎工作正常。这是否等同于使用InstanceType&lt;typeof Bar&gt;
    猜你喜欢
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    相关资源
    最近更新 更多