how to use all parameters except the first one in TypeScript

Is there a way to reference one function's parameter types in another function, but only use a subset of them without repeating the entire list of parameters?

//params of bar should be same as foo, except p1 should be a different type

function foo(p1: string, p2: number, p3: boolean){
 ...
}

//i'd like to do something like this, though it's obviously not valid syntax
function bar(p1: string[], ...rest: Parameters<typeof foo>.slice(1)){
}

In my actual code, I have more than just 3 parameters and manually specifying them is not ideal. Any suggestions on how to achieve this efficiently?

Answer №1

Exploring TypeScript 4.0 Features

Option 1: Simplified Variadic Tuple Syntax

type DropFirst<T extends unknown[]> = T extends [any, ...infer U] ? U : never

function bar(p1: string[], ...rest: DropFirst<Parameters<typeof foo>>) { }
// bar: (p1: string[], p2: number, p3: boolean) => void

A new syntax for inferring tuple elements except the first one has been introduced in TypeScript 4.0. Check out Robby Cornelissen's solution for versions prior to 4.0.

Option 2: Named Tuple Elements

type CommonParams = [p2: number, p3: boolean];

function foo2(p1: string, ...rest: CommonParams){} 
// foo2: (p1: string, p2: number, p3: boolean) => void
function bar2(p1: string[], ...rest: CommonParams) { }
// bar2: (p1: string[], p2: number, p3: boolean) => void

Using named tuples can help retain function parameter names, avoiding data loss during conversions.

Try it Out on TypeScript Playground

Answer №2

If you want to create a new type tuple in TypeScript, you can utilize the utility type called Parameters. From there, you can derive a new type by excluding the initial type:

type NewType<T extends any[]> = 
  ((...input: T) => void) extends ((first: infer First, ...rest: infer Rest) => void) ? Rest : never;

function myFunction(firstArg: string, secondArg: number, thirdArg: boolean) {
}

function finalFunction(firstArg: string[], ...restArgs: NewType<Parameters<typeof myFunction>>) {
}


finalFunction([''], 0, true); // works fine
finalFunction('', 0, true); // shows error
finalFunction([''], true, 0); // also displays an error

To learn more about this concept, refer to this insightful answer.

Answer №3

Utilizing destructured object parameters can streamline your code. When passing an object into a function, you have the flexibility to specify which fields from that object will be used.

You have the option to define the parameter interface type separately (as shown with example below), or you can define it directly within the function call (like in sample below).

This allows both functions to extract only the necessary information from the object containing all the parameters.

type ExampleParameters = { key1: string, key2: number, key3: boolean }
function example({ key1, key2, key3 }: ExampleParameters) {
  console.log("Extracted keys from example:", key1, key2, key3)
}

//Hypothetical scenario utilizing inline definition
function sample({ key1 }: { key1: string }) {
  console.log("Selected key from sample:", key1)
}

const data = { key1: "Value One", key2: 5, key3: true }

example(data)
sample(data)

Answer №4

One approach that could simplify the code is by introducing a shared rest parameter type:

type SharedParams = [number, boolean];

// Define function foo with parameters p1 and a destructured array of shared params

function foo(p1: string, [p2, p3]: SharedParams){
    ...
}

// Attempting to create function bar with an array for p1 and rest parameter using SharedParams

function bar(p1: string[], ...rest: SharedParams){
    ...
}

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

Implement conditional props for a React component by linking them to existing props

