Mapping TypeScript Types: Transforming type attributes into type instances

I'm currently working on converting a group of class constructors into a mapped object with properties that are functions returning instances.

For instance:

// Auto-generated utility from external source:
class FooClient { getData() {}}
class BarClient { getData() {}}

export const Clients = {
    FooClient,
    BarClient
}

This can then be used like:

import { Clients } from './somemodule';

type ClientTypes = typeof Clients;

function getFooData(c: ClientTypes) {
  const fooClient = new c.FooClient();
  return fooClient.getData();
}

What I want to achieve is replacing the classes / constructors with factory functions:

type Factories = {
  [Property in keyof ClientTypes as `use${Property}`]: () => ClientTypes[Property]
}

function getFooData(f: Factories) {
  const fooClient = new (f.useFooClient());  // <-- use function returns the original constructor type
  return fooClient.getData();
}

My query is, how can I adjust the return type in the mapped type so that it doesn't return a constructor but rather the value as if the constructor had been invoked.

For example:

function getFooData(f: Factories) {
  const fooClient = f.useFooClient();  // <-- instead returns an instance
  return fooClient.getData();
}

Is there any specific keyword I should use to indicate that I want my function to return an instance of a type rather than the type itself?

Answer №1

Almost there! While defining the return type of use_, you inadvertently returned the class type instead of making it behave like a regular function that returns a class. To fix this, you'll need to put in some additional effort by creating a new function that will return

InstanceType<ClientTypes[Property]>
.

class FooClient { getData() {}}
class BarClient { getData() {}}

export const Clients = {
    FooClient,
    BarClient
}

type ClientTypes = typeof Clients;

type Factories = {
  [Property in keyof ClientTypes as `use${Property}`]: () => InstanceType<ClientTypes[Property]>
}


function getFooData(f: Factories) {
  const fooClient = f.useFooClient();
  return fooClient.getData();
}

Check out TypeScript Playground Link here

If you wish to incorporate constructor parameters into this callback function, then simply add a rest parameter to the function type specifying the type as

ConstructorParameters<ClientTypes[Property]>
.

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

In React TypeScript, the property types of 'type' are not compatible with each other

I have a unique custom button code block here: export enum ButtonTypes { 'button', 'submit', 'reset', undefined, } type CustomButtonProps = { type: ButtonTypes; }; const CustomButton: React.FC<CustomButtonProp ...

What are the steps to retrieve the original source code of an HTML file, specifically in Angular 2 RC4

Is there a way to retrieve the source code that I manually typed in my IDE using JavaScript? Note: I am working with angular2 rc4. I attempted to access it using Reflect.getMetadata, but encountered errors indicating that it is not functioning properly. ...

Using an Enum member as an index for a Record<S,O> type: Is it possible?

When designing a library, I wanted to implement the feature of allowing users to modify its configuration using presets. My approach was to define an Enum containing all possible presets and exporting it with the select function. Unfortunately, my initial ...

Executing a function in Angular depending on the values emitted by two distinct observables

As someone who is relatively new to Angular (6 months), I am facing a challenge with my code. Currently, I have two observables that are working independently of each other: this.siteService.siteChanged$ .pipe(takeUntil(this.disconnect$)) .subscribe(_ ...

Exploring the Possibilities with Material UI v4: Expanding on PaletteColor

Looking to make a simple adjustment in Material UI v4's (v4.11) palette, specifically adding a new field to PaletteColorOptions like darker?: string. The type definition can be found in the relevant Material UI module: createPalette.d.ts export type ...

Tips for implementing a feature in Angular 6 that enables an input box to accept both negative and positive values within the range of 0 to

HTML markup <input type="number" min="0" max="100" required placeholder="Charge" [(ngModel)]="rateInput" name="rateInput" [formControl]="rateControl"> Implementing TypeScript validation this.rateControl = new FormControl("", [Validators.max(100) ...

Decorators in Angular 9 do not have the capability to support function expressions

Currently, I am working with Angular 9 and facing an issue while generating dynamic routes values during runtime. I have implemented a ComplexUrlRouter to achieve this functionality and integrated it into my Route configuration. However, I encountered the ...

Arrange and conceal legendary items based on their values using Chartjs in Angular

Is there a way to hide the legend or not display it when the value supplied is 0, and also order items in ascending order? export class DoughnutChartComponent { doughnutChartLabels: Label[] = ['CR1', 'CR2', 'CR3', 'CR4 ...

Properties in a model class in typescript that share common characteristics

I need a data model class that can store identical information for two individuals simultaneously. For instance: export class People { constructor( public person1Name: string = '', public person1Age: number = 0, public ...

Mastering the process of importing AngularJS submodules in TypeScript

Currently, I am in the process of structuring an AngularJS (Angular 1) project using TypeScript. To compile TypeScript & ES6 to JavaScript, I have set up webpack. In my webpack configuration, I only compile the "app.ts" file and any other files it imports ...

What is the best way to run tests on TypeScript-built node apps utilizing threads?

My server is written in TypeScript, built with rollup and runs on node. Currently, I have numerous tests including unit tests that import and test specific entities, as well as end-to-end tests that start the server (with database and other components) and ...

Top method for changing Enum to Set in TypeScript

Take a look at the enum below: enum Animes { OnePiece = 'One Piece', Naruto = 'Naruto', Bleach = 'Bleach' } How can we efficiently transform this enum into a Set? ...

Error message: Unable to locate module without the '.js' extension at the end of the import file path

It seems like the solution is not difficult, just something obvious. I am working on a simple TypeScript project. There are no modules involved, only TypeScript for compilation. The TS files compile into JS files in the dist folder, which are then connect ...

React failing to fetch GraphQL query successfully

I've been experimenting with using GraphQL in React through the useQuery API as shown below: const {loading, data, error} = useQuery<BaseUser, BaseUserVars>( GET_DASHBOARD_USER, {variables: {id: "1"}} ) Withi ...

How to import an HTML file using TypeScript

I need to load an html file located in the same directory as the typescript file and return it from the function. public ...(... ) : angular.IHttpPromise<string> { ... return $http({ method: 'GET', url: &apos ...

Angular Build Showing Error with Visual Studio Code 'experimentalDecorators' Configuration

Currently experiencing an issue in VSC where all my typescript classes are triggering intellisense and showing a warning that says: "[ts] Experimental support for is a feature that is subject to change in a future build. Set the 'experimentalDeco ...

Issue encountered when utilizing TypeORM within NestJS: Unable to import Entity Repository

Issue with EntityRepository Import Despite having @nestjs/typeorm installed, VS Code is not recognizing the decorator I need to use. Any suggestions on how to resolve this? ...

TypeScript: Type narrowing issue when deconstructing an array within a function

I am working with an object that has a const assertion: const foo = { bar: ['a', 'b'], } as const; My objective is to create a function that can update the bar array and accurately infer the new type. I have successfully achieved th ...

Merge arrays values with Object.assign function

I have a function that returns an object where the keys are strings and the values are arrays of strings: {"myType1": ["123"]} What I want to do is merge all the results it's returning. For example, if I have: {"myType1": ["123"]} {"myType2": ["45 ...

Using React to simulate API calls outside of testing environments

For instance, I encounter issues when certain endpoints are inaccessible or causing errors, but I still need to continue developing. An example scenario is with a function like UserService.getUsers where I want to use fake data that I can define myself. I ...