Obtaining parameter types for functions from deeply nested types

I'm currently facing a challenge involving deeply nested parameters.

When dealing with non-nested parameters, everything functions smoothly without any issues

export type test = {
  'fnc1': () => void,
  'fnc2': () => void,
  'fnc3': () => void,
  'fnc4': () => void,
}
export type FncParams<key extends keyof test> = Parameters<test[key]>;

However, upon attempting to work with deep nesting, I encounter a TypeScript error. It's important to note that the typing works fine for code hinting despite the compilation error.

export type testDeep = {
  'key1': {
    'fnc1': () => void,
    'fnc2': () => void,
  },
  'key2': {
    'fnc3': () => void,
    'fnc4': () => void,
  }
}
export type FncDeepParams<
  key extends keyof testDeep,
  event extends keyof testDeep[key]
> = Parameters<testDeep[key][event]>;
Type 'testDeep[key][event]' does not satisfy the constraint '(...args: any) => any'.
  Type 'testDeep[key][keyof testDeep[key]]' is not assignable to type '(...args: any) => any'.

One workaround was to include

[x:string]: (...args: any) => void
in testDeep, but this led to a loss of typing assistance

Is there a way to meet the constraint requirement without making it overly generic?

Thank you!

Answer №1

Is there a way to meet the constraint without making it too generic?

I'm not entirely sure what you mean, but here is a solution that enables indexing function parameters on nested objects similar to your example:

TS Playground

type Fn<Params extends readonly any[] = readonly any[], Result = any> =
  (...params: Params) => Result;

type FnInObject<O extends Record<K, Fn>, K extends PropertyKey> = O[K];

type NestedFunctions = {
  key1: {
    fnc1: (param: string) => void;
    fnc2: (param: number) => void;
  };
  key2: {
    fnc3: (param: boolean) => void;
    fnc4: (param: null) => void;
  };
};

type NestedFnParams<
  O extends Record<PropertyKey, Record<PropertyKey, Fn>>,
  K0 extends keyof O,
  K1 extends keyof O[K],
> = Parameters<O[K0][K1]>;

type P1 = NestedFnParams<NestedFunctions, 'key1', 'fnc1'>; // [param: string]
type P2 = NestedFnParams<NestedFunctions, 'key1', 'fnc2'>; // [param: number]

type P3Invalid = NestedFnParams<NestedFunctions, 'key1', 'fnc3'>; // never

type P3 = NestedFnParams<NestedFunctions, 'key2', 'fnc3'>; // [param: boolean]
type P4 = NestedFnParams<NestedFunctions, 'key2', 'fnc4'>; // [param: null]

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

How Angular services transmit information to components

I have implemented a search field within my top-bar component and I am facing an issue in passing the input value of that search field to another component. Design Search service Top bar component Result component Operation Top bar component receives th ...

Which is the optimal choice: subscribing from within a subscription or incorporating rxjs concat with tap?

After storing data in the backend, I proceed to retrieve all reserved data for that specific item. It is crucial that the data retrieval happens only after the reservation process to ensure its inclusion. Presented with two possible solutions, I am cont ...

add the string to the chat messages array in the observable

Currently, I am in the process of developing a chat application and my goal is to showcase the user's messages in the chatroom, referred to as the feed in this project. I have already implemented a function called getMessages() that displays all exist ...

Ensuring type signatures are maintained when wrapping Vue computed properties and methods within the Vue.extend constructor

