Search code examples
typescripttypescript-genericstypemaps

Typescript - Is it possible to reference interfaces from extended interface?


I wanted to add chained functionality to all of the interfaces in HTMLElementTagNameMap. Since there are dozens of them and all of the elements either are HTMLElement or extend it, I thought there should be a way of doing something like this:

interface HTMLElement {
    doSomething<K extends keyof HTMLElementTagNameMap>(anArgument: any): HTMLElementTagNameMap[K]
}

This of course doesn't work, because every interface extending HTMLElement now contains a doSomething method that is expected to return any of the HTMLElementTagNameMap values. Instead, I want for HTMLTableElement.doSomething to return an object of type HTMLTableElement, HTMLDivElement.doSomething to return an object of type HTMLDivElement and so on.

Is such a generalization possible or do I need to 'duplicate' it for every interface?

And if it is possible, how do I do it?


Solution

  • I think a return type of this is what you want.

    Here's a demo:

    interface HTMLElement {
        foo(): this;
    }
    
    const a = document.createElement("a");
    
    // ...
    
    const aFoo = a.foo();
    //    ^^^^
    // HTMLAnchorElement
    
    // ...
    

    In the demo, you can hover over the variable that has the result of calling foo assigned to it and see the type is the interface for the respective HTML element.