I am trying to solve an issue getting deep nested parameters.
If I am getting parameters from non nested type, everything is working fine
export type test = {
'fnc1': () => void,
'fnc2': () => void,
'fnc3': () => void,
'fnc4': () => void,
}
export type FncParams<key extends keyof test> = Parameters<test[key]>;
But when I am trying to do it deeply, I am getting typescript error. Note that typing is working (I mean code hinting) except error during compilation.
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'.
What helped is to add
[x:string]: (...args: any) => void
into testDeep, but then I lose all typing helps
Is there way to satisfy constraint without doing it too generic?
Thanks!
CodePudding user response:
Is there way to satisfy constraint without doing it too generic?
I'm not exactly sure what that means, but here's a solution that will allow you to index function parameters on nested objects like in your example:
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]