Home > Mobile >  Need help to convert typescript helper
Need help to convert typescript helper

Time:12-07

I have a helper I'm exporting and importing into multiple files which is working fine, however I want to change it slightly and I'm struggling to figure this one out:

// utils.ts
export enum RequestTypes {
  Request,
  Success,
  Failure,
}

type CombineEnums<P, C> = {
  [KP in keyof P]: {
    [KC in keyof C]: KP extends string ? KC extends string ? `${KP}${KC}` : never : never;
  };
};

export function createActions <P, C>(actionTypes: P, requestTypes: C): CombineEnums<P, C> {
  const result: any = {};
  for (const keyP of Object.keys(actionTypes)) {
    result[keyP] = {};
    for (const keyC of Object.keys(requestTypes)) {
      result[keyP][keyC] = `${keyP}${keyC}`;
    }
  }
  return result;
}

Now in another file I'm importing the createActions method & RequestTypes and using it like so:

// module.ts
import { createActions, RequestTypes } from './utils.ts';
enum Actions {
   Find,
   Create
}
const actions = createActions(Actions, RequestTypes);
// actions.Find.Request -> 'FindRequest'
// actions.Find.Success -> 'FindSuccess'
// actions.Create.Failure -> 'CreateFailure'

This all works fine, however RequestTypes will rarely change, i want to make it an optional argument, but still able to pass through other RequestTypes if needed.

So idealy by default I'd like the above solution but the usage will be:

const actions = createActions(Actions) with the same output.

And if need be, pass through different RequestTypes:

enum TabRequests {
   Open,
   Close
}
enum TabActions {
   Tab
}
const actions = createActions(TabActions, TabRequests);
// actions.Tab.Open -> 'TabOpen'
// actions.Tab.Close -> 'TabClose'

I've tried everything i can think of but can't seem to figure out the typescript side of this!

CodePudding user response:

You can use typescript overload signatures, also see the playground:

// signature for only one argument
export function createActions <P>(actionTypes: P): CombineEnums<P, typeof RequestTypes>;

// signature for two arguments
export function createActions <P, C>(actionTypes: P, requestTypes: C): CombineEnums<P, C>;

// actual implementation with default value for second argument
export function createActions <P>(actionTypes: P, requestTypes: any = RequestTypes): CombineEnums<P, any> {
  const result: any = {};
  for (const keyP of Object.keys(actionTypes)) {
    result[keyP] = {};
    for (const keyC of Object.keys(requestTypes)) {
      result[keyP][keyC] = `${keyP}${keyC}`;
    }
  }
  return result;
}

// If you want you could also use the following line as implementation signature
// export function createActions <P, C>(actionTypes: P, requestTypes: C | typeof RequestTypes = RequestTypes): CombineEnums<P, C | typeof RequestTypes> {


// Now you can use both signatures, typesafe.
const actionsWithRequestTypeArgument = createActions(Actions, RequestTypes);
const actionsWithoutRequestTypeArgument = createActions(Actions);
  • Related