【问题标题】:How to use class type parameter in static member?如何在静态成员中使用类类型参数?
【发布时间】:2019-10-07 19:13:22
【问题描述】:

我想实现以下模式。一个类,其中子类应具有静态 defaults 属性、options 构造函数参数和 $options 实例属性,该属性包含前两个值的合并值。这三个应该具有相同的形状。像这样的:

class Foo<T> {
  static defaults: T
  $options: T

  constructor (options: T) {
    this.$options = Object.assign({}, Foo.defaults, options)
  }
}

但是,static defaults: T 出现以下错误:

静态成员不能引用类类型参数。

然后,TypeScript 将defaults 的类型设置为any。之后,如果我这样做:

interface BarOptions {
  length: number
  color: string
}

class Bar extends Foo<BarOptions> {
  static defaults = {
    length: 'oops' // should be number
  }
}

let bar = new Bar({
  length: 42,
  color: 'green'
})

new Bar({...}) 中的对象经过了正确的类型检查,但 defaults 没有,因为它被认为是 any。这意味着我可以错误地将length 设置为string 而不会出错。如何避免这种情况?

我读到了 in the docs 类的静态和实例端之间的区别,但我仍然不知道如何解决这个问题。有解决办法吗?

编辑

看起来我可以这样做,虽然有点笨拙:

class Foo<T> {
  static defaults: any
  $options: T

  constructor (options: T) {
    this.$options = Object.assign({}, Foo.defaults, options)
  }
}

interface BarOptions {
  length: number
  color: string
}

class Bar extends Foo<BarOptions> {
  static defaults: BarOptions = {
    length: 12,
    color: 'black'
  }
}

let bar = new Bar({
  length: 42,
  color: 'green'
})

有没有更好的方法不需要在Bar 中显式设置static defaults: BarOptions

【问题讨论】:

  • 无论 Foo 有多少不同的实例,静态成员只能初始化一次,这就是为什么你不能使用 T 类型的静态成员,因为可能有许多不同的类型T 但只有一个静态场。您可以做的是基于 T 创建一个数组或查找并以这种方式获取您的默认值。
  • T 是“动态的”,因此试图将“静态”定义为“动态”是没有意义的。为什么你需要该属性是静态的?
  • 我编辑了我的问题。 @Igor 你能解释一下你的建议吗?我不认为我明白。

标签: typescript


【解决方案1】:

您不能使用动态T 签名定义static 属性。您可以做的是定义abstract class 并强制任何子类实现getDefaults 方法:

abstract class Foo<T> {
  abstract getDefaults(): T
  $options: T

  constructor (options: T) {
    this.$options = Object.assign({}, this.getDefaults(), options)
  }
}

interface BarOptions {
  length: number
  color: string
}

class Bar extends Foo<BarOptions> {
  getDefaults(): BarOptions {
    return {
      length: 3,
      color: "red"
    };
  }
}

let bar = new Bar({
  length: 42,
  color: 'green'
})

请参阅playground

【讨论】:

  • 这对我不起作用,因为我需要 defaults 可以像这样编辑:Bar.defaults.color = 'blue'
  • 假设你定义了Bar.defaults.color = 'blue',然后你初始化了你的Bar实例,然后你说Bar.defaults.color = 'red'。你对你的代码有什么期望——哪一部分应该中断并警告错误?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多