Type parameter that allows for the retrieval of a function parameter's type based on specific conditions

There is a custom type I've developed to extract the type of the second parameter in a function:

type SecondParam<T> = T extends (a: any, b: infer R) => any
  ? R
  : never;

For the most part, it functions correctly:

type T1 = SecondParam<(x: any, y: number) => void>; // number
type T2 = SecondParam<(x: any, y: { x: string[] }) => void>; // { x: string[] }

However, when the second parameter is absent, I want it to return void instead of an empty object:

type T3 = SecondParam<(x:any) => any> // currently {}, but I prefer void

I'm utilizing the SecondParam type to specify another function's type:

type F<T> = (p: SecondParam<T>) => void;
type F1 = F<(x: any, y: number) => any>; // (p: number) => void
type F2 = F<(x: any, y: { x: string[] }) => any>; // (p: { x: string[] }) => void
type F3 = F<(x: any) => any>; // currently (p: {}) => void, but I prefer () => void

Unfortunately, it doesn't handle cases where the second parameter is missing as desired.

Answer №1

The condition

(a: any, b: infer R) => any ? .. : ..
will always evaluate to true because omitting parameters does not result in compile errors as shown in this example:

const abc: (one: string, two: string, three: string) => void = (onlyFirst: string) => { };

If you actually want () => void as the type, then you need to introduce a new type condition for the SecondParam type like this:

type SecondParam<T> = T extends (a: any, b: infer R) => any
  ? R
  : never;

type F<T> = T extends (a: any) => any
  ? () => void
  : (p: SecondParam<T>) => void;

type F3 = F<(x: any) => any>; // is () => void

If you require the type never, which cannot be assigned directly, you can modify the SecondParam type like this:

type SecondParam<T> = T extends (a: any) => any
  ? never
  : T extends (a: any, b: infer R) => any
    ? R
    : never;

// Since it expects only one argument due to the never type:
const f: F3 = () => { };
f(); // expects 1 argument

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

Best practices for utilizing forwardRef and next/dynamic in next.js version 13.4 with the "react-email-editor" component

I've been attempting to utilize the "react-email-editor" library in a Next.js project. My goal is to copy the email content generated within the editor to the clipboard. Since the library relies on browser interaction and the use of the "window" objec ...

The process of creating Jasmine tests for an Angular 2 Observable

Currently, I am in the process of testing a component that involves calling a service. My goal is to effectively stub or mock the service in order to control its return value and manipulate the component variables within the callback/success function of ...

Struggling to resize my icon correctly using tailwindCSS and Next.js with TypeScript

I've hit a roadblock with an issue that's been driving me crazy. I attempted to follow a tutorial on tailwindcss with next.js from YouTube. The goal was to utilize the heroicon library to create a stylish header with an icon. However, the icon I& ...

I'm curious about the significance of this in Angular. Can you clarify what type of data this is referring

Can anyone explain the meaning of this specific type declaration? type newtype = (state: EntityState<IEntities>) => IEntities[]; ...

Tips on preventing the need for null or undefined checks in JS/Typescript singletons that have an initialization function

Is there a way to streamline the process of handling props in an Object literal that is dynamically initialized only once? I'm looking for a pattern that would eliminate the need for repetitive null/undefined checks and throw errors when certain metho ...

Guide to creating varying component sizes using ReactJS and Styled Components

Is it possible to add variation to my button based on the prop 'size' being set to either 'small' or 'medium'? interface Props { size?: 'medium' | 'small'; } How can I adjust the size of the component us ...

Please ensure the subscription has completed before proceeding with the loop

I am currently working on an Angular application that retrieves data from an API and uses one of its parameters from a looped array. The issue I'm facing is that the data is pushed in a random order due to the continuous looping without waiting for th ...

The type does not contain a property named 'x' - Error in Promise syntax - TS2339

I encountered a problem while working with Typescript that I couldn't quite figure out. Although I came across similar issues in other topics, I'm still struggling to find a solution for my particular issue. I can easily log userCredential.user.m ...

Using TypeScript in Node.js to iterate through an asynchronous forEach loop

I attempted to integrate a database operation within an async forEach loop with the following code snippet: let successCounter = 0; let failureCounter = 0; let myData = [101, 102, 104, 105]; myData.forEach(async data => { let response = awai ...

Incorporating a Link/Template Column into Your Unique Table Design

I built a table component following the guidelines from this article: Creating an Angular2 Datatable from Scratch. While I have added features like sorting and paging to suit my app's needs, I am struggling with implementing a "Template column" to al ...

Differences between Typescript compilation: Using dot notation vs square brackets when accessing non-existent properties

Imagine having the given class and code snippet: class myClass{ x: number; } const obj = new myClass(); obj.y = 7; // produces a compile error. Property 'y' does not exist on type myClass. obj['y'] = 7; // compiles without any issu ...

Definition of TypeScript array object type

Can you explain the distinction between these two type definitions? type objectArray = [object] type objectArray = object[] ...

Injecting a useFactory provider in Angular is a common practice

I manage a factory provider service that selects a service based on a flag. Everything works fine when I need a debug students service, but when I set the flag to false, the application throws an ERROR TypeError: serverService.fetchData is not a function. ...

How can we efficiently determine the number of B entities related to a specific A entity in TypeORM when they have a one-to-many relationship?

Illustrated in the example below, the BlogPost entity is reliant on the BlogPostCategory: import { Entity, Column, PrimaryGeneratedColumn, ManyToOne as ManyToOne, Relation } from "typeorm"; import { isUndefined } from "@yamato-daiwa/es-exten ...

Utilizing ExpressJS in a NodeJS application with ES6 and Typescript

After confirming my information, I discovered that in an ES6 application, it is necessary to import dependencies using import .. from '..' instead of var .. = require('..'). I made the necessary changes to the imports, but encountered ...

Assigning variables within Redux saga generators/sagas

Consider this scenario: function* mySaga(){ const x = yield call(getX) } The value of const x is not determined directly by the return value of call(getX()). Instead, it depends on what is passed in mySaga.next(whatever) when it is invoked. One might a ...

Tips for iterating through nested objects with a for loop

Struggling with validations in an Angular 5 application? If you have a form with name, email, gender, and address grouped under city, state, country using FormGroupname, you might find this code snippet helpful: export class RegistrationComponent implemen ...

TSX implementation of a paginator with an ellipse in the center

Looking to add ellipses in the Pagination, specifically when there are more than 10 pages (e.g., 1 2 3 4 ... 11 12 13 14). I've tried various methods but need guidance as a beginner. Can anyone suggest changes based on my code to help me achieve this? ...

Sign up for a feature that provides an observable exclusively within an if statement

There is an if clause in my code that checks for the presence of the cordova object in the window global object. If cordova is present, it will make a http request and return the default angular 2 http observable. If the application is in a web context wh ...

Reassigning InputHTMLAttributes in TypeScript

After looking into this issue, I believe I may have a solution. I am exploring the possibility of overriding a React InputHTMLAttribute while using an interface within the context of styled-components. import { InputHTMLAttributes } from 'react' ...