Determine the data type based on the object property

Can a versatile function be created to automatically determine the type based on an "external" object property?

Consider the following scenario:

const resolversMap: {
  overallRankingPlacement: (issuer: number, args: Record<string, any>, context: Record<string, any>) => Promise<number>;
} = {
  overallRankingPlacement: createResolver((issuer, args, context) => {
    return 0;
  }),
};

function createResolver<T extends () => void>(resolverFn: T): ReturnType<T> {
  return (...args) => {
    // Some additional logic...
    resolverFn(...args);
  };
}

The objective is for the function generated by createResolver to perfectly match the return of "overallRankingPlacement", with arguments mirroring and proxying the same—ensuring consistent types throughout.

Answer №1

To achieve this functionality, you can utilize generic parameters for both the argument-array and the result type. By implementing something similar to the code snippet below:

function createResolver<Args extends unknown[], Res>(
  resolverFn: (...args: Args) => Res
): (...args: Args) => Res {
  return (...args: Args) => {
    // Additional logic can be added here...
    return resolverFn(...args);
  };
}

However, keep in mind that the example with the resolversMap may not work as expected because the overallRankingPlacement function returns a promise while the argument of createResolver does not. To resolve this issue, you can either remove Promise from the return type or pass an asynchronous function to createResolver for aligning the types correctly.

If your goal is to have a version of createResolver that returns an async function, you can modify the function as follows:

function createAsyncResolver<Args extends unknown[], Res>(
  resolverFn: (...args: Args) => Res
): (...args: Args) => Promise<Res> {
  return async (...args: Args) => {
    // Additional async logic can be included here...
    return resolverFn(...args);
  };
}

This updated version will operate seamlessly with your provided resolversMap.

It's important to note that wrapping functions in this manner might not handle overloaded functions effectively. The wrapped function may retain only the last overload, resulting in situations like:

const unfortunatelyNotOverloaded = createResolver(overloaded)
const ok = unfortunatelyNotOverloaded('ok') // inferred type: string
const fail = unfortunatelyNotOverloaded(1)
// ERROR: Argument of type 'number' is not assignable to parameter of type 'string'.

At present, there doesn't seem to be a workaround for this limitation, and it might not be supported in the future.

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

Angular Error: The first argument has a property that contains NaN

Struggling with a calculation formula to find the percentage using Angular and Typescript with Angularfire for database storage. Encountered an error stating First argument contains NaN in property 'percent.percentKey.percentMale. The properties are d ...

What is the best way to apply multiple array filters to an object list in react.js?

Looking to filter an array of items using multiple filter arrays in order to display only the items that match all selected filters. For example: The main array contains a table with the following data: ID TypeID LocationID Name 1 2 ...

Type of result from a function that returns a linked promise

In my class, I have a method that returns a chained promise. The first promise's type is angular.IPromise<Foo>, and the second promise resolves with type angular.IPromise<Bar>. I am perplexed as to why the return type of doSomething is an ...

Implementing Immer in Typescript

Recently, I've been exploring the possibility of integrating Immer into my React project that already utilizes Typescript. Unfortunately, I haven't been able to discover a clear guide on how to effectively employ Immer in conjunction with Typescr ...

Strategies for resolving a mix of different data types within a single parameter

Here, I am setting up the options params to accept a value that can either be a single string or another object like options?: string[] | IServiceDetail[] | IServiceAccordion[]; However, when attempting to map these objects, an error is encountered: Prope ...

Angular 2: Harnessing the power of Observables with multiple Events or Event Handlers

In the component template, I have grouped multiple Inputs and their events like this: <tr (input)="onSearchObjectChange($event)"> <th><input [(ngModel)]="searchObject.prop1"></th> <th><input [(ngModel)]="searchObje ...

Angular is showing an error indicating that the property "name" is not found on an empty object

After thorough checking, I have confirmed that the property does exist with the correct key. However, it is returning an error message stating name is not a property of {}. I attempted to assign this object to an interface along with its properties but enc ...

Only one argument is accepted by the constructor of NGRX data EntityServicesBase

In an attempt to enhance the convenience of my application class, I decided to create a Sub-class EntityServices based on the NGRX/data documentation which can be found here. Despite following the provided example, it appears that it does not function pro ...

Every instance of 'WeakMap' must include the same type parameters

While developing an Ionic App, I encountered a strange issue. Everything was running smoothly until I cloned the source code to a different machine, which resulted in an error that is displayed in the attached image. Even though there are no compilation e ...

How can I access a file uploaded using dxFileUploader?

I am facing an issue with retrieving a file from dxFileUploader (DevExpress) and not being able to read it in the code behind. The file is only appearing as an object. Here is My FileUploader : { location: "before", ...

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" ...

What could be causing the issue of CSS Styles not being applied to an Angular 2 component with Vaadin elements?

Currently, I am immersed in the tutorial on Vaadin elements using Angular 2 that I stumbled upon here In section 5.3, Styles are applied to the app.component.ts as shown below import { Component } from [email protected]/core'; @Component({ select ...

Do constructors in TypeScript automatically replace the value of `this` with the object returned when using `super(...)`?

I’m having some trouble grasping a concept from the documentation: According to ES2015, constructors that return an object will automatically replace the value of “this” for any instances where “super(…)” is called. The constructor code must ...

Implementing a video pause event trigger from a function in Angular2

Here is the content of my player.component.html: <video width="320" height="240" autoplay autobuffer [src]="videoSrc" (ended)="videoEnd()"> Your browser does not support the video tag. </video> <button (click)="pauseOrPlay()">pause/play ...

"Benefit from precise TypeScript error messages for maintaining a streamlined and organized architecture in your

As I dip my toes into the world of functional programming with typescript for a new project, I am encountering some challenges. In the provided code snippet, which follows a clean architecture model, TypeScript errors are popping up, but pinpointing their ...

Leveraging Window Object in Custom Hooks with NextJS

ReferenceError: window is not defined This issue arises on the server side when NextJS attempts to render the page. However, it is possible to utilize window within the useEffect hook by following the guidance provided here. I am seeking advice on creati ...

A method to simultaneously retrieve all emitted values from multiple EventEmitters in Angular 7

I am facing a scenario where I have a parent component that consists of multiple child components. Each child component may differ from the others, creating a diverse structure within the parent component. Here's an example: ...

How to transfer the label text value from html to .ts file in Ionic 3?

Hey everyone! I just started using Ionic and I'm wondering how to pass the value of a label text from HTML to the .ts file. Here's a snippet of my code: <div class="box" (click)="openChatBot()"></div> <ion-label>LEADER ...

Example TypeScript code: Use the following function in Angular 5 to calculate the total by summing up the subtotals. This function multiplies the price by the quantity

I have a table shown in the image. I am looking to create a function that calculates price* quantity = subtotal for each row, and then sum up all the subtotals to get the total amount with Total=Sum(Subtotal). https://i.stack.imgur.com/4JjfL.png This is ...

What is the best way to implement an interface for accurately checking each prop type?

Currently, while working with Typescript, I am looking for a solution to define an interface with specific properties inside my object of marks. At the moment, I am using "any", but I know there must be a better approach. Any guidance or advice on how to p ...