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

A method for comparing two arrays containing identical objects and then storing the results in a variable

I have an item stored within two other items called formKeyValues and form formKeyValues https://i.stack.imgur.com/nRfiu.png form https://i.stack.imgur.com/eDpid.png I am looking to extract only the keys and values from formKeyValues and place them in ...

Encountering issues with verifying login credentials in Angular 2

Greetings! I have designed a login page where the user will be logged in if the response is successful, otherwise an error message will be displayed. Below is the JSON data with email and password fields: { Email": "<a href="/cdn-cgi/l/email-protect ...

`The Art of Curved Arrows in sigjma.js, typescript, and npm`

I have encountered an issue while trying to draw curved arrows in sigma.js within my TypeScript npm project. The error occurs on the browser/client-side: Uncaught TypeError: Cannot read properties of undefined (reading 'process') at Sigma.pro ...

Steps for utilizing an `<a>` link tag to submit a form in Angular 4

Is there a way to retrieve the selected option in this form from the other side when clicking a link? <form (ngSubmit)="onSubmit(x)"> <input type="radio" id="radioset3" name="radioset" [checked]="x==0"> <input type="radio" id="radio ...

In TypeScript Next.js 14 APP, object literals are limited to declaring existing properties

I encountered an error in my typescript next.js 14 APP. I need assistance resolving this issue, which states: Object literal may only specify known properties, and 'productPackages' does not exist in type '(Without<ProductCreateInput, Pr ...

The fillFormValues function is not functioning properly within the mat-select element

I need help filling a form value by id. This function successfully retrieves the value: fillFormValues(expenseCategory: ExpenseCategory): void { console.log('response', expenseCategory.parent_category) this.aa= expenseCategory.parent_c ...

Update the value in a nested object array by cross-referencing it with a second nested object array and inserting the object into the specified

I have a large array of objects with over 10,000 records. Each object contains an array in a specific key value, which needs to be iterated and compared with another array of objects. If there is a match, I want to replace that value with the corresponding ...

The 'palette' property is not found on the Type 'Theme' within the MUI Property

Having some trouble with MUI and TypeScript. I keep encountering this error message: Property 'palette' does not exist on type 'Theme'.ts(2339) Check out the code snippet below: const StyledTextField = styled(TextField)(({ theme }) = ...

The function 'transformArticles' is not recognized as a property of the object 'Article'

I'm encountering an issue with Typescript that I need help understanding. In my code, I have a route where I am importing a class called Article like this: import { Request, Response } from "express"; const appRoot = require("app-root-path"); import ...

Exploring the functionality of the scan operator within switchMap/mergeMap in RxJS

We're utilizing the scan operator to handle our 'load more' button within our table. This operator allows us to accumulate new results with the previous ones, but we've come across some unexpected behavior. Let's break it down by l ...

Error: Unable to cast value to an array due to validation failure

I'm currently working on integrating Typegoose with GrqphQL, MongoDB, and Nest.js for a project. My goal is to create a mutation that will allow users to create a post. I have set up the model, service, and resolver for a simple Post. However, when I ...

Arranging information within the Ngb-Accordion

Welcome to the code snippet showcasing how to create an accordion in Angular: <ngb-accordion [closeOthers]="false" activeIds="0"> <ng-container class="card" *ngFor="let post of Posts"> <ngb-panel title="{{post.title}} - ...

Tips to store Google fonts in the assets directory

I've included this link in my styles.scss @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap'); While it works locally, the API fails on production or is blocked. How can I host it within my p ...

Creating a new JavaScript object using a Constructor function in Typescript/Angular

Struggling with instantiating an object from an external javascript library in Angular/Typescript development. The constructor function in the javascript library is... var amf = { some declarations etc } amf.Client = function(destination, endpoint, time ...

Tips for patiently anticipating the completed response within an interceptor

Using the interceptor, I want to display a loading spinner while waiting for subscriptions to complete. This approach works well in individual components by showing and hiding the spinner accordingly: ngOnInit() { this.spinnerService.show(); this. ...

Customizing the Material UI v5 theme with Typescript is impossible

I'm attempting to customize the color scheme of my theme, but I am encountering issues with accessing the colors from the palette using theme.palette. Here is a snippet of my theme section: import { createTheme } from "@mui/material/styles&qu ...

ERROR TS1086: A declaration of an accessor within an ambient context is not allowed. Accessor for firebaseUiConfig(): NativeFirebaseUIAuthConfig

Trying to create a Single Page Application with Angular/CLI 8. Everything was running smoothly locally until I tried to add Firebase authentication to the app. Upon compiling through Visual Studio Code, I encountered the following error message: ERROR in ...

Integrate a fresh global JSX attribute into your React project without the need for @types in node_modules

It is crucial not to mention anything in tsconfig.json. Error Type '{ test: string; }' cannot be assigned to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'. Property 'test' does not exi ...

TailwindCSS applies CSS settings from tailwind.admin.config.js without overriding tailwind.config.js. The @config directive is utilized for this purpose

I'm currently working on a project using Vite and React. I have a tailwind.admin.css file that is similar to the example provided in the documentation. @config './configs/tailwind.admin.config.js'; @tailwind base; @tailwind components; @tai ...

An unfamiliar data type is provided as a number but is treated as a string that behaves like a number

Here is the code snippet in question: let myVar = unknown; myVar = 5; console.log((myVar as string) + 5); Upon running this code, it surprisingly outputs 10 instead of what I expected to be 55. Can someone help me understand why? ...