Deriving variable function parameters as object or tuple type in TypeScript

Searching for a similar type structure:

type ArgsType<F extends Function> = ...

which translates to

ArgsType<(n: number, s: string)=>void>

will result in

[number, string]

or

{n: number, s: string}

Following one of the provided solutions, created these types:

type ArgsType<F extends (...x: any[]) => any>
    = F extends (...x: infer A) => any ? A : never;

type CtorArgsType<F extends new (...x: any[]) => any>
    = F extends new (...x: infer A) => any ? A : never;


interface RepoGroup {
    resetAsync?: () => Promise<void>
}

interface RepoGroupOptions<Reset extends "CanReset" | "CannotReset"="CannotReset"> {
    reset: Reset extends "CanReset" ? () => Promise<void> : undefined
}

type RepoGroupCtor<Reset extends "CanReset" | "CannotReset"="CannotReset">
    = new (...args: any[]) => RepoGroupOptions<Reset>


export function generate<
    CanReset extends "CanReset" | "CannotReset"="CannotReset",
    T extends RepoGroupCtor<CanReset>=RepoGroupCtor<CanReset>
    >(args: T) {
    return class implements RepoGroup {
        private args: InstanceType<T>
        constructor(...config: CtorArgsType<T>) {
            this.args = new args(config) as any
        }

        resetAsync = this.args.reset
    }
}


export const Repo = generate(class {
    readonly baseUrl: string
    constructor(args: { apiBaseUrl: string }) {
        this.baseUrl = args.apiBaseUrl
    }

    reset: undefined
})

let repository = new Repo()

Encountering an error on the last line, as expected. However, by adding a generic parameter to repo like so:

