generate abstract form from universal process

I have been attempting to declare a generic type based on another generic type but haven't been successful so far.

The main goal is to create my own test framework and define some parameters depending on another parameter (the method).

type Arguments<T> = T extends (...args: infer U) => any ? U : never;

// my custom test method
const methodCall = <T extends (...args: any) => any>(args: {
  method: T;
  response: ReturnType<T>;
  myArguments: Arguments<T>;
}): boolean => {
  const { method, myArguments, response } = args;
  return method.apply(null, myArguments) === response;
};

const test1 = (toto: string) => {
  return toto === "success";
};

// using my custom function
methodCall({
  method: test1,
  myArguments: ["fail"],
  response: false
});


// desired typing for this
interface MyHelpers {
  methodCall: any // HOW TO TYPE THIS? 
  methodCall2: (args: { flag: boolean }) => boolean;
}

// Only exposing the helpers object
const helpers = (): MyHelpers = {
  methodCall: <T extends (...args: any) => any>(args: {
    method: T;
    response: ReturnType<T>;
    myArguments: Arguments<T>;
  }): boolean => {
    const { method, myArguments, response } = args;
    return method.apply(null, myArguments) === response;
  },
  methodCall2: (args: { flag: boolean }): boolean => {
    return args.flag;
  }
};

When calling helpers from another object, I expect to be able to type helpers().methodCall(...) as it is declared in helpers, not with any.

You can access the playground here.

Appreciate your help!

Answer №1

You are very close to the correct understanding. You have the option to choose between function syntax, where you define the signature of methodCall as if it were a function implementation, or property syntax, where you define methodCall as a property that contains a lambda expression, which is similar to your current approach.

In function syntax, you specify the generic within angle brackets (<>), the parameter list in parentheses, and the return type after a colon; this resembles defining a function without an implementation. In property syntax, you create a lambda with the generic inside angle brackets, the parameter list in parentheses, and the return type following a fat arrow (=>); here, you are declaring a property with that name and assigning a type—a function type—after the colon. Either method will be suitable for your needs.

(I also replaced your custom Arguments utility type with the undocumented Parameters built-in.)

interface MyHelpers {
  methodCall<T extends (...args: any) => any>(args: {
    method: T;
    response: ReturnType<T>;
    myArguments: Parameters<T>;
  }): boolean;
  methodCall2: (args: { flag: boolean }) => boolean;
}

interface MyHelpersInObjectForm {
  methodCall: <T extends (...ar

gs: any) => any>(args: {
    method: T;
    response: ReturnType<T>;
    myArguments: Parameters<T>;
  }) => boolean;
  methodCall2: (args: { flag: boolean }) => boolean;
}

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

The Promise type is now incomplete without the property

I'm confident I can resolve this issue on my own, but if sharing my solution can save someone else time, then I want to do so. To address the error, I needed to incorporate the es6-promise library. The problem arose when utilizing Promise.all and en ...

Encountering ng build --prod errors following Angular2 to Angular4 upgrade

Upon completing the upgrade of my Angular2 project to Angular4 by executing the following command: npm install @angular/common@latest @angular/compiler@latest @angular/compiler-cli@latest @angular/core@latest @angular/forms@latest @angular/http@latest @an ...

Error: It appears that the callback with the specified ID for the module <unknown> cannot be found

I decided to create a yarn package that includes common components, services, utils, and more for my project. After creating the package, I added an index.ts file in the src folder to export all components. Once the package was built and added to my projec ...

The inversify middleware is executed a single time

