Finding the data type of a collection of functions stored in an associative array

I am seeking assistance in creating a function where the caller must provide an associative array of functions. The function should return a new associative array with the same keys and return types, but each function will take a different argument compared to the original map.

My challenge lies in defining the return type for this function.

So far, I have attempted:

type FunctionMap<A> = {
    [functionName: string]: <R>(a: A) => R
}

type B = {};
const b: B = {};

const FunctionMapArg: FunctionMap<B> = {
    getA: b => 1,
    getB: b => "two"
};

type TypeOfFunctionMapArg = typeof FunctionMapArg;


type ReturnedFunctionMap<T extends TypeOfFunctionMapArg> = {
    [P in keyof T]: () => ???; // using Typescript 2.6
//    [P in keyof T]: () => ReturnType<T[P]); // using Typescript 2.8
}

However, I encounter issues right from the start - I cannot even declare the FunctionMapArg constant without receiving the following compiler error:

Type '{ getA: <R>(a: any) => number; getB: <R>(a: any) => string; }' is not assignable to type 'FunctionMap<any>'.
Property 'getA' is incompatible with index signature.
Type '<R>(a: any) => number' is not assignable to type '<R>(a: any) => R'.
Type 'number' is not assignable to type 'R'.

If anyone could guide me on the correct path, especially one that is compatible with Typescript 2.6, it would be greatly appreciated.

Answer №1

I'm not entirely certain about the specific requirements for the arguments of the input and output functions, so I am providing an educated guess. Utilizing mapped types and inference from mapped types can help in representing the desired transformation effectively. These features are compatible with TypeScript 2.6. For instance, if your input functions have a structure like this:

type B = {
  // Define input function argument type here
};

const functionMapArg = {
  getA: (b: B) => 1,
  getB: (b: B) => "two"
};

declare const b: B;
const gotA = functionMapArg.getA(b); // number
const gotB = functionMapArg.getB(b); // string

The following demonstrates one possible way to transform functionMapArg:

type Functionize<T, A> = { [K in keyof T]: (a: A) => T[K] };
type C = {
  // Specify output function argument type here
};
declare function alterFunctions<T>(fs: Functionize<T, B>): Functionize<T, C>;

Functionize<T, A> converts a standard object type T into a mapped type where the keys K match those of T, and the values are functions that take A as input and return T[K]. The function alterFunctions() expects a Functionize<T, B> as input (such as functionMapArg) and outputs a Functionize<T, C>, with the TypeScript compiler inferring the type

T</code automatically. Here's how it works:</p>

<pre><code>const alteredFunctions = alterFunctions(functionMapArg);
declare const c: C;
const gotAnotherA = alteredFunctions.getA(c); // number
const gotAnotherB = alteredFunctions.getB(c); // string

Therefore, alteredFunctions is similar to functionMapArg but with methods that require an argument of type C</code instead of <code>B. Does this align with your needs?

Wishing you the best of luck and hope this information proves helpful!


Update: To streamline the process and avoid specifying the argument type for each function in functionMapArg, you can utilize a helper function that anticipates input of type Functionize<any, B> and returns the input unchanged, as shown below:

function asFunctionsOfB<F extends Functionize<any, B>>(fs: F): F {
  return fs;
}

This method enables the compiler to infer the argument type, as illustrated here:

const functionMapArg = asFunctionsOfB({
  getA: b => 1,
  getB: b => "two"
});

Trust this makes it clearer for you.

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

Guide to specifying a type as optional based on specific criteria

