Obtain the parameters of a function within another function that includes a dynamic generic

I am attempting to extract a specific parameter from the second parameter of a function, which is an object. From this object, I want to access the "onSuccess" function (which is optional but needed when requested), and then retrieve the first dynamic parameter of that function.

Although

Parameters<NonNullable<Parameters<typeof sampleFunction>[1]["onSuccess"]>>[0]
does work, I prefer not to use it everywhere as it can be quite difficult to read. I would like to create a more dynamic approach like:
ResponseOf<typeof sampleFunction>

TS playground link

interface ApiCallback<T = any> {
  onSuccess?: (response: T, headers?: any) => void;
  onFailure?: (error: unknown) => void;
  label: string;
  // ...other
}

interface ApiActionPayload<T = any> extends ApiCallback<T> {
  url: string;
  // ... other
}

interface ApiAction<T = any> {
  type: "API";
  payload: ApiActionPayload<T>;
}

function apiAction<T = any>({
  url = "",
  label = "",
  ...props
}: ApiActionPayload<T>): ApiAction<T> {
  return {
    type: "API",
    payload: {
      url,
      label,
      ...props
    }
  }
}

const sampleFunction = (_param1: any, callbacks: ApiCallback<{ data: any[] }>): ApiAction => {
  return apiAction({
    url: "google.com",
    ...callbacks
  })
}

type DesiredNonDynamicType = Parameters<NonNullable<Parameters<typeof sampleFunction>[1]["onSuccess"]>>[0];


export type ResponseOf<
  T extends (
    first: any,
    second: { onSuccess?: (x: any) => any; label: string;[k: string]: any },
    ...args: any[]
  ) => any> = T extends (first: any, second: { onSuccess?: (x: infer U) => any;[k: string]: any }, ...args: any[]) => any
  ? U : never;


type DesiredType = ResponseOf<typeof sampleFunction>;

One solution I have experimented with is:

export type ResponseOf<
  T extends (
    first: any,
    second: { onSuccess?: (x: any) => any; label: string; [k: string]: any },
    ...args: any[]
  ) => any
= T extends (first: any, second: { onSuccess?: (x: infer U) => any; [k: string]: any }, ...args: any[]) => any
  ? U
  : never;

Answer №1

To simplify this process, you can utilize the ApiCallback utility type within your conditional type inference. Instead of attempting to reverse-engineer, using ApiCallback<infer U> directly is much more efficient. Here's an example:

export type ResponseOf<T> =
  T extends (first: any, second: ApiCallback<infer U>, ...args: any) => any ? U : never

This approach will give you the desired behavior:

type DesiredType = ResponseOf<typeof sampleFunction>;
/* type DesiredType = {
    data: any[];
} */

Access the Playground link to view the code.

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

Inferencing partial types in Typescript

I'm completely stuck on this and can't seem to figure it out without using a second function: interface Fixed { a: number } const fn = <A, B extends {} = {}>(b: B) => { return b } fn({ a: 1 }) // { a: number } fn<Fixed>({ a: 1 } ...

How to extract key-value pairs from an object in a TypeScript API request

