Home > other >  Typescript create nested type based on parent key
Typescript create nested type based on parent key

Time:08-30

Trying to create status, subStatus type from an object.

The subStatus type is inferred from the status.

const APP_STATE = {
  success: {
    defaultX: {}
  },
  failed: {
    apiError: {},
    timeout: {}
  }
}

type AppStateFn<T, U = keyof T> = {
  status: U;
  subStatus: keyof T[U]; // U not working
}

type AppState = AppStateFn<typeof APP_STATE>;

How to extract nested subStatus based on status from the object? This is required type

type AppStateManuallyTyped = {
  status: 'success',
  subStatus: 'defaultX'
} | {
  status: 'failed',
  subStatus: 'apiError' | 'timeout'
}

playground

CodePudding user response:

I think this is what you want (playground):

const APP_STATE = {
  success: {
    defaultX: {}
  },
  failed: {
    apiError: {},
    timeout: {}
  }
}

type AppStateFn<T extends object> = {
  [key in keyof T]: {
    status: key;
    subStatus: keyof T[key];
  };
}[keyof T];

type AppState = AppStateFn<typeof APP_STATE>;

Resulting type is:

type AppState = {
    status: "success";
    subStatus: "defaultX";
} | {
    status: "failed";
    subStatus: "apiError" | "timeout";
}

As to what is going on, first part of the type generates a type for each top-level property of input via mapped type, and that generated type consists of that top-level property (status: key;) and all second-level properties (subStatus: keyof T[key];). Afterwards, through means of indexed access type [keyof T] extracts all resulting types and unionize them into single |-expression.

  • Related