是否可以在TypeScript类型系统中使用泛型进行原型设计

时间:2018-11-07 11:13:15

标签: javascript html typescript dom types

我想使用自己的某些功能来扩展dom库,但是我希望对从HTMLElement派生的现有DOM元素进行扩展。我用window.customElements创建的新创建的元素,它们也是从HTMLElement派生的。我将提供一些示例代码,以说明如何在打字稿类型系统中实现这一目标。

首先,我在HTMLELement接口上声明了一些常用功能,例如

interface HTMLElement{
    $showPanel(Event: Event, ButtonID: number, ForceShow: boolean): boolean;
    $_showPanel(Panel: any, Element: HTMLElement, PanelID: number, ForceShow: boolean): void;
    getElementsByAttribute(Attribute: string, Value: string, Tag?: string):Element[];
    updateView(config: {}): void;
    $readonly(BReadonly: boolean): void;
    $disable(Disable: boolean, AddToModelReadOnly: string): void;
    atRuntime():void;
};

然后,我具有使用特定DomElement的特定属性的功能,并且需要检查给定属性在该DomElement上是否存在。我创建了一个额外的接口,用于扩展具有这些特定功能的HTML元素。

 interface ElmentSpecificFunction<T> extends HTMLElement{
    $sed(this:T,atb: keyof ElementSpecficProperties<T> ,val: string): CEEO<boolean>;
    $set(this:T,atb: keyof ElementSpecficProperties<T> , val: string|null, dom?: boolean): CEEO<boolean>;
}

atb参数使用以下类型

type ElementSpecficProperties<T> =  Pick<T,WritableKeys<T>>;

 type WritableKeys<T> = {
       [P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: 
      T[P] }, P>
     }[keyof T];

 type IfEquals<X, Y, A=X, B=never> =
 (<T>() => T extends X ? 1 : 2) extends
 ( <T>() => T extends Y ? 1 : 2) ? A : B;

这些类型只是出于我的意愿过滤掉了只读属性。

此接口将由每个Dom元素的特定接口实现 像这样

interface HTMLDivElement extends ElmentSpecificFunction<HTMLDivElement>{};

这样做,所有属性将继承标准HTML元素属性并在那里实现。

然后我编写了以下函数

 $set<T>(this:ElmentSpecificFunction<T>,atb: keyof ElementSpecficProperties<ElmentSpecificFunction<T>> , val:any, dom:boolean): CEEO<boolean> {//TODO moet try catch met het Catch_Error_Object.
    dom = dom || false;
    try {
        // let decrip = Object.getOwnPropertyDescriptor(this,atb)!;
        // this.
        if(val !== null ){
            if( dom ) {
                this.setAttribute( atb.toString(), val );
                return {succes:true,error:undefined,data:true};
            }
            else{
                this[atb] = val;
                return {succes:true,error:undefined,data:true};
            }
        }
        return {succes:false,error:new Error("value is null no set possible"),data:false}
    }
    catch( Error ) {
        window.AE.Log("Error while setting attribute [" + atb + "] on object [" + this.id + "] where dom = [" + dom + "] and val = " + val + "\n"+ Error, "$set", true );
        return {succes:false,error:Error,data:false};
    }
},

我将按如下所示制作原型

HTMLDivElement.prototype.$set = $set

并像这样进行测试

let div = document.createElement("div"); div.$set("","")

但是当我使用align这样的变量时,应该不会有问题,因为当使用元素上不存在的其他名称时,它会出现在div元素上,这应该会产生一个错误,我可以使用普通的HTMLElement但希望它可用于每个特定的Dom元素。 仅当使用此类功能添加接口时,此方法才有效 div.$set<HTMDivElement>("","")

我希望这里的人知道如何执行此操作,因为这将有助于对这些函数进行类型检查。

0 个答案:

没有答案