首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于子类中的静态成员类型确定类实例成员类型

基于子类中的静态成员类型确定类实例成员类型
EN

Stack Overflow用户
提问于 2019-10-22 09:43:57
回答 1查看 131关注 0票数 0

我有一个名为Parent的基类

代码语言:javascript
运行
复制
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)输入的子类:

代码语言:javascript
运行
复制
class Child extends Parent {
    static elType = window.HTMLElement
}

但是,实例成员el没有正确地设置为HTMLElement。它仍然是Element

代码语言:javascript
运行
复制
let foo = null as unknown as HTMLElement
let ch = new Child(foo)

// Property 'offsetLeft' does not exist on type 'Element'.
ch.el.offsetLeft

我认为问题在于:

代码语言:javascript
运行
复制
el: InstanceType<typeof Parent['elType']>

我正在将el的类型设置为elType类型的Parent,它是Element,不受Child的静态elType的影响。我的问题是--我如何才能做到这一点?我需要一些技巧,比如:

代码语言:javascript
运行
复制
el: InstanceType<typeof {{ current class }}['elType']>

请在操场中查看这个。

我知道我可以通过在el中显式声明Child来解决这个问题。

代码语言:javascript
运行
复制
class Child extends Parent {
    static elType = window.HTMLElement
    el: HTMLElement
}

但我想避免这样做因为这是多余的。el应该始终是static elType的实例类型。

EN

回答 1

Stack Overflow用户

发布于 2019-10-22 18:13:58

如果您没有使用静态属性,我建议使用类型来表示子类属性将与其他属性一致缩小的约束。就像这样:

代码语言:javascript
运行
复制
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属性是一个实例属性,而不是静态属性。

如果您真的想静态地看到这一点,我可能会放弃直接继承,而是使用一个工厂函数为您创建类。如下所示:

代码语言:javascript
运行
复制
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接受一个构造函数作为参数,并返回一个新类,它的静态和实例端都以您想要的方式强类型了elTypeel属性。当然,这里没有一条容易的继承路径,但也许这就是您所需要的:您可以始终使用class Child extends ParentMaker(window.HTMLElement) { ... }来使Child拥有自己的属性和方法。只有在需要子类或ch instanceof Parent工作时,您才会遇到麻烦。

希望其中之一能给你一些关于如何继续的想法。祝好运!

链接到代码

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58501434

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档