In coding, there exists a certain type that is defined as follows: type PropsType = { dellSelectedOption: (id: string, idOptions: string[]) => void; ownFilterData: Array<ActiveFilterAndPredFilterDataType>; watchOverflow: boolean; childre ...

Disable the functionality of the device's back button to prevent it from going back to the

For my project, I utilize popups to display important information to the user. When a popup is displayed, how can I override the functionality of the device's back button so that instead of navigating to the previous route, it will close the popup? ...

Tips for setting an argument with a promise data type

I am currently working on writing unit tests using jest to test two functions in a separate file called generator, where I generate fake data : generator.ts export async function generateReportData(overide = {}) { return { clientId: faker.data ...

Using SCSS based on the browser language in Angular: A Step-by-Step Guide

Is there a way to implement SCSS that is dependent on the user's browser language? When I checked, I found the browser language specified in <html lang = "de"> and in the CSS code as html[Attributes Style] {-webkit-locale: "en&quo ...

Tips for syncing the state data stored in local storage across all tabs with Ngxs state management

After converting the state data to base64 format using the Ngxs state management library, I am saving it. While I can retrieve all data across different tabs, any changes made in one tab do not automatically sync with other tabs. A tab refresh is required ...

Chart.js Axis Labels Orientation Guidelines

I am currently utilizing chart.js within an Angular 8 environment using Primeng. I am looking to customize the options for my chart as follows: For the y-axis ticks, set textDirection to 'ltr' For the x-axis ticks, set textDirection to 'rtl ...

Encountering a 403 error when attempting to upload files to Google Cloud Storage (GCS) using Signed URLs

The main aim is to create a signed URL in the api/fileupload.js file for uploading the file to GCS. Then, retrieve the signed URL from the Nextjs server through the nextjs API at localhost://3000/api/fileupload. Finally, use the generated signed URL to upl ...

What is a practice for utilizing navCtrl.push() with a variable storing a class name?

Currently, I am utilizing Visual Studio Code for Ionic 3 development with AngularJS/Typescript. In my code, I am using this.navCtrl.push() to navigate to different pages within the application. Specifically, I have two classes/pages named "level1" and "lev ...

Access file using operating system's pre-installed application

How can I open a file using the default application for that file type on different operating systems? For example, when opening an image.png on Mac, it should open with Preview, and on Windows with Windows Photo Viewer. I know you can use open image.png ...

Can a TypeScript interface inherit from multiple other interfaces simultaneously?

Hello Angular Community, I have a question regarding nesting three interfaces within another interface. Let me explain with some code: I am attempting to integrate the IProject1, IProject2, and IProject3 interfaces into the IAdmin2 interface: Thank you ...

Ways to extract information from an Object and save it into an array

In my Angular2 project, I am working on retrieving JSON data to get all the rooms and store them in an array. Below is the code for the RoomlistService that helps me fetch the correct JSON file: @Injectable() export class RoomlistService { constructor( ...

Leveraging the power of Framer Motion in combination with Typescript

While utilizing Framer Motion with TypeScript, I found myself pondering if there is a method to ensure that variants are typesafe for improved autocomplete and reduced mistakes. Additionally, I was exploring the custom prop for handling custom data and des ...

Unveiling RxJs: The secret to extracting the notifier value using the takeuntil operator

I have a straightforward Rxjs timer set up that runs until a notifier emits a signal, it's pretty basic so far. enum TimerResult = { COMPLETE, ABORTED, SKIPPED }; _notifier: Subject<TimerResult> = new Subject(); notifier$: Observab ...

Issues with mat-input functionality within a mat-table in Angular 8

I'm encountering an issue with my mat-table. The input field within the table is not functioning properly. All rows are sharing the same input field, so when I type text into the box, it appears in all rows. Here is my code: <ng-container matColum ...

The type 'AxiosResponse<IUser, any>' is not to be mistaken for an array type

I am facing a minor issue while working with axios response in my code. I have a method that fetches user profiles from an API: static async getProfileById(id: string | undefined){ const jwt = localStorage.getItem("jwt"); const response ...

MSBUILD encounters numerous JQuery errors when compiling a web project with TypeScript

Currently, I am working on a .net core 3.1 (netcoreapp3.1) razor pages project that includes typescript files and a few javascript files. The project builds perfectly from Visual Studio 2019 (professional) as well as from the command line using MSBuild. H ...

JavaScript and JSX file formats are used for a variety of types

I am currently delving into the react-grid-layout library, and I find myself perplexed by the presence of types in .js/.jsx files. Here's an example excerpt from a .jsx file: type Props = { children: ReactElement<any>, cols: number, conta ...

Assign an event listener to a collection of elements

Suppose I have an Array containing elements and another Array consisting of objects in the exact same index order. My goal is to add a click event for each element that will display a specific property of each object. For instance: myDivArray = [ div0, d ...

How to safely add multiple objects to an array in TypeScript & React without replacing existing objects - Creating a Favorites list

I'm in the final stages of developing a weather application using TypeScipt and React. The last feature I need to implement is the ability for users to add queried locations to a favorites list, accessed through the "favorites" page. By clicking on a ...

Determine the tuple data type by analyzing a union of tuples using a single element as reference

Looking for a way to work with a union of tuples: type TupleUnion = ["a", string] | ["b", number] | [Foo, Bar] // ... In need of defining a function that can handle any type K extends TupleUnion[0], with the return type being inferred ...