A function that accepts a type parameter and returns an instance of that specific type

My goal is to implement a factory method for all my Axios API classes that are generated by the OpenAPI generator.

The Open-API tool creates a BaseAPI class with a constructor, and then generates several API classes that extend this BaseAPI based on my Backend Controllers.

I attempted to create the following function:

import { BaseAPI } from "@/api/base";

abstract class AbstractControllerHandler {
  protected createApi<T extends typeof BaseAPI>(clazz: T)  {
    return new clazz(
      undefined,
      "",
      AxiosInstanceHolder.getInstance().getAxiosInstance(),
    );
  }

This function is then utilized by another class:

import { CrudCapitalsourceControllerApi } from "@/api";

class CapitalsourceControllerHandler extends AbstractControllerHandler {
  private api: CrudCapitalsourceControllerApi;

  public constructor() {
    super();

    this.api = super.createApi(CrudCapitalsourceControllerApi);
  }
}

The CrudCapitalsourceControllerApi is defined as a subclass of BaseAPI and is automatically generated by OpenAPI.

When attempting to use the createApi function, I encountered a ts(2739) error which indicates that the returned type is BaseAPI, but it cannot be assigned to a variable of type CrudCapitalsourceControllerApi.

To resolve this issue, I believe I need to specify a return type for the createApi method. However, simply using T as the return type resulted in a ts(2322) error because I am returning an instance, not a type. Any suggestions on how I can address this problem? Perhaps something along the lines of "instanceof T" for the return type declaration?

Answer №1

Let's focus on the core issue in your code, as it lacks essential details needed for execution.

class Foo { baseAPI!: true }
class Bar extends Foo { foo!: true }

function createApi<T extends typeof Foo>(clazz: T) {
  return new clazz();
}

const bar: Bar = createApi(Bar) // encountering a type error because Foo cannot be assigned to Bar

The main concern lies in what is being constructed, not the constructor itself. Thus, that should be your generic parameter T.

If you modify createApi like this:

function createApi<T extends Foo>(clazz: new () => T) {
  return new clazz();
}

You will no longer face a type error here:

const bar: Bar = createApi(Bar) // works fine now

Check playground

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

Setting up Oauth2 OIDC in an Angular 8 application

I've been attempting to set up OAuth2 in my Angular project for user login. I followed the documentation, but whenever I try to log in, it keeps showing an Unauthorized error and I'm not sure how to resolve it. Here are my configurations: auth c ...

Unable to fetch data from API in React post-build

After developing an API that interacts with a web service from OpenWeather, everything was functioning smoothly on localhost. However, upon building and deploying the application with Vercel, the site rendered but failed to load the weather information. Th ...

What is the process for exporting a TypeScript function so that it can be accessed from the command line in a web browser?

const ident = (v) => {return v}; export default ident; Although the code compiles successfully, if I attempt to call ident from the browser's command line, it throws an error: VM1228:1 Uncaught ReferenceError: ident is not defined at <anon ...

What could be the reason for my function throwing a TypeError with the message "<function> is not a function"?

Every time I try to call a function that clearly appears to be defined as a function, I continuously receive the error message: TypeError: [function name] is not a function. To demonstrate the issue, here is a simple example: main.ts import someFunction ...

React.js: You cannot call this expression. The type 'never' does not have any call signatures

Could someone help me troubleshoot the error I'm encountering with useStyles? It seems to be related to Typescript. Here's the line causing the issue: const classes = useStyles(); import React from "react"; import { makeStyles } from & ...

Tips for creating an onClick event for a React Component that is passed as a prop to another component

I am currently in the process of creating a custom trigger component that can be passed down to another component. My goal is to implement a click event on this trigger component from the receiving component. If you'd like to see a live example, chec ...

Utilizing Angular for Select Options with Objects as Values

One issue I am encountering is with a form that contains select boxes using objects as values: <mat-option [value]="object"> While this works fine when creating new records, editing existing ones proves to be problematic because the object in the m ...

Enhance Tuple in Angular Component Properties

When using React, state variables can be created like this: const SomeComponent = ({ someProp }) => { const [value, setValue] = useState<boolean>(false); } I wonder if there is a similar way to achieve the spread of a tuple within an Angular co ...

What steps can be taken to ensure the visibility and accessibility of two vertically stacked/overlapped Html input elements in HTML?

I have encountered a challenge with my HTML input elements. There are two input elements that overlap each other, and I would like to make both inputs visible while only allowing the top input to be editable. I have tried several approaches involving z-ind ...

Ways to extract information from nested JSON arrays in objects?

We are currently developing an Extension for WeClapp, with Custom Attributes that can be added to various Datatypes within the platform. These Attributes are accessible through a nested JSON object Array. Here is an example of the interface: export inter ...

Updating the value of a dropdown in React Testing Library

When testing an input, the process is as follows: it('test input', () => { const { getByTestId, getByLabelText } = render(<MyComponent />); const myButton = getByTestId('submit-button'); expect(myButton).toBeInTh ...

The String retrieved from the API response does not support displaying line breaks, whereas a hard-coded string can successfully display line breaks

Greetings, My frontend is built on Angular 8, with a Java API service serving as the backend. I need to fetch a String from the backend, which will contain '\n' line breaks. For example: "Instructions:\n1. Key in 122<16 digit ...

Steps for clearing the chosen input data

I am currently developing an Angular 6 application and I am working on implementing a multiple select feature using just an input box without relying on any third-party plugins, jQuery, datalist, or select boxes. The solution needs to be purely input box b ...

Enhancing Vue prop with TypeScript typing

In my Vue component, I am working with a prop called tabs. The format for this prop is expected to be as follows: [{ id: string title: string color: `#${string}` },{ id: string title: string color: `#${string}` }] Currently, I am utilizing Lar ...

What is the proper way to utilize this xd-file package?

I'm currently working on manipulating an Adobe XD file using a specific package. If you're interested, here's the link to the package: xd-file My goal is to incorporate this code snippet into a JavaScript file, utilizing Node.js. The meth ...

What is the method for retrieving the second type of property from an array of objects?

I have a collection of objects that map other objects with unique identifiers (id) and names (name). My goal is to retrieve the name corresponding to a specific id. Here is my initial approach: const obj = { foo: { id: 1, name: 'one' }, ...

Encountering a Typescript error when defining a curried function after an uncurried function

Upon placing the uncurried definition of a method above the curried definition, I encountered an error stating: Expected 1 arguments, but got 2.ts(2554). The dtslint test that failed reads as follows: function match(regExpression: RegExp, str: string): st ...

Issue with the functionality of Angular 2 router not functioning correctly

After updating the Angular router from version 2 to "3.0.0-beta.2", my app stopped working. I suspect the issue lies in the following code snippet: Files: app.component.ts import { Component} from '@angular/core'; import {NavComponent} from ". ...

Creating a spy object in Jest just got easier with the `

If you want to create a spy object with Chai, you can do so by using the following syntax: chai.spy.object([ 'push', 'pop' ]); For jasmine users, the equivalent code would be: jasmine.createSpyObj('tape', ['play', ...

Leveraging IF conditions on part of the worksheet title

Currently, my script is performing the task of hiding three columns for tabs in a workbook that start with "TRI". However, the execution speed is quite sluggish. I am seeking suggestions on how to optimize and enhance the performance. If possible, please p ...