Generate a map object by combining functions

Currently, I am attempting to create a helper function that accepts an object of functions and wraps it in another function;

const bindFn = (obj, wrapFn) => Object.entries(obj).reduce((carry, [key, fn])=>{
carry[key] = ( ...args ) => wrapFn(fn.apply(null, args))
return carry;
},{})


// example of usage

const n = bindFn( { sum: (x) => x+1 }, console.log);
n.sum(3); // this should console.log 4

The issue is, I am unsure how to define the type for bindFn so that it returns the correct type that contains an object with the same keys and return types as the supplied object. Something like:

interface BindFn = {
[name: keyof obj] : () => ReturnType<obj[name]> :D !!! no clue.
}

Answer №1

Give this a shot:

const wrapFunctions = <T extends {[key: string]: Function}>(
  obj: T,
  wrapperFn: Function
) => {
  return Object.entries(obj).reduce((accumulator, [key, fn]) => {
    accumulator[key] = (...args) => wrapperFn(fn.apply(null, args));
    return accumulator;
  }, {}) as T;
};

const n = wrapFunctions({ sum: (x: number) => x + 1 }, console.log);
n.sum(3);
n.sum('3'); // error: type string does not match number
n.foo(2);   // error: 'foo' is not in the structure defined by wrapFunctions
const z = wrapFunctions('foo', console.log); // error: incorrect parameter shape for wrapFunctions

This approach provides valuable type checking as the output type of wrapFunctions() will match the format of its first input. For example, n.sum() will have the type (x: number) => x + 1 because that was the initial value passed to wrapFunctions() (due to the use of return ... as T)

https://i.sstatic.net/1L3yM.png

Furthermore, it enforces that the primary parameter of wrapFunctions() must be an object with keys representing functions (via

T extends {[key: string]: Function}
)

https://i.sstatic.net/nBx8M.png

Answer №2

Do you think this is what you're looking for? I believe this is correct.

const bindFunction = <A extends keyof any, B>(obj: Record<A, B>, wrapperFunction: (func: (arg: B) => B) => any): typeof obj => Object.entries(obj).reduce((accumulator, [key, func])=>{
    accumulator[key] = ( ...args: any[] ) => wrapperFunction(func.apply(null, args))
    return accumulator;
}, {})

const object = { name: () => "my name is", age: () => "my age is" };
const result = bindFunction(object, (argument) => {
    console.log("executed on");
    return argument;
})

Alternatively, here is the version with the executed function:

const bindFunction = <A extends keyof any, B , C>(obj: Record<A, B>, wrapperFunction: (func: (arg: B) => any) => C): Record<A, C> => Object.entries(obj).reduce((accumulator, [key, func])=>{
    accumulator[key] = ( ...args: any[] ) => wrapperFunction(func.apply(null, args))
    return accumulator;
}, {})

const object = { name: () => "my name is", age: () => "my age is" };
const result = bindFunction(object, (argument) => {
    console.log("executed on");
    return 5;
}) // {name: number, age: number}

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

Creating a custom type declaration for .lottie files in Next.js

https://i.sstatic.net/go6pV.png I've successfully integrated the module with no "can't find module" errors, and my code is functioning correctly. However, the main problem lies in the type declarations error, which prevents my code from recogni ...

The module '@ngmodule/material-carousel' could not be located

Having an issue with Angular 8 where I am encountering an error when trying to import the @ngmodule/material-carousel module. The specific error message is: Cannot find module '@ngmodule/material-carousel' Package.json "private": true, "depen ...

Build for Node.js using TypeScript with full functionality

When compiling TypeScript for Node.js using tsc --module commonjs --target ES5 I face limitations with async/await and generators as tsc doesn't know how to handle them in ES5. To address this issue, I can compile TypeScript for Node.js with tsc - ...

Node JS application facing compatibility issues with Typescript not working as intended

I've been diving into Typescript and recently followed a tutorial on how to integrate it with an express api app. However, I encountered the following error: D:\Development\Node\Ed\TypeScript\src\app.ts:5 const app: Appl ...

