Home > Software design >  How to get parameters of nested object
How to get parameters of nested object

Time:08-11

I'm trying to infer the parameters of a nested object that looks like this:

const lightSwitch = {
  off: {
    switchOn: (state: Data, payload: number) => ({
      ...state,
      state: 'on',
      meta: payload,
    }),
  },
  on: {
    switchOff: (state: Data) => ({
      ...state,
      state: 'off',
    }),
  },
};

I want a type, Params, that looks like this:

 {
   'switchOn': [state: Data, payload: number]
   'switchOff': [state: Data]
 }

Here's what I'm doing:

type Intersect<T> = T extends { [K in keyof T]: infer E } ? E : T;

type Flattened = Intersect<typeof lightSwitch>;

type Params = { [K in keyof Flattened]: Parameters<Flattened[K]> }; // type Params = {}

Why is Params empty, and how do I correct this?

https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgCJzHZBvAsAKGWQGdNIAuEsKUAcwG4CiBbCTAfkrhAE9H8AvgQIIA9iFLIANsFoALMAGUA7sDAI5yALw4myUTBiU8hIiVXq5AeRCUAFKQwRK6TABpkABzg8pouAAmlCAArswARtAAlNoAfMh2JmZmAHRpjpBueskZzsgA5OL5WabJrJiU3r7 ASXJAlF1yAJN4sbZ5moaVob2uS4YcDFa8YkdRGkpuU05ZHmFhsUdDU0tBAL8BGA8nigAkuDQxBAIYAA8ACrxOhfIEAAekCABxDjIANoA0sigyADWEB4BmQFwAupRQDBoMgAKLNZDsWHISgXTb4ba7ZAAMSkGCeEAC2mQB0gUGOpzOGIgwJk8iUFg0sTRVOQAAU4FA4MxXjpsB9vr8AUCYNjcWB8QFwWyOVy2Eczji8RAQASvqD4htkAB6LXIFnsznconYIT4Ag65AACVEyj1omQtDYep2KANXNecGI5HNupMFqI WIDOsIHylHe-TQgw8VT8gWCYUiUFBPrMgeDPRgYY kdccBT AtAiAA

CodePudding user response:

Flattened is a union of objects which do not share any properties. That's why keyof Flattened just evaluates to never resulting in an empty object type. We should convert this union to an intersection using the UnionToIntersection type.

type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

type GetNested<T> = UnionToIntersection<T[keyof T]>

The GetNested type will convert typeof lightSwitch to an object with two properties switchOn and switchOff which can be mapped.

type Params<T> = { 
  [K in keyof GetNested<T>]: 
    Parameters<
      GetNested<T>[K] extends infer U extends (...args: any) => any ? U : never
    > 
};

type T0 = Params<typeof lightSwitch>
// type T0 = {
//   switchOn: [state: Data, payload: number];
//   switchOff: [state: Data];
// }

Playground

  • Related