Working with an arbitrary number of arguments in TypeScript

Looking for a way to pass an arbitrary number of arguments with different types into a function and utilize those types, similar to the following:

function f<A>(a: A): A;
function f<A, B>(a: A, b: B): A & B;
function f<A, B, C>(a: A, b: B, c: C): A & B & C;
function f<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;

function f(...args: any[]) {
    return Object.assign({}, ...args);
}

var smth = f({ x: 1 }, { y: 2 }, { z: 3 });
var res = smth.x + smth.y + smth.z;

To avoid repeating these declarations due to needing an arbitrary number of parameters, I aim to consolidate them into a single declaration like:

function f<...T>(args: [...T]): &<...T>;

However, this syntax is incorrect. Is there a proper way to rewrite this structure?

PS: The same question in Russian.

Answer №1

Revision for Version 3.0

Although the initial answer was accurate, there have been changes in TypeScript since then. In typescript 3.0, it is now possible to utilize tuples in rest parameters to capture the type of arguments within a tuple.

type UnionToIntersection<U> =
    (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

function f<A extends any[]>(...args: A): UnionToIntersection<A[number]> { return null! }
var smth = f({ x: 1 }, new A(), new B());  // will be of type  A & B & { x: number; }

Initial Response

While Proposal: Variadic Kinds could potentially aid in this situation as suggested by others, there are workarounds available for your specific scenario.

If we define the function signature with a single type argument, we can achieve a union type of the arguments:

function f<A>(...args: A[]): A {}
var smth = f({ x: 1 }, { y: 2 }, { z: 3 });
typeof smth = {
    x: number;
    y?: undefined;
    z?: undefined;
} | {
    y: number;
    x?: undefined;
    z?: undefined;
} | {
    z: number;
    x?: undefined;
    y?: undefined;
}

An issue arises when using a class instead of an object literal as the compiler fails to infer the union and generates an error. By omitting the rest parameter (...) and simply utilizing an array, the compiler deduces a union of the parameter type:

function f<A>(args: A[]): A { /*…*/}
var smth = f([{ x: 1 }, new A(), new B()]); 
typeof smth == A | B | {
    x: number;
}

To convert the union into an intersection, conditional types can be employed (refer to this for additional information)

type UnionToIntersection<U> = 
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

function f<A>(args: A[]): UnionToIntersection<A> {
    return Object.assign({}, ...args);
}

class A { z: number }
class B { y: number }

var smth = f([{ x: 1 }, new A(), new B()]); // will result in type  A & B & { x: number; }
var res = smth.x + smth.y + smth.z;

We trust that this has provided a helpful workaround until the inclusion of variadic kinds.

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

encountering a problem integrating react-dropzone into a project using react-16.13.1

I'm having an issue adding the package https://www.npmjs.com/package/react-dropzone to my TypeScript React project using Yarn as the package manager. I ran the command yarn add @types/react-dropzone, but it ended up installing a deprecated package h ...

Creating Angular UI states with parameters in TypeScript

My Understanding In my experience with TypeScript and angular's ui state, I have utilized "type assertion" through the UI-Router definitely typed library. By injecting $state into my code as shown below: function myCtrl($state: ng.ui.IStateService){ ...

Issue encountered while conducting tests with Jest and React Testing Library on a React component containing an SVG: the type is not recognized in React.jsx

In my Next.js 12.1.4 project, I am using Typescript, React Testing Library, and SVGR for importing icons like this: import ChevronLeftIcon from './chevron-left.svg' The issue arises when running a test on a component that includes an SVG import, ...

Basic exam but located in a place that is not valid

Here is a test I am working on: // import {by, element, browser} from "protractor"; describe('intro', () => { beforeEach(() => { browser.get(''); }); it('should have multiple pages', () => { let buttonOn ...

What is the method for obtaining a literal type through a function parameter to use as a computed property name?

Can you help me with this code snippet? const fn = (name: string) => { return { [name]: "some txt" }; }; const res = fn("books"); // books or any other string The type of res recognized by TS is: const res: { [x: string]: string ...

Using Typescript for AngularJS bindings with ng.IComponentController

Currently, I am utilizing webpack alongside Babel and Typescript Presently, the controller in question is as follows: // HelloWorldController.ts class HelloWorldController implements ng.IComponentController { constructor(private $scope: ng.IScope) { } ...

Showing canvas lines while dragging (using only plain JavaScript, with React.JS if needed)

Is there a way to add lines with two clicks and have them visible while moving the mouse? The line should only be drawn when clicking the left mouse button. Any suggestions on how I can modify my code to achieve this functionality? Currently, the lines are ...

Angular2 - how can I effectively organize the logic between my components and services?

Within my current project setup, I have the following structure implemented: I have a Component that interacts with a Service Class which in turn calls an external API. The specific logic that I need to implement is related solely to the user interface. ...

Modify every audio mixer for Windows

Currently working on developing software for Windows using typescript. Looking to modify the audio being played on Windows by utilizing the mixer for individual applications similar to the built-in Windows audio mixer. Came across a plugin called win-audi ...

Master the Art of Scrolling Lists in Ionic 2

I am currently using Ionic2 for my project. One of the challenges I'm facing is scrolling to the top of a list when a specific event, called messageSend, occurs. Let me show you the code for this: <ion-content padding class="messages-page-conten ...

The negation operator in Typescript is failing to negate as expected

When a user changes a multiselect element, there is a function that runs to control the visibility of an error message: getVisibility(multiselect) { if ((multiselect.selectedCategories.length < 1 && !multiselect.allSelected) && th ...

Utilizing Angular's async pipe to dynamically customize and assign values to variables

I have a parent component named A with over 20 child components, all of which extend A and are located within <ng-content></ng-content>. Within component A, I am updating the value of the showContent variable in multiple places. The issue aris ...

Angular 8 allows for the creation of custom checkboxes with unique content contained within the checkbox itself, enabling multiple selection

I'm in need of a custom checkbox with content inside that allows for multiple selections, similar to the example below: https://i.sstatic.net/CbNXv.png <div class="row"> <div class="form-group"> <input type ...

Using Angular Form Builder to assign a value depending on the selected option in a dropdown menu

My approach to Angular Form Builder initialization includes a group that looks like this: contactReason: this.formBuilder.group({ description: '', source: this.sourceType() }) For the 'description' field, I hav ...

Cross-origin resource sharing (CORS) seems to be creating a barrier for the communication between my Angular

During the process of developing an Angular and NestJS app with NGXS for state management, I encountered a CORS error while serving my application. The error message in the console indicated: Access to XMLHttpRequest at 'localhost:333/api/product-i ...

When utilizing create-next-app, an error may occur stating that the produced JSX.Element cannot be assigned to a variable

After creating a new project with TypeScript using create-next-app, I encountered an error in the default homepage when opened in my IDE (WebStorm). The error message reads: "Initializer type () => JSX.Element is not assignable to variable type NextPa ...

ERROR: Unhandled promise rejection: Route cannot be found. URL Segment: 'details'

My current setup involves a router configuration in my Angular application. Below is the code snippet showcasing my router settings: import { Route, RouterModule } from '@angular/router'; import { ProjectDetailsComponent } from '../componen ...

Encountering difficulty when trying to define the onComplete function in Conf.ts. A type error is occurring, stating that '(passed: any) => void' is not compatible with type '() => void'.ts(2322)'

I have been developing a custom Protractor - browserstack framework from the ground up. While implementing the onComplete function as outlined on the official site in conf.ts - // Code snippet to update test status on BrowserStack based on test assertion ...

Looping issue with ForEach in Typscript with Firebase Functions

While browsing through various questions on this topic, I've noticed that the specific answers provided don't quite fit my situation. My query involves converting a Google Firebase RTB datasnapshot into an array of custom objects, each representi ...

Resolving TypeScript error when importing images statically in Next.js

In order to enhance the performance of images in my nextjs app, I am working on image optimization. However, I encountered an issue stating: Cannot find module '/images/homeBg.jpg' or its corresponding type declarations. The image is actually st ...