Currently, I am trying to encapsulate all of my defined methods and computed properties within a function that tracks their execution time. I aim to keep the IntelliSense predictions intact, which are based on the type signature of Vue.extend({... Howeve ...

Swiper moves through different sections, while the navigation bar acts as pagination

I am currently utilizing next.js, typescript, and swiper. My goal is to highlight the current slide or section in the navigation bar. I was successful in achieving this with vanilla javascript at https://codepen.io/ms9ntQfa/pen/eYrxLxV but I'm unsure ...

Obtain the firebase object using Angular framework

Hey there, I've been working on retrieving a Firebase object using Angular and have successfully achieved that. However, I'm now faced with the challenge of how to navigate deeper into the data that is being returned (check out the images linked ...

Getting a "function is not defined" error in Angular 6 while using it within a nested function

I'm facing an issue related to typescript, where the following code is causing trouble: private loadTeams = function(){ let token = sessionStorage.getItem('token'); if(token !== undefined && token !== null && token ...

What is the process for publishing TypeScript interface definitions via npm?

I've been grappling with this problem for the past few days, scouring the internet and reading extensively, but I haven't come across any examples that match my specific scenario. My goal is to publish a library using npm that includes its own ty ...

Discover the latest DOM elements using Webdriverio 5

Currently, I am developing a REact based CMS application that features a form with multiple carousels. I am encountering an issue where the webdriverio implementation is unable to locate an element, even though the same xpath works fine when tested manua ...

The outcome of using Jest with seedrandom becomes uncertain if the source code undergoes changes, leading to test failures

Here is a small reproducible test case that I've put together: https://github.com/opyate/jest-seedrandom-testcase After experimenting with seedrandom, I noticed that it provides consistent randomness, which was validated by the test (running it multi ...

Implementing JavaScript Code in TypeScript

Every JavaScript code should also be valid in TypeScript, but when attempting to run the following code snippet below, an error is triggered. Could someone convert this JavaScript code into TypeScript? Error: 20:9 - TS2531 Error: Object is possibly 'z ...

Checking conditions sequentially in Angular

I have a unique use case that requires me to verify certain conditions. If one condition fails, I should not proceed to the next one. Instead, based on the failed condition, I need to display a dialog with a title and description explaining what went wrong ...

I implemented progress bars in Angular 2 that have changing maximum values. The service updates the maximum value for each bar dynamically. Currently, the progress bars are functioning at 100% capacity

this.games=[ {"val":50, "name":"Articlescontributed","max":35}, {"val":30 ,"name":"Articlesrated", "max":999}, {"val":20, "name":"Views", "max":35}, {"val":30, "name":"Ratings", "max":35}, {"val":20, "name":"Follower", "max":200}, { ...

How can you verify the anticipated log output in the midst of a function execution with Jest unit testing?

Below is a demonstration function I have: export async function myHandler( param1: string, param2: string, req: Request, next: NextFunction, ) { const log = req.log.prefix(`[my=prefix]`); let res; If (param1 === 'param1&a ...

Error in TypeScript code for combined Slider and Input onChange functionality within a Material-UI component

HandleChange function is used to update the useState for Material-UI <Slider /> and <Input />. Here is the solution: const handleChange = (event: Event, newValue: number | number[]) => { const inputValue = (event.target as HTMLInputEle ...

How to pass a distinct identifier to an Angular 2 component?

Encountering an issue with Angular2 where I need to assign a unique identifier to my reusable component. Seeking assistance from the community. account.html <div class="container"> <!-- ACCOUNT INFO --> <div class="row"> ...

What is the reason behind TypeScript's lack of reporting an incorrect function return type?

It's surprising to see that TypeScript 4.4.3 does not identify an invalid type for the callback function. It makes sense when the function returns a "non-promise" type, but when it returns a Promise, one would expect TypeScript to recognize that we ne ...

When working with Angular Universal, using d3.select may result in a "reference error: document is not defined" in the server.js file

I'm currently working on an Angular project that uses server-side rendering to generate D3 charts. Each chart is encapsulated within its own component, such as a line-chart component which consists of TypeScript, spec.ts, HTML, and CSS files for rende ...

Encountering an issue accessing a property retrieved from a fetch request in TypeScript

I am currently dealing with the property success defined in the API (reCAPTCHA). /** * The structure of response from the veirfy API is * { * "success": true|false, * "challenge_ts": timestamp, // timestamp of the challen ...

Tips on continuously making calls to a backend API until receiving a successful response with status code 200

While working on my Angular project, I have encountered a situation where I need to make calls to a backend API. If the response is not 200 OK, I have to keep calling the API every 30 seconds until I receive a successful response. In Angular, I usually ca ...