Preserving type information while dynamically adding functions to an object

Within my functions.ts file, I have defined 2 functions. Each of these functions accepts an api object and returns a function with varying argument types, numbers, and return types.

export function f1 (api: Api) {
  return function (a: number): number[] {/* not important */}
};
export function f2 (api: Api) {
  return function (a: string, b: string): boolean {/* not important */}
};

Now, with a global api: Api object, I aim to create an object that includes the fields f1 and f2, with each field holding the inner function from the aforementioned functions.

Manually, this can be achieved as follows:

const api: Api = ...;
const myObject = {
  f1: f1(api),
  f2: f2(api),
}

This manual method works perfectly.

However, the next challenge is to achieve this dynamically, without explicitly typing out f1 and f2.

Here is my initial attempt:

import * as functions from './functions';

const api: Api = ...;
const myObject = Object.keys(functions).reduce((accumulator, functionName) => {
  accumulator[functionName] = functions[functionName](api);
}, {} as ???);

The code functions correctly, but the typings are incorrect. I am unsure what to input instead of ???. Using

{[index: keyof typeof functions]: (...args: any[]) => any}
would work, but it would result in losing type information.

I have explored TypeScript's Parameters<T> and ReturnType<T>, and suspect that there may be a solution involving infer, but I am struggling to grasp it.

Answer №1

The functionality is working fine, although the typings are an issue. I'm uncertain about the replacement for ???.

One possible solution is to create a custom type that associates each function name with its return type.

type ReturnTypes<T> = {
    [K in keyof T]: T[K] extends (...args: any) => any
    ? ReturnType<T[K]>
    : never;
};

const myObject = Object
    .keys(functions)
    .reduce(
        (accumulator, functionName) => {
            accumulator[functionName] = functions[functionName](api);
            return accumulator;
        },
        {} as ReturnTypes<typeof functions>
    );

const result1: number[] = myObject.f1(10);
const result2: boolean = myObject.f2('foo', 'bar');

You can test this code in the TypeScript 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

Best Practices for Converting TypeScript to JavaScript

What is the recommended approach to converting this JavaScript code into TypeScript? JAVASCRIPT: function MyClass() { var self = this, var1 = "abc", var2 = "xyz"; // Public self.method1 = function () { return "somethin ...

Guide to leveraging various build targets while executing the capacitor sync command within an Angular project

In my current Angular project, I have been utilizing Capacitor. Within my angular.json file, I have set up various build targets such as development, staging, and production. To deploy with different configurations, I use the command ng build --configurati ...

Utilize TypeScript to access scope within a directive

Is there a way to access the controller's scope properties using my custom TypeScript directive? For example, in this snippet below, I am trying to retrieve and log scope.message: /// <reference path="typings/angularjs/angular.d.ts" ...

When posting on social platforms, the URL fails to display any metadata

We recently completed a project (Web Application) using React .net core with client-side rendering in React. One challenge we encountered was that when the app loads in the browser, it only displays the static HTML initially without the dynamic meta tags. ...

What is the best way to verify a numerical input in a React component?

When I use the return statement, I attempt to validate a number and if it's not valid, assign a value of 0. However, this approach doesn't seem to be working for me. Is there an alternative method to achieve this? return ( <Input col ...

Encountered an error while attempting to compare 'true' within the ngDoCheck() function in Angular2

Getting Started Greetings! I am a novice in the world of Angular2, Typescript, and StackOverflow.com. I am facing an issue that I hope you can assist me with. I have successfully created a collapse animation for a button using ngOnChanges() when the butto ...

Update the value in a nested object array by cross-referencing it with a second nested object array and inserting the object into the specified

I have a large array of objects with over 10,000 records. Each object contains an array in a specific key value, which needs to be iterated and compared with another array of objects. If there is a match, I want to replace that value with the corresponding ...

What is the best method for calculating the total of a column field within an array in Angular 9.1.9?

I am using Angular 9.1.9 and Html to work with a nested array field in order to calculate the total sum and display it in a row. Within my array list ('adherant'), I am aiming to sum up a specific column's values ({{ Total Amount }}) and pr ...

Is it possible to apply search filters within a child component in Angular?

I have a situation where I am passing data from a parent component to a child component using *ngFor / @input. The child component is created multiple times based on the number of objects in the pciData array. pciData consists of around 700 data objects, ...

An issue occurred while trying to run Ionic serve: [ng] Oops! The Angular Compiler is in need of TypeScript version greater than or equal to 4.4.2 and less than 4.5.0, but it seems that version 4

Issue with running the ionic serve command [ng] Error: The Angular Compiler requires TypeScript >=4.4.2 and <4.5.0 but 4.5.2 was found instead. Attempted to downgrade typescript using: npm install typescript@">=4.4.2 <4.5.0" --save-dev --save- ...

Having trouble retrieving the JSON data from the getNutrition() service method using a post request to the Nutritionix API. Just started exploring APIs and using Angular

When attempting to contact the service, this.food is recognized as a string import { Component, OnInit } from '@angular/core'; import { ClientService } from '../../services/client.service'; import { Client } from '../../models/Cli ...

Tips for setting a default value in a generic function in TypeScript, where the default argument's type is determined by the generic parameter

One of my functions calls an API and accepts a parameter to limit the fields returned by the API: type MaximumApiResponse = { fieldA: string, fieldB: number } const f = async <U extends keyof MaximumApiResponse>( entity: number, prop ...

Create an interface that inherits from a class

I am currently in the process of converting some code that attempts to create an instance of http.ServerResponse. However, typescript is throwing an error: [ts] Property 'ServerResponse' does not exist on type 'typeof "http"'. I hav ...

Utilizing *ngIf for Showing Elements Once Data is Completely Loaded

While working on my Angular 2 app, I encountered an issue with the pagination UI loading before the data arrives. This causes a visual glitch where the pagination components initially appear at the top of the page and then shift to the bottom once the data ...

Unveiling the types of an object's keys in Typescript

I am currently utilizing an object to store a variety of potential colors, as seen below. const cardColors = { primaryGradientColor: "", secondaryGradientColor: "", titleTextColor: "", borderColor: "&quo ...

In the realm of Typescript Angular, transferring the value of an object's property to another property within the

I'm working with a large TypeScript object and I am hoping to automate certain parts of it to streamline my workflow. myObject = [ { id: 0, price: 100, isBought: false, click: () => this.buyItem(100, 0) } buyItem (it ...

angular-bootstrap-mdindex.ts is not included in the compilation result

Upon deciding to incorporate Angular-Bootstrap into my project, I embarked on a quest to find a tutorial that would guide me through the download, installation, and setup process on my trusty Visual Studio Code. After some searching, I stumbled upon this h ...

What is the most effective way to retrieve a specific type of sibling property in TypeScript?

Consider the code snippet below: const useExample = (options: { Component: React.ComponentType props: React.ComponentProps<typeof options.Component> }) => { return } const Foo = (props: {bar: string; baz: number}) => <></& ...

The Angular Service code cannot be accessed

Currently, I am utilizing Local Storage in an Angular 5 Service by referencing https://github.com/cyrilletuzi/angular-async-local-storage. My goal is to retrieve data from storage initially. In case the value is not present, I intend to fetch data from fir ...

Leveraging the find method to sort through an array with dual parameters

I'm facing an issue while trying to filter my array of objects using two parameters. Despite having an object in the array with the same values as the parameters, the result is empty. const item = this.lista.find(i => i.number === rule.number && ...