我有一个名为Parent的基类
class Parent {
static elType = window.Element
el: InstanceType<typeof Parent['elType']>
constructor(input: Element) {
let ctor = this.constructor as typeof Parent
if (input instanceof ctor.elType) {
this.el = input
} else {
throw new Error()
}
}
}只有当input是构造函数中指定的elType实例时,才允许创建实例。如果检查通过,则实例成员el设置为input。
然后,我想创建一个只允许HTMLElement (扩展Element)输入的子类:
class Child extends Parent {
static elType = window.HTMLElement
}但是,实例成员el没有正确地设置为HTMLElement。它仍然是Element
let foo = null as unknown as HTMLElement
let ch = new Child(foo)
// Property 'offsetLeft' does not exist on type 'Element'.
ch.el.offsetLeft我认为问题在于:
el: InstanceType<typeof Parent['elType']>我正在将el的类型设置为elType类型的Parent,它是Element,不受Child的静态elType的影响。我的问题是--我如何才能做到这一点?我需要一些技巧,比如:
el: InstanceType<typeof {{ current class }}['elType']>请在操场中查看这个。
我知道我可以通过在el中显式声明Child来解决这个问题。
class Child extends Parent {
static elType = window.HTMLElement
el: HTMLElement
}但我想避免这样做因为这是多余的。el应该始终是static elType的实例类型。
发布于 2019-10-22 18:13:58
如果您没有使用静态属性,我建议使用类型来表示子类属性将与其他属性一致缩小的约束。就像这样:
class Parent {
elType = window.Element
el: InstanceType<this['elType']>
constructor(input: Element) {
if (input instanceof this.elType) {
this.el = input as InstanceType<this['elType']>; // assert
} else {
throw new Error()
}
}
}
class Child extends Parent {
elType = window.HTMLElement
}
let foo = null as unknown as HTMLElement
let ch = new Child(foo)
ch.el.offsetLeft; // okay在这里,el类型被声明为InstanceType<this['elType']>,它将始终与每个子类中特定类型的elType相关。这使得为this.el分配一些东西变得有点棘手,因为编译器无法很容易地验证这样的分配对于所有子类都是安全的。类型断言是解决这个问题的最简单的方法。
无论如何,您可以看到这几乎完全符合您的要求,只是elType属性是一个实例属性,而不是静态属性。
如果您真的想静态地看到这一点,我可能会放弃直接继承,而是使用一个工厂函数为您创建类。如下所示:
const ParentMaker = <T extends Element>(elType: new () => T) => {
return class Parent {
static elType = elType;
el: T;
constructor(input: Element) {
let ctor = this.constructor as typeof Parent
if (input instanceof ctor.elType) {
this.el = input
} else {
throw new Error()
}
}
}
}
const Child = ParentMaker(window.HTMLElement);
let foo = null as unknown as HTMLElement
let ch = new Child(foo)
ch.el.offsetLeft在这里,ParentMaker接受一个构造函数作为参数,并返回一个新类,它的静态和实例端都以您想要的方式强类型了elType和el属性。当然,这里没有一条容易的继承路径,但也许这就是您所需要的:您可以始终使用class Child extends ParentMaker(window.HTMLElement) { ... }来使Child拥有自己的属性和方法。只有在需要子类或ch instanceof Parent工作时,您才会遇到麻烦。
希望其中之一能给你一些关于如何继续的想法。祝好运!
https://stackoverflow.com/questions/58501434
复制相似问题