export const Repo = generate<"CannotReset">(class {...

the error vanishes, which appears to be a bug in the code

Answer №1

interface ExtractParams<T extends (...args: any[]) => any> {
  type Params = T extends (...args: infer P) => any ? P : never;
}

This code snippet is part of a proposal to add it to the standard library, as seen here.

Second Round

When specifying at least one type argument for the function generate, the inference for other type arguments is disabled and defaults are used (such as

T = RepoGroupCtor<CanReset>
). Since RepoGroupCtor<CanReset> allows a rest parameter of type any[], no error occurs in this scenario. For situations where you want to avoid this behavior, you can refer to the discussion on Partial type argument inference.

Answer №2

If you need to utilize Parameters<T>, you can do so. This feature has been available since at least version 3.2.

Here is how you can use it:


function printMessage(msg: string) { console.log(msg)}
type MsgType = Parameters<typeof printMessage>[0]; // string

interface MessageLogger {
    log(message: string): void;
}
type MsgType2 = Parameters<MessageLogger['log']>[0]; // string

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

Uniting the client-side jQuery and server-side Express for enhanced functionality

Currently, I am deepening my understanding of Express/Node. My goal is to construct a basic HTML form that undergoes client-side validation (using jQuery/AJAX) while also being processed server-side (via Express.js). The application's complexity remai ...

How to generate an array within a TypeScript extension function

As I was working on creating an extension method using typeScript, the main goal was to establish a static or normal variable within the method. The ServiceCollector method was invoked three times in order to send and store data or objects in an array. B ...

Discover the Prisma findMany method for implementing tanstack react table functionality

I'm looking to build a table (using tanstack table) populated with data fetched from Prisma.findMany. Let's suppose I have a User model: model User { id Int @id @default(autoincrement()) name String age String email String } Now, in my p ...

Having trouble converting a timestamp to a date in JavaScript

My database uses MongoDB and has a timestamp field with unique formats, such as: 1657479170.7300725 1657479170.7301126 1657479170.7301197 1657479170.9120467 1657479170.932398 Converting these timestamps to the date format YYYY-MM-DD yields the correct res ...

Is there a way to match a compressed javascript stack trace with a source map to pinpoint the correct error message?

When managing our production server, I have implemented minified javascript without including a map file to prevent users from easily deciphering errors. To handle angular exceptions caught by $exceptionHandler, I developed a logging service that forwards ...

Error: Django unable to load jQuery library

Hey there! I have a template that includes my JavaScript code. However, when I view the template in a browser, it doesn't provide the interaction I was hoping for. Upon checking the console, I see the following error messages: Error: Bootstrap's ...

Tips on utilizing Ajax for updating the RenderBody() segment

Can anyone help me understand why my Ajax.ActionLink menu item is calling JavaScript twice when I try to use it for the second time? I simply want to update the RenderBody() after clicking on a menu item. _Layout.cshtml: ... <body> <div i ...

Creating a Text Typer ReactJS component that functions properly regardless of whether or not it is used within StrictMode is no

My goal is to develop a custom Text Typer component that displays text character by character every 100ms. While it works perfectly fine in production, I encounter issues when testing it in the development environment. Despite trying various solutions, tw ...

AngularJS constants are values that can be accessed and

Is it feasible to inject one constant into another constant using AngularJS? For example: var app = angular.module('myApp'); app.constant('foo', { message: "Hello" } ); app.constant('bar', ['foo', function(foo) ...

Navigating to my own posts within Nuxt: A guide

Having trouble with internal links in my template, as they are not directing to the correct URLs. <nuxt-link :to="blog.url" >{{ blog.title }} by {{ blog.author }}</nuxt-link > In my data, I have the foll ...

Mastering the management of various events within React Material UI components

I am working with a Material UI Switch Component and need to detect click events on it. In certain situations, I want to prevent the change event from triggering. What is the most effective way to achieve this? While I have previously used event.preventD ...

Comparing form submission with a button click to pass data using Ajax - success in one method but failure in the other

I am facing an issue with two pieces of jquery code in my Flask application. While one works perfectly, the other is not functioning as expected. Both the form and a button trigger the same function through ajax calls. Currently, for troubleshooting purpos ...

Tips for retrieving the values of both a checkbox and radio button in AngularJS

Hello, I have created MY PLUNKER I have a condition in my JSON where if the minimum value of the ingredients is equal to one, it will change to a radio button. If it's greater than one, it will change to a checkbox. To display as a radio button: ng ...

Displaying Photo on Webpage using Bearer Authorization Token in JavaScript

In my JavaScript code, I am currently loading an image using the following method: var img = new Image(); img.onload = function () { .. }; img.src = src; However, I have recently realized that I need to secure the images on my server side with OAuth 2, j ...

Obtain the AJAX response in separate div elements depending on whether it is successful or an error

Currently, my jQuery script outputs the result in the same div for error or success messages: HTML <div id="error-message").html(res); JQUERY jQuery('#register-me').on('click',function(){ $("#myform").hide(); jQuery ...

Submit user-specific form data in Angular 5 based on user selection

Utilizing a common reactive form to handle various types of user data, such as teachers, students, guards, etc. The form is selected from a dropdown list. The goal is to send specific data objects based on the selected user type. A model named "User" has ...

JQUERY confirm dialog causing AJAX malfunction

I am encountering an issue where I am trying to execute an ajax function only after the user confirms a dialogue using JQUERY confirm. Strangely, when I include the confirmation step, my code throws an error and does not function properly. It's worth ...

NGRX reducer avoids generating errors due to incorrect assignments

My experience with ngrx is relatively new. In my typical TypeScript work, I usually encounter an incorrect assignment error like the one below due to a missing property in the interface declaration: interface IExample { count: number; } let initialState ...

What is the most effective method in Vue.js for transitioning elements without the need to use v-for and v-if at the

Utilizing v-for to generate multiple <p> elements, each one animating in within a Vue <transition> component if the v-if condition is met. Below is the code snippet: <transition name="fade"> <p v-for="(quote, idx) in game.quot ...