Typescript: [BUG] inheritance of static methods doesn't work

Created on 31 Aug 2020  路  6Comments  路  Source: microsoft/TypeScript

class Animal {
  static say() {
    console.log('Animal')
  }

  constructor() {
    this.constructor.say()
  }
}


class Cat extends Animal {
  static say() {
    console.log('Cat')
  }
}

i have error:
image

Expected Behavior:

new Animal() // console log "Animal"
new Cat() // console log "Cat"

If I use the class name to access static methods, then inheritance naturally also does not work, and Cat.say() does not calls with new Cat(), cuz new Cat() calls Animal.say()

class Animal {
  static say() {
    console.log('Animal')
  }

  constructor() {
    Animal.say()
  }
}
Duplicate

Most helpful comment

@RyanCavanaugh is this something wich is planed to be fixed at some time?

And shouldn't #32452 also be closed as duplicate?

All 6 comments

I've the same problem in my small class.
Cause of this I need many ts-ignores.
Don't know if it would be possible...

export const html = function (strings: TemplateStringsArray, ...values: any[]): HTMLTemplateElement {
  const template = document.createElement('template');
  template.innerHTML = strings.raw[0];
  return template;
};

export const css = function (strings: TemplateStringsArray, ...values: any[]): CSSStyleSheet {
  const cssStyleSheet = new CSSStyleSheet();
  //@ts-ignore
  cssStyleSheet.replaceSync(strings.raw[0]);
  return cssStyleSheet;
};

abstract class BaseCustomWebComponent extends HTMLElement {
  static readonly style: CSSStyleSheet | Promise<CSSStyleSheet>;
  static readonly template: HTMLTemplateElement;

  protected _getDomElement<T extends Element>(id: string): T {
    if (this.shadowRoot.children.length > 0)
      return <T>(<any>this.shadowRoot.getElementById(id));
    return <T>(<any>this._rootDocumentFragment.getElementById(id));
  }

  protected _getDomElements<T extends Element>(selector: string): T[] {
    if (this.shadowRoot.children.length > 0)
      return <T[]>(<any>this.shadowRoot.querySelectorAll(selector));
    return <T[]>(<any>this._rootDocumentFragment.querySelectorAll(selector));
  }

  //@ts-ignore
  private static _propertiesDictionary: Map<string, string>;
  protected _parseAttributesToProperties() {
    //@ts-ignore
    if (!this.constructor._propertiesDictionary) {
      //@ts-ignore
      this.constructor._propertiesDictionary = new Map<string, [string, any]>();
      //@ts-ignore
      for (let i in this.constructor.properties) {
        //@ts-ignore
        this.constructor._propertiesDictionary.set(i.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`), [i, this.constructor.properties[i]]);
      }
    }
    for (const a of this.attributes) {
      //@ts-ignore
      let pair = this.constructor._propertiesDictionary.get(a.name);
      if (pair) {
        if (pair[1] === Boolean)
          this[pair[0]] = true;
        else if (pair[1] === Object)
          this[pair[0]] = JSON.parse(a.value);
        else
          this[pair[0]] = a.value;
      }
    }
  }

  /*attributeChangedCallback(name, oldValue, newValue) {
    //@ts-ignore
    if (this.constructor._propertiesDictionary) {
      this._parseAttributesToProperties();
    }
  }*/

  protected _rootDocumentFragment: DocumentFragment;

  constructor() {
    super();

    this.attachShadow({ mode: 'open' });

    //@ts-ignore
    if (this.constructor.template) {
      //@ts-ignore
      this._rootDocumentFragment = this.constructor.template.content.cloneNode(true);
    }

    //@ts-ignore
    if (this.constructor.style) {
      //@ts-ignore
      if (this.constructor.style instanceof Promise)
        //@ts-ignore
        this.constructor.style.then((style) => this.shadowRoot.adoptedStyleSheets = [style]);
      else
        //@ts-ignore
        this.shadowRoot.adoptedStyleSheets = [this.constructor.style];
    }


  }
}

export class BaseCustomWebComponentLazyAppend extends BaseCustomWebComponent {
  constructor() {
    super()
    queueMicrotask(() => {
      if (this._rootDocumentFragment)
        this.shadowRoot.appendChild(this._rootDocumentFragment);
      //@ts-ignore
      if (this.oneTimeSetup && !this.constructor._oneTimeSetup) {
        //@ts-ignore
        this.constructor._oneTimeSetup = true;
        //@ts-ignore
        this.oneTimeSetup();
      }
      //@ts-ignore
      if (this.ready)
        //@ts-ignore
        this.ready();
    })
  }
}

export class BaseCustomWebComponentConstructorAppend extends BaseCustomWebComponent {
  constructor() {
    super()
    if (this._rootDocumentFragment)
      this.shadowRoot.appendChild(this._rootDocumentFragment);

    queueMicrotask(() => {

      //@ts-ignore
      if (this.oneTimeSetup && !this.constructor._oneTimeSetup) {
        //@ts-ignore
        this.constructor._oneTimeSetup = true;
        //@ts-ignore
        this.oneTimeSetup();
      }
      //@ts-ignore
      if (this.ready)
        //@ts-ignore
        this.ready();
    })
  }
}

@RyanCavanaugh why was this bug not fixed 3 years later? that is, LITERALLY, typescript DOES NOT SUPPORT extending static methods o_O

@RyanCavanaugh is this something wich is planed to be fixed at some time?

And shouldn't #32452 also be closed as duplicate?

@MaxmaxmaximusAWS maybe you should open this again, the other issues are so far behind

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Was this page helpful?
0 / 5 - 0 ratings