In my current project, I am working on a component that has a loading state. The component has an isLoading prop which determines whether the component is currently in a loading state or not: interface CustomImageComponentProps { isLoading: boolean ...

"Exploring Angular 9: A guide to retrieving form data with an array of objects [Revised as of July 29th, 2020

I am encountering an issue with my Angular 9 form code. I am getting the error "ERROR TypeError: Cannot read property 'mobile_number' of undefined" and I need help in resolving this problem. <form (ngSubmit)="processForm()"> & ...

Ensuring the presence of TypeScript variables

Take a look at this code snippet: let str: string | null; function print(msg: string) { console.log(msg); } print(str); When running this code, the typescript compiler correctly identifies the error, stating that Argument of type 'string | nu ...

The server has access to an environment variable that is not available on the client, despite being properly prefixed

In my project, I have a file named .env.local that contains three variables: NEXT_PUBLIC_MAGIC_PUBLISHABLE_KEY=pk_test_<get-your-own> MAGIC_SECRET_KEY=sk_test_<get-your-own> TOKEN_SECRET=some-secret These variables are printed out in the file ...

Modify a single parameter of an element in a Map

Imagine I have a map data type exampleMap: Map<string, any> The key in the map is always a string, and the corresponding value is an object. This object might look like this: { name: 'sampleName', age: 30} Now, let's say the user se ...

Utilizing Typescript and sinon to mock the functionalities of jsonwebtoken

Looking for help with mocking the function verify in Typescript's jsonwebtoken library. I've installed typescript, jsonwebtoken, sinon, mocha, and chai along with their corresponding types. However, when trying to stub the function, an error occu ...

Module error caused by Typescript path inconsistency

After creating a new model named "project" within the existing project, I encountered an error when attempting to import the class into another typescript file in VS2019. The specific error message thrown is as follows: "ts2307 cannot find module ' ...

Angular v15 Footer Component Table

In my Angular 15 project, I am attempting to correctly position and utilize the mat table with the following code snippet: <tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>. While the displayedColumns property is functionin ...

Generate a Jest dummy for testing an IncomingMessage object

I am facing a challenge in writing a unit test for a function that requires an IncomingMessage as one of its parameters. I understand that it is a stream, but I am struggling to create a basic test dummy because the stream causes my tests to timeout. : T ...

Include type declarations for property values that resemble arrays in a generic object

Imagine you have a function that: receives an object with multiple properties and a property name; checks if the property holds an array; if it does, performs an action (such as printing the values it contains) Here's an illustration: function pro ...

typescript: best practices for typing key and value parameters in the forEach loop of Object.entries()

I have a specific object with key/value pairs that I need to iterate over using the entries() method of Object followed by a forEach() method of Array. However, I'm struggling to understand how to avoid a typescript error in this situation: type objTy ...

Angular - passing information to a nested component

Within my application, I have a main component along with three sub-components. I am passing data to these three sub-components and using setTimeout to manage the timing of the data being sent. The first sub-component displays for 5000 milliseconds. The ...

TS2304 TypeScript (TS) Unable to locate the specified name

Encountering an error message stating Cannot find name 'Record'. Do I need to install a specific package for this class? Severity Code Description File Project Line Suppression State Error TS2304 (TS) Cannot find name 'Record ...

Is it feasible to evaluate a Typescript method parameter decorator at request time in a nodejs+nestjs environment rather than just at build time?

Looking to simplify my handling of mongodb calls with and without transactions in a single service method by writing a decorator. This would help eliminate the repetition of code and make things more efficient. Key points for usage: • Service class has ...

What is the best way to test for errors thrown by async functions using chai or chai-as-promised?

Below is the function in question: async foo() : Promise<Object> { if(...) throw new Error } I'm wondering how I should go about testing whether the error is thrown. This is my current approach: it("checking for thrown error", asy ...

Setting up Next Js to display images from external domains

Encountering an issue with my next.config.js file while working on a project with Next.js in TypeScript. This project involves using ThreeJs, @react-three/fiber, and @react-three/drei libraries. Additionally, I need to include images from a specific public ...

Exploring generic types using recursive inference

The scenario: export type SchemaOne<T> = | Entity<T> | SchemaObjectOne<T>; export interface SchemaObjectOne<T> { [key: string]: SchemaOne<T>; } export type SchemaOf<T> = T extends SchemaOne<infer R> ? R : nev ...

Ways to align the label at the center of an MUI Textfield

My goal is to center the label and helper text in the middle of the Textfield. I managed to achieve this by adding padding to MuiInputLabel-root, but it's not responsive on different screen sizes (the Textfield changes size and the label loses its cen ...

What is the best way to transform the request query id = ' [12eetftt76237,jhgasduyas7657] ' into an array of elements or strings like [12eetftt76237,jhgasduyas7657]?

Hey there, I am working on a project using hapijs and typescript. I have a requirement to send an array of IDs as parameters through the request URL. Here is an example of the URL: localhost:3444/?id='[askjajk78686,ajshd67868]' I attempted to u ...

Creating a dynamic selection in Angular without duplicate values

How can I prevent repetition of values when creating a dynamic select based on an object fetched from a database? Below is the HTML code: <router-outlet></router-outlet> <hr> <div class="row"> <div class="col-xs-12"> & ...