Using two indexes in ngFor can result in unexpected changes to the values being displayed

I am currently working on printing checkboxes and facing an issue with initializing the id and name attributes using ngFor. The values I'm getting are incorrect. Let's consider 2 arrays (or n arrays retrieved from a database): animal = 'do ...

Choosing the correct key and handling parsing errors

As I work on converting a class component to TypeScript, I encountered an error while trying to implement one of my onChange methods. The error message stated: "Argument of type '{ [x: number]: any; }' is not assignable to parameter of type &ap ...

Tips for incorporating null checks into a function in TypeScript

In my code, I have multiple functions that require a null check on an object before proceeding with certain actions or throwing an error if the object is null. Here is an example of what it looks like: interface SomeObject { doThingOne: () => string ...

Using the spread operator in React to distribute JSX elements within a map function

I am struggling with mapping over an array within another array to create a Picker and am having difficulty returning JSX elements instead of an array of JSX elements. Here is the code example: {modelA.map((mA) => { const pickerItems = mA.modelB.m ...

How can RxJS be used to handle only the first value returned when calling multiple URLs?

I am faced with the challenge of having multiple URLs containing crucial information. My goal is to find a specific ID within these URLs, but I do not know which URL holds the necessary details. The approach I'm taking involves calling each URL and us ...

Display a loading spinner while the search bar makes an API request in Angular

I'm struggling with incorporating a loading spinner display when a user enters a search term in the search bar. When there is a change detected in the search term property, an API request is made to populate the lists in the view with the relevant dat ...

The TypeScript error is causing issues in the Express router file

Here is the structure of my module: import * as express from 'express'; let router = express.Router(); router.post('/foo', function(req,res,next){ // ... }); export = router; However, I'm encountering the following error: ...

Discover the power of Angular2 by utilizing local template variables for efficient element management within a list

Here is a simple code snippet: <ul> <li *ngFor="let item of list"> <div class="button">Click to show text</div> <div class="text">hello</div </li> </ul> The goal is to create and assign a local var ...

What is the method for verifying the types of parameters in a function?

I possess two distinct interfaces interface Vehicle { // data about vehicle } interface Package { // data about package } A component within its props can receive either of them (and potentially more in the future), thus, I formulated a props interface l ...

Issues with the typings for the toPromise function in WebStorm have been identified

I'm encountering an issue with WebStorm not recognizing the typings for the toPromise function on 'rxjs', despite having updated it. Is there a way I can troubleshoot this and fix it? Strangely, the code still runs successfully despite the ...

Display and conceal multiple div elements using Angular 2/Typescript after a brief delay

Currently, I am in the process of generating multiple divs while passing specific data to them. My objective is to hide certain divs based on particular conditions. However, the issue I am facing is that all divs are being hidden regardless of the conditi ...

Looking to retrieve the request body in a route handler in Next.js version 13.2?

I encountered an issue while attempting to send a post request to my API. The problem arises when I try to access the request body within the route handler, resulting in the following error: Code: export async function POST(request: Request) { const ...

Finding the final day of a specific year using the moment library

When it comes to determining the last day of a year, hard-coding the date as December 31st seems like a simple solution. While there are various methods using date, js, and jquery, I am tasked with working on an Angular project which requires me to use mom ...

The ViewChild from NgbModalModule in @ng-bootstrap/ng-bootstrap for Angular 6 is causing the modal to return as

I have successfully integrated ng bootstrap into my project, specifically utilizing the modal module to display a contact form. The form includes input fields for email and message, as well as a submit button. You can find the ngbootstrap module I am using ...

"An auto-invoking function is declared in a TypeScript compiled module with a var statement

Currently, I am in the process of converting an existing AngularJS (1.x) project to TypeScript. The code seems to be functioning properly, but there are some aspects that leave me with questions. In JavaScript, I declare a module like this: (function() { ...

Filtering an array using criteria: A step-by-step guide

Currently, I am developing a system for Role Based permissions that involves working with arrays. Here is an example of the array structure I have: let Roles = { [ { model: 'user', property: 'find', permission: 'allow' ...