Is there a minimal-impact generic tuple type available for storing [function,...params]?

How can I specify to the type checker that tuples must consist of a function and valid arguments? For example:

let expressions:TYPE[] = [
    [(a:number, b:string)=>{},1,"ok"], // ok
    [(a:number)=>{},true] // error
    [(a:number)=>{}] // error
    [(a:number, b:string)=>{},1] // error
]

The current solution I have feels redundant because it uses a function:

expression<F extends (...args:any[])=>any>(fn:F, ...params:Parameters<F>){
return [fn,...params]
}

let queue:ReturnType<expression>[] = [
    expression(...),
    expression(...),
    expression(...),// seriously?
] 

If only I could do it in one call:

let queue = expressions(
    [(a:number)=>{},1], // ok
    [(a:number)=>{},true] // error
    [(a:number)=>{}] // error
)

But creating that function is beyond my capabilities. It seems to require a generic tuple type that I don't think is possible, leading me to use the expression function in the first place.

Here's an inadequate tuple type that doesn't work and requires extra effort:

type Expression<F extends (...args:any[])=>any = (...args:any[])=>any>  = [F,...Parameters<F>]


let queue:Expression[] = [
    [(a:number)=>{},true] // No error
]

// A cumbersome alternative:

const fn = (a:number)=>{}
queue = [
    [fn,true] as Expression<fn>  // Error as desired, but c'mon.
]

Answer №1

The resolution to this issue presents itself in the following manner:

function expressions<
  F extends any[]
>(...functions: [...{
    [K in keyof F]: [
      (...arg: F[K]) => any, 
      ...F[K]
    ]
  }]
){
  return functions
}

We utilize the generic type F to retain the types of the parameters within the functions passed as arguments in a tuple. The type of each function will be held in F[K], which will also determine the typing for the second element in the tuple.

Lets put it to the test:

let queue = expressions(
    [ (a:number, b: string) => {}, 1, "abc"],
    [ (a:boolean) => {}, true],
    [ (a: Date) => {}, new Date()],
    [ (a: number) => {}, false] // Error: Type 'boolean' is not assignable to type 'number'
)

let queue2 = expressions(  
    [ (a: number) => {} ] // Error: 'unknown' is not assignable to type 'number'
)

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

"Unlock the power of Luxon in your Angular 2 application with these simple

I have been on the search for a great library to integrate with Angular2 for handling dates and performing operations like diff/add, translations, and more. Despite my attempts to install Luxon from http://moment.github.io/luxon/ using npm install --save-d ...

What is the best way to invoke a function that is declared within a React component in a TypeScript class?

export class abc extends React.Component<IProps, IState> { function(name: string) { console.log("I hope to invoke this function"+ name); } render() { return ( <div>Hello</div> ); } } Next, can I cal ...

Loading WebAssembly with react-typescript and Vite.js

Transitioning from webpack and create-react-app to vitejs, encountering an issue with a wasm file. import init from "swaplab2/dist/swaplab2.wasm?init"; import { setSwaplab2 } from "swaplab2"; export function TestPage(): React.ReactElem ...

What are the optimal methods for structuring NPM module exports within a TypeScript library project?

Currently, I am in the process of developing a library package using Typescript that will eventually be published to the npm registry for use by various projects. To ensure that type definitions are also exported along with the code, I have followed the g ...

Utilizing Angular and RxJS: A guide on transforming JSON data into an array of objects within a function that returns an Observable

Sharing my hero.service.ts file that was utilized in a recent project: // hero.service.ts import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { Observable, o ...

Webpack: Creating a shared global variable accessible across non-module scripts

I am facing a challenge with integrating Typescript UMD modules into legacy code that does not follow any module pattern. My hope was to find a Webpack loader or plugin that could generate global variables for specific modules instead of treating them as ...

Displaying data from an Angular subscription in a user interface form

I am attempting to transfer these item details to a form, but I keep encountering undefined values for this.itemDetails.item1Qty, etc. My goal is to display them in the Form UI. this.wareHouseGroup = this.formBuilder.group({ id: this.formBuilder.contr ...

Is there a way to enable live-reload for a local npm package within a monorepo setup?

Currently, I am in the process of setting up a monorepo workspace that will house a Vue 3 application (using vite and TypeScript), cloud functions, and a shared library containing functions and TypeScript interfaces. I have successfully imported my local ...

Applying Type Constraints in Typescript Arrays Based on Other Values

Uncertain about how to phrase this inquiry. I have a specific situation where an object is involved. Key1 represents the name, while key2 stands for options. The type of options is determined by the value of the name. The existing solution works fine than ...

I'm struggling to create a similar query in GraphQL because I can't quite grasp how to execute it

I am currently developing a car rental application as a personal project. Within the /vehicles route, there are lists of available vehicles. I have included 5 select inputs on the left sidebar for filtering purposes. My goal is to apply a filter when a v ...

Tips on transforming current JSON into an alternate JSON format

Using React with TypeScript, I have a JSON data set of employees categorized by their department. Here's a snippet of the JSON data: [ { "department": 1, "name": "Test", "age": 32, "contact": 242222120, "id": 1 }, { "department": 1, "name": "Te ...

What is the best way to loop through pairs of elements in a row using ngFor?

I am facing an issue with populating every two strings from an array in a row using ngFor. This is my current attempt: <div class='row wow fadeInUp' *ngFor='let index of myArray; let i = index;'> <div class='col-md-6 ...

Learn how to efficiently disable or enable a button in Angular depending on the selected radio button

In order to disable the button when the remarks are marked as failed. Here is an example scenario: Imagine there is an array containing two to four items. First example: ITEM 1 -> FAILED -> Remarks (required) ITEM 2 -> FAILED -> Remarks (r ...

What is the trick to accessing an object's key and value when you are unsure of the object's

Currently, I am in the process of constructing a React component that is designed to receive an array of objects. However, I have encountered a question: Is there a way for me to retrieve both the key and value of an object within the map function without ...

How can I define the True function using Typescript?

Currently, I am working on converting Javascript examples to typed Typescript as part of the "Flock of Functions" series. You can find the reference code at https://github.com/glebec/lambda-talk/blob/master/src/index.js#L152. The True function returns the ...

Filtering rows in angular based on the current data's id

currData = { id: "iStyle1", status: "PENDING" }; data = [ { id: "splitStyle1", rows: [ { id: "1cUMlNRSapc5T", row: 2, sequence: 2, status: ...

Typescript Error:TS2345: The argument '{ theme: string; jsonFile: string; output: string; }; }' is not compatible with the parameter type 'Options'

Encountering an error mentioned in the title while using the code snippet below: import * as fs from 'fs' import { mkdirp } from 'mkdirp' import * as report from 'cucumber-html-reporter' const Cucumber = require('cucumber ...

unable to see the new component in the display

Within my app component class, I am attempting to integrate a new component. I have added the selector of this new component to the main class template. `import {CountryCapitalComponent} from "./app.country"; @Component({ selector: 'app-roo ...

Whenever I am building a React application, I encounter a bug that states: "node:fs:1380 const result = binding.mkdir()"

Whenever I try to enter the command: create-react-app my-app --template typescript I keep encountering this error message: node:fs:1380 const result = binding.mkdir( ^ Error: EPERM: operation not permitted, mkdir 'D:\ ...

Loop through the JSON response and calculate the total bill using TypeScript

Having trouble calculating the total sum of bills in an order list using typescript. The error message 'Object is of type 'unknown' keeps popping up when trying to access the total bill field. Interestingly, it works fine in the browser cons ...