I am trying to extract the data '"Cursed Body": "100.000%"' from this API response using TypeScript in order to display it on an HTML page. Can anyone help me figure out how to do this? API Response { "tier": &q ...

Determine data types for functions in individual files when using ElysiaJS

Currently, I am utilizing ElysiaJS to establish an API. The code can be found in the following open-source repository here. In my setup, there are three essential files: auth.routes.ts, auth.handlers.ts, and auth.dto.ts. The routes file contains the path, ...

Waiting for Angular's For loop to complete

Recently, I encountered a situation where I needed to format the parameters and submit them to an API using some code. The code involved iterating through performance criteria, performance indicators, and target details to create new objects and push them ...

What is the best way to only buffer specific items from an observable source and emit the rest immediately?

In this scenario, I have a stream of numbers being emitted every second. My goal is to group these numbers into arrays for a duration of 4 seconds, except when the number emitted is divisible by 5, in which case I want it to be emitted immediately without ...

Mapping the response from an http.get call to create a new typed object instance in Angular 2

Can anyone help me understand how to map the result from a service call to an object using http.get and Observables in Angular 2? Please check out this example In my getPersonWithGetProperty method, I am trying to return an Observable of type PersonWithG ...

Choose a value, then multiply it by a number using a reactive

I have been attempting to multiply a fixed value by the selected value of a mat-select element, for example A x B, where A remains constant and does not change while B is the changing value from the mat-select. After performing this multiplication, I aim ...

Set the default value for a form control in a select dropdown using Angular

I've been struggling to figure out how to mark an option as selected in my select element, but I haven't had any luck. I've tried multiple solutions from the internet, but none of them seem to be working for me. Does anyone out there have ...

How to dynamically load a component within a class-based Vue component

I am facing an issue with loading two components dynamically using an object map. Info (options-based) SearchBar (class-based) While it works for the options-based component, I encounter an error stating _currentTab is undefined when trying to load a si ...

Is it possible to use TypeScript in a React Native project with a JavaScript file?

Currently, I am learning React Native by working on app clones like Instagram and YouTube. I have recently started an AirBnb clone project, but I'm facing some issues with the initial build. One issue I noticed is that in 'App.js', the temp ...

The 'style' property is not found within the 'EventTarget' type

Currently, I am utilizing Vue and TypeScript in an attempt to adjust the style of an element. let changeStyle = (event: MouseEvent) => { if (event.target) { event.target.style.opacity = 1; Although the code is functional, TypeScript consist ...

Utilizing Jest and nest.js for testing with absolute paths

Looking at my jest configuration inside the package.json: "jest": { "moduleFileExtensions": [ "js", "json", "ts" ], "moduleDirectories":["node_modules", "src" ...

The Node.js express seems to be unable to fetch the css and js files

Sharing my main.ts file in which I am facing issues with linking my css and js files. view image import express from 'express'; import {Request,Response} from 'express'; import expressSession from 'express-session'; import pat ...

Tips for storing information without using ngModel in template-driven methodology

Currently facing a dilemma where data needs to be saved to the database from Angular UI. The display format of tabular data changes dynamically based on dropdown selections, without having predefined model properties for binding. The question arises: How ...

A TypeScript interface creating a type with optional keys of various types while enforcing strict null checks

I am attempting to devise an interface in typescript that resembles the following: type MoveSpeed = "min" | "road" | "full"; interface Interval { min?: number, max?: number } interface CreepPlan { [partName: string] : Interval; move?: MoveSpe ...

Angular: utilizing input type="date" to set a default value

Looking for a way to filter data by date range using two input fields of type "date"? I need these inputs to already display specific values when the page loads. The first input should have a value that is seven days prior to today's date, while the ...

Upon running the code, no errors appear on the console. However, my project isn't functioning properly and I'm encountering errors on the web console

ReferenceError: require is not defined when trying to access external "url" at Object.url in webpack_require (bootstrap:83) at client:6 importing from webpack-dev-server client index.js(http://0.0.0.0:0) vendor.js:219506 dynamically imp ...

Having trouble opening a JPEG file that was generated using the Writefile Api in Ionic-Cordova

Currently, I am using the writeFile API to create a JPEG image. The process is successful and the image is stored in the directory as expected. However, when I try to open the file manually from the directory, I encounter an error message saying "Oops! Cou ...

Creating a personalized fake database functionality in Angular

Is there a way to implement the fake-db feature in Angular while utilizing this resource? I need it to support an API response structure like the one below for list retrieval. // GET 'api/outlets' { data: [ {'id':1, 'name&ap ...

Using ThreeJS to Apply Dual Materials to a Mesh Entity

With ThreeJS, it's possible to incorporate more than one material into an Object3D/Mesh as stated in the documentation. You can either utilize a single Material or an array of Material: Class declaration and constructor for Mesh TypeScript file (exce ...