【发布时间】: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