Using TypeScript to Return a Derived Class as a Method's Return Type

I'm currently facing a challenge with an abstract class in typescript that includes a method to provide a callback for later use. The issue lies in the return type of the method, as it is set to the class itself, preventing me from using fluent style coding when extending the class. Specifically, I am working on extending the class and struggling to figure out how to make the method return the derived class type:

export abstract class Wizard {
   ...

   public onPageChanging(handler: PageChangingHandler): Wizard { // Returns Wizard (but I would like this to be the derived class instead)
       this.onPageChangingHandler = handler;
       return this;
   }

   public onPageChanged(handler: PageChangedHandler): Wizard { // Returns Wizard (but I would like this to be the derived class instead)
       this.onPageChangedHandler = handler;
       return this;
   }
   ...
}

export class StepWizard extends Wizard {
   ...
}

Snippet of the calling code:


export class Foo {

    private wizard: StepWizard;

    ...
    wireUpWizard() {
        this.wizard = new StepWizard({ 
             elem: HTMLElement,
        }).onPageChanging(pc => {
          // Handle Page Changing
        }).onPageChanged(pc => {
          // Handler Page Changed
        });

        // Problem arises due to inability to use fluent chaining, since onPageChanging/onPageChanged returns Wizard instead of StepWizard
    }

    ...

}

I understand that I need to utilize Generics somehow in order to return a Generic type from onPageChanging and onPageChanged methods, but I have yet to find a solution.

Any assistance would be greatly appreciated.

Answer №1

If you're searching for information on the polymorphic this type, you've come to the right place.

export abstract class Wizard {
   ...

   public onPageChanging(handler: PageChangingHandler): this { // <-- this is crucial
       this.onPageChangingHandler = handler;
       return this;
   }

   public onPageChanged(handler: PageChangedHandler): this { // <-- don't forget this
       this.onPageChangedHandler = handler;
       return this;
   }
   ...
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Caution in version 3.5.1 of Vue Router: The tag prop of `<router-link>` is now obsolete and has been eliminated in Vue Router 4

After updating the node packages of our Vue.js app, a warning is now appearing in the browser console: [vue-router] The 'tag' prop has been deprecated and removed in Vue Router 4. To remove this warning, use the v-slot API. Check out the migrat ...

What is the reason behind the warning "Function components cannot be given refs" when using a custom input component?

When attempting to customize the input component using MUI's InputUnstyled component (or any other unstyled component like SwitchUnstyled, SelectUnstyled, etc.), a warning is triggered Warning: Function components cannot be given refs. Attempts to acc ...

Navigational menu routing with AngularJS2 using router link paths

Currently, I am working on developing a navigation menu using angularJS2. Here is the snippet from my app.component.ts: import {provide, Component} from 'angular2/core'; import {APP_BASE_HREF, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, HashLocati ...

module 'next/router' cannot be located or its associated type declarations are missing

Running into some issues with my NextJS application. An unusual error message is appearing, even though my code is functioning smoothly without any errors. import { useRouter } from 'next/router'; // Cannot find module 'next/router' or ...

Utilizing Rxjs to transform an array of objects

My goal is to map an array of objects. Currently, I have the following code: return this.service.post(url, payload, this.httpOptions) .pipe( map((obj: any, index) => [({ ...obj, val1: obj[index].val1.id, v ...

Angular TypeScript test checking file size with Jasmine

Seeking optimal method for testing File size during input type="file" change event. Currently, my test specification appears as follows: it('attach file with too large size', () => { const file: File = { name: 'filename', ...

Unable to locate the name 'Cheerio' in the @types/enzyme/index.d.t file

When I try to run my Node application, I encounter the following error: C:/Me/MyApp/node_modules/@types/enzyme/index.d.ts (351,15): Cannot find name 'Cheerio'. I found a suggestion in a forum that recommends using cheerio instead of Cheerio. H ...

What is the best way to explain a function that alters an object directly through reference?

I have a function that changes an object's properties directly: function addProperty(object, newValue) { object.bar = newValue; } Is there a way in TypeScript to indicate that the type of object is modified after calling the addProperty function? ...

Tailored production method based on specific criteria

One of my challenges is to create a versatile factory method using typescript. The main objective is to initialize a class based on its name using generics, instead of employing if/else or switch statements. I am aiming for similar functionality as this ...

Store the selected checkbox values in an array when submitting in Ionic

One issue I am facing is that the checked checkboxes are returning true instead of the value of input (type="checkbox"). Array displaying responded checked or unchecked items I am unable to store this data in an array as needed. Additionally, I cannot sp ...

Is it possible for a React selector to retrieve a particular data type?

As a newcomer to React and Typescript, I am currently exploring whether a selector can be configured to return a custom type. Below is a basic selector that returns a user of type Map<string, any>: selectors/user.ts import { createSelector } from ...

What is the best way to define the type of an object in TypeScript when passing it to a function

I am currently working on a function that accepts an object of keys with values that have specific types. The type for one field is determined by the type of another field in the same object. Here is the code: // Consider this Alpha type and echo function. ...

Ever tried asynchronous iteration with promises?

I have a specific code snippet that I am working on, which involves registering multiple socketio namespaces. Certain aspects of the functionality rely on database calls using sequelize, hence requiring the use of promises. In this scenario, I intend for t ...

Tips for establishing communication between a server-side and client-side component in Next.js

I am facing a challenge in creating an interactive component for language switching on my website and storing the selected language in cookies. The issue arises from the fact that Next.js does not support reactive hooks for server-side components, which ar ...

Tips for creating a tailored Express.js request interface using Typescript efficiently

I have been working on designing a custom Express request interface for my API. To achieve this, I created a custom interface named AuthRequest, which extends Request from Express. However, when attempting to import my interface and define req to utilize t ...

What is the best way to show all cards in Angular when no filtering input is provided?

I have implemented a filter feature for multiple cards in Angular using Pipes. The filter works well, but I am facing an issue where no cards are displayed when there is no input value provided. I would like all the cards to be displayed when no input is g ...

Arrange the array based on the order of the enumeration rather than its values

Looking to create an Array of objects with enum properties. export enum MyEnum { FIXTERM1W = 'FIXTERM_1W', FIXTERM2W = 'FIXTERM_2W', FIXTERM1M = 'FIXTERM_1M', FIXTERM2M = 'FIXTERM_2M', FIXTERM3M = 'FIX ...

The error message "Property 'data1' is not a valid property on the object type {}"

const Page: NextPage = ({data1}:{data1:any}) => { const [open, setOpen] = React.useState(false); const [data, setData] = React.useState(data1); const handleAddClick = () => { setOpen(true); }; ..... } export async function getServerS ...

The implementation of getStaticPaths was done independently of getStaticProps - TypeScript

I am currently in the process of setting up a new blog using a combination of nextJS, TypeScript, and sanity CMS. The homepage is already set up to display posts perfectly. Next on my list is to display the details of each post when it is clicked, based on ...

Steps to activate zone-conscious bluebird assurances in Angular 8

In order to make all the promises in my Angular 8 project cancelable, I embarked on a quest to find the perfect library for the job. It was during this search that I stumbled upon bluebird.js, a promising candidate ;-) Following these guidelines on integr ...