I utilize Inversify for object binding in the following manner: container.applyMiddleware(loggerMiddleware); let module = new ContainerModule((bind: interfaces.Bind) => { bind<Logger>(TYPES.Logger).toConstantValue(logger); bind<ILogger ...

Using getter functions and Visual Studio for TypeScript

In my TypeScript classes in Visual Studio, I have been implementing getter functions. I find that using getter functions helps to clean up my code, although there is one issue that I would like to address. class Foo { doWork(){ console.log(this.bar ...

Transform the process.env into <any> type using TypeScript

Need help with handling logging statements: log.info('docker.r2g run routine is waiting for exit signal from the user. The container id is:', chalk.bold(process.env.r2g_container_id)); log.info('to inspect the container, use:', chalk.b ...

What exactly does the context parameter represent in the createEmbeddedView() method in Angular?

I am curious about the role of the context parameter in the createEmbeddedView() method within Angular. The official Angular documentation does not provide clear information on this aspect. For instance, I came across a piece of code where the developer i ...

The power of RXJS's combineLatest operator

Upon using the combineLatest operator, I encountered an unexpected response when adjusting the interval duration of the first and second observables. Here is an example of the code: let intObs1$ = interval(1000).pipe(take(3)); let intObs2$ = interval( ...

"Prevent further button clicks by disabling it after the initial click with ActionRowBuilder in Discord.Js

Encountering a puzzling issue where I am unable to disable a button after it has been clicked. The option to disable the button does not seem to appear. When attempting to deactivate the button, I utilize the following function: const row = new ActionRowBu ...

Using Firestore and Typescript for Efficient Dynamic Where Conditions

My goal is to incorporate the Repository Pattern using Firestore Firebase and TypeScript. Here is the code snippet: import { firestore } from "firebase-admin"; import { ISearchCriteria } from './ISearchCriteria' export class DBContext { st ...

Improve disorganized subscription processes to enhance future subscriptions

While diving into my Angular learning journey, I stumbled upon Observables which intrigue me but still hold a mystery for me. One specific challenge I faced was having an Observable that depended on another Observable to complete before proceeding. This l ...

Encountering TypeScript error in the beforeRouteUpdate hook with Vue and vue-property-decorator

I am developing an application using Vue 2 with TypeScript and vue-property-decorator. Within my component, I am utilizing the beforeRouteEnter/beforeRouteUpdate hooks. One of the methods in my component is findProjects, which I want to call within the bef ...

Tips for accessing the final iteration in a _.forEach() loop

Recently I started using lodash and encountered a simple challenge while working with it. I'm currently utilizing a _.forEach() loop in typescript to apply a function to objects within an Array. However, I need to determine when the loop reaches its l ...

TypeScript is unable to detect the .sequelizerc configuration file

I have a file called .sequelizerc which contains the following configuration: const path = require('path'); module.exports = { config: path.resolve('.', 'src/config/sequelizeCLIConfig.json'), 'migrations-path': ...

Unsure about module loading with system.js and navigating Typescript

I am currently in the process of transitioning an ASP.Net MVC application to Angular2, and I've encountered some perplexing behavior that I can't seem to grasp. Within my Angular2 app, I have a separate Layoutview that allows me to switch betwee ...

Issue arising from frequent refresh token expiration in Angular 8

Currently, my setup involves AWS Cognito for oauth authentication. Upon login, Cognito returns a token that needs to be refreshed every hour. I implemented logic using setTimeout to handle this token refresh every hour, but this method fails upon page refr ...

There are no imports in index.js and there is no systemjs configuration set up

After creating a fresh Angular project using ng new some-name, I noticed that the generated index.html file does not include any <script> tags and there is no SystemJS configuration either. Is this the expected behavior? I was anticipating the CLI ...

What is the process for extracting the "path expression" from an interface in TypeScript?

My goal is to achieve the following structure: type Post = { id: number title: string author: { name: string } comments: { text: string }[] } type ExtractPathExpressions<T> = ??? type Paths = ExtractPathExpressions<Post> / ...

After updating the file path, the Next.Js module couldn't be located: Module not found – Unable to

After relocating the EmptyTable.tsx file from its original directory at views/forms-tables/tables/react-table/EmptyTable to a new location at components/Tables/EmptyTable, I encountered a persistent issue. Despite updating the import path in my code to mat ...

A critical error has arisen: UNSUPPORTED: the use of "id" as a keyword, please utilize "$id" for schema identification in Angular 14

Recently, I upgraded from Angular 9 to version 14 but encountered an issue while running CLI commands like ng g c component name. The error message I received is as follows: An unhandled exception occurred: NOT SUPPORTED: keyword "id", use " ...