What is the best approach to have a method in the parent class identify the type based on a method in the child class using TypeScript?

I'm faced with a code snippet that looks like this.

class Base{
   private getData(): Data | undefined{
        return undefined
   }
   public get output(): Data | undefined {
        return {
             data: this.getData()
        }
   }
}
class A extends Base{
    private getData(){
        return getDatasFromOutside()
    }
    //......
}
class B extends Base{
   //......
}
let x = new A()
let x2 = new B()
x.output.data // I want this to be considered as type Data
x2.output.data // but in this case, it should remain undefined

In the current setup, typescript interprets x.output.data as Data | undefined when it is actually just Data.

Is there a way to correct this issue?

Or would it be more appropriate to avoid having A and B share the same base class altogether?

Answer №1

To represent this concept, you can utilize generics in the following way:

abstract class Base {
  public getData(): Data | undefined {
    return undefined
  }
  getOutput<D>(this: {getData(): D}): { data: D } {
    return {
      // ... other outputs
      data: this.getData()
    };
  }
}
class A extends Base {
  public getData(): Data {
    return getDatasFromOutside()
  }
}
let x = new A()
x.getOutput().data // getOutput<Data>(this: A): Data

(playground)

Nevertheless, there are certain limitations to this approach:

  • The getData method must be declared as public to be considered part of the type.
  • The output getter needs to be a method since TypeScript does not support generics or this types on accessor property declarations.

An improved alternative would involve an abstract base class with two different implementations:

abstract class Base<D = undefined> {
  protected abstract getData(): D;
  public get output(): { data: D } {
    return {
      // ... other outputs
      data: this.getData()
    };
  }
}
class A extends Base<undefined> {
  protected getData() {
    return undefined;
  }
}
class B extends Base<Data> {
  protected getData() {
    return getDatasFromOutside()
  }
}
let x = new B()
x.output.data // Data

(playground)

Answer №2

To properly define the method, consider declaring it like this:

protected abstract fetchData(): Data;

Within the Primary class, ensure that the result getter always returns a valid Data instead of null.

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

What is the best way to handle this unconventional JSON structure?

Looking for some insight on retrieving process information from a VPS with PM2. However, the JSON string returned by PM2 is malformed, making it impossible to run JSON.parse(). An example of the output provided by PM2: '{data: 0, informations: " ...

Ways to incorporate external JavaScript files into a React component

I have been attempting to incorporate external javascript files into my react component. When I included them in a basic html file using script tags, everything worked smoothly. However, I am unsure of how to achieve this within a react component. < ...

Dealing with multiple occurrences of forward slashes in a URL

Currently utilizing React and grappling with resolving duplicate forward slashes on my site in a manner similar to Facebook. The process functions as follows: For example, if the user visits: https://facebook.com///settings, the URL is then corrected to h ...

Responsive images in CSS3/HTML5 are designed to adapt to different

I am looking to implement responsive image sizing based on the webpage size. My images come in two different sizes: <img src="images/img1.jpg" data-big="images/img1.jpg" data-small="images/img1small.jpg" alt=""></img> The data-small image has ...

What are some ways to adjust the size of the option field in a select menu?

In my ionic popup, I have a HTML property called select with nested options. Below is the code snippet along with the applied CSS. My query is how can I set the white space to occupy the entire area of the select? https://i.stack.imgur.com/iPqAa.png http ...

Guide to separating the bytes of a number and placing them into an Uint8Array

I am looking to convert a JavaScript number into the smallest possible uint8array representation. For example : 65 535 = Uint8Array<[255,255]> (0b1111111111111111 = [0b11111111, 0b11111111]) 12 356 = Uint8Array<[48,68]> (0b0011000001000100 = [ ...

"Identify the protocol name (string) based on a specific port number in TCP/UDP communication

Is there a built-in function in any web-oriented language to return protocol names based on port numbers? For example, if we have the following code: protocol = get_protocol_name(22) print protocol We would expect it to print out "ssh". A more detailed ...

What is the best way to load a component every time the function is called?

Currently, I am utilizing Angular and endeavoring to create reusable actions such as bulk updates, deletes, and deactivations. I have incorporated all of these actions into another component and aim to use it as a generic method. This implies that I have ...

Tips for retrieving user input and displaying it on an HTML page

I have encountered an issue with displaying user input in a table. The code for the table display is as follows: <tr ng-repeat="user in users" ng-class-even="'bg-light-grey'" ng-if="isLoading==false"> <td> ...

Limit function parameter types to object keys

Is it possible to constrain my function parameter to match the keys of an object? I want to achieve something similar to this: export const details = { x: { INFO_x: 'xxx' }, y: { I ...

Convert the numerical values from an array into an input field format

Currently, I have two inputs and an array with two number positions. The v-model in each input corresponds to a value in the array. Whenever a change is made in either input field, it reflects on the corresponding position in the array, which works perfect ...

Consistently encountering incorrect values during onClick events

I am using a Table to display certain values const [selected, setSelected] = React.useState<readonly number[]>([]); const isSelected = (id: number) => selected.indexOf(id) !== -1; return ( <TableContainer> <Table sx={{ width ...

Turn off choices by utilizing data type attribute values within select2 version 4

I'm attempting to deactivate the options by using the data-type attribute specified for each option in select2. Unfortunately, my attempts have been unsuccessful thus far. In addition, I am encountering this error within the change event handler: ...

Determine the category of a container based on the enclosed function

The goal is to determine the type of a wrapper based on the wrapped function, meaning to infer the return type from the parameter type. I encountered difficulties trying to achieve this using infer: function wrap<T extends ((...args: any[]) => any) ...

I am attempting to update the URL of an iframe dynamically, but I am encountering an issue: the Error message stating that an Unsafe value is being

Currently, I am attempting to dynamically alter the src of an iframe using Angular 2. Here is what I have tried: HTML <iframe class="controls" width="580" height="780" src="{{controllerSrc}}" frameborder="0" allowfullscreen></iframe> COMPONE ...

Inconsistent behavior of transform scale() between Chrome and Safari upon page refresh

My goal was to design a code that would adjust all content according to the browser size, ensuring that everything remains visible even when the window is resized. var docHeight = $(document).height(); var winHeight; var zoomRatio; function z(number) { ...

Update image source dynamically using AJAX and jQuery

Within my app, there exists a web page that contains numerous images with dynamically generated source URLs obtained by sending get requests to the rails server. Initially, these images are assigned a default source. Upon loading the page, another request ...

The most efficient method for retrieving data in React

Recently, I started working on a React App integrated with Riot API to display users' recent games and more. As part of this project, I'm utilizing React and NextJS (fairly new to NextJS). However, I'm contemplating the most efficient way to ...

Using jQuery to include the value of an array index in the output

Looking for guidance on jQuery & JavaScript. I have successfully implemented code that adds a new text input field based on the user's selection from a dropdown select field. <script> $(function() { var input = $('<input placeholder= ...

Iterating through an array of objects and performing reduction based on various key-value pairs

I am faced with a challenge of consolidating a large array of objects into one single array that has a specific structure. Each item, such as a banana, needs to be present in two separate objects for buy orders and sell orders, each with their own distinct ...