جنریکها - در تایپاسکریپت، چگونه میتوانم زیرکلاس را از کلاس پایه بازگردانم؟


من یک کلاس پایه دارم و یک یا چند زیر کلاس که از آن گسترش یافتهاند. من در حال تلاش برای پیادهسازی قابلیت ایجاد عناصر HTML بهصورت آسان هستم.

کلاس اول من، کلاس پایهای است که شامل متدهای مشترک برای همه عناصر HTML میباشد:

class $NewElement<E extends HTMLElement> {

    public element: E = null;

    constructor(name: string) {
        this.element = <E>document.createElement(name);
    }

    public className(className: string): any {
        this.element.className = className;
        return this;
    }

}

من کلاسهای دیگری دارم که هر کدام کلاس بالا را گسترش میدهند. به عنوان مثال، این یکی مخصوص تگ img است:

class $NewImage extends $NewElement<HTMLImageElement> {

    constructor() {
        super('img');
    }

    public source(fileName: string): $NewImage {
        this.element.src = fileName;
        return this;
    }

}

من میخواهم چیزی شبیه به این را، به صورت امن از نظر نوع، انجام دهم:

let img = new $NewImage().className('a').source('b').element;

چطور میتوان این کار را انجام داد؟ بعد از فراخوانی className()، من دیگر با یک شیء $NewImage سر و کار ندارم، بلکه با یک شیء $NewElement سر و کار دارم، که متد source() را ندارد.

پاسخ شماره ۱

شما میتوانید از this به عنوان یک نوع استفاده کنید، به این معنا که نوع بازگشتی همان نوعی است که این متد روی آن فراخوانی شده است:

class $NewElement<E extends HTMLElement> {
    public element: E;
    constructor(name: string) {
        this.element = <E>document.createElement(name);
    }
    public className(className: string): this {
        this.element.className = className;
        return this;
    }
}

class $NewImage extends $NewElement<HTMLImageElement> {
    constructor() {
        super('img');
    }
    public source(fileName: string): this {
        this.element.src = fileName;
        return this;
    }
}

let img = new $NewImage().className('a').source('b').element; //works