Home > Mobile >  How to handle this types
How to handle this types

Time:11-05

A quick question (maybe a noob one) :

A have this Main Element class which has a property called "workingElement". The way i thought this program is that property could be any HTMLElement type. For example: HTMLFormElement, HTMLDivElement, HTMLElement and so on. So my main class looks like this:

class MainElement {
  protected _workingElement;
  protected _mapElements: Map<any, any>;
  protected _id: string | undefined;

  constructor(tagElement: string, id?: string) {
    this._workingElement = document.createElement(tagElement);

    if (id) {
      this._workingElement.setAttribute("id", id);
      this._id = id;
    }

    this._mapElements = new Map();
  }
}

And I have a Form class which extends MainElement class:

export class Form extends MainElement {
  constructor(id?: string, actionForm?: string, method: string = "GET") {
    super("form");
    this._workingElement = document.createElement("form");

    if (id) {
      this._workingElement.setAttribute("id", id);
      this._id = id;
    }
    if (actionForm) this._workingElement.action = actionForm;

    this._workingElement.method = method;
  }
}

I'm not able to tell typescript to infer the type of _workingElement dynamically. When i construct my form element and call super("form") i expect typescript to know that the corresponding type for workingElement is HTMLFormElement. Just stays as an "HTMLElement"

Any suggestions?

Thanks in advance!

I tried to add a switch case to tagElement argument that maybe let typescript know which type of element i'm working on.

CodePudding user response:

If you make your MainElement class generic and make it take a generic parameter:

class MainElement<E extends keyof HTMLElementTagNameMap = keyof HTMLElementTagNameMap> {
    protected _workingElement;
    protected _mapElements: Map<any, any>;
    protected _id: string | undefined;

    constructor(tagElement: E, id?: string) {
        this._workingElement = document.createElement(tagElement);

        if (id) {
            this._workingElement.setAttribute("id", id);
            this._id = id;
        }

        this._mapElements = new Map();
    }
}

All you need to do is say that FormElement extends MainElement<"form">:

class Form extends MainElement<"form"> {

Then because of document.createElement's typings, you'll get the correct type for _workingElement already, at no cost. See it in action below:

Playground

  • Related