Я хочу расширить библиотеку dom с помощью некоторой собственной функции, но я хочу это для существующих элементов DOM, которые получены из HTMLElement. И недавно созданные элементы, которые созданы мной с window.customElements
и также получены из HTMLElement. Я приведу пример кода, как я хочу достичь этого внутри системы типов машинописи.
Во-первых, я объявляю некоторые общие функции в интерфейсе My 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>("","")
Я надеюсь, что кто-то здесь знает, как это сделать, потому что это поможет проверке типа этих функций.