Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

112
Vistas
Need help to convert typescript helper

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!

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

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);
about 4 years ago · Juan Pablo Isaza Denunciar

0

Here's how you can use the overloaded function from the other answer in a separate module:

TS Playground link

// utils.ts

type StringEnum = Record<string, string>;

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

export function nestAndCombineStringEnums <
  P extends StringEnum,
  C extends StringEnum,
>(enumParent: P, enumChild: C): NestedCombinedStringEnum<P, C> {
  const result: any = {};

  for (const keyP of Object.keys(enumParent)) {
    result[keyP] = {};
    for (const keyC of Object.keys(enumChild)) {
      result[keyP][keyC] = `${keyP}${keyC}`;
    }
  }

  return result;
}

export enum RequestType {
  Request = 'Request',
  Success = 'Success',
  Failure = 'Failure',
}

export function createActions <
  P extends StringEnum,
  C extends StringEnum,
>(enumParent: P, enumChild: C): NestedCombinedStringEnum<P, C>;
export function createActions <P extends StringEnum>(enumParent: P): NestedCombinedStringEnum<P, typeof RequestType>;
export function createActions <
  P extends StringEnum,
  C extends StringEnum,
>(enumParent: P, enumChild?: C) {
  return nestAndCombineStringEnums(enumParent, enumChild ?? RequestType);
}

// module.ts

import {createActions, RequestType} from './utils.ts';

enum ActionType {
  Find = 'Find',
  Update = 'Update',
  Create = 'Create',
}

const actions = createActions(ActionType); // same as createActions(ActionType, RequestType);
console.log(actions.Create.Success); // "CreateSuccess"
console.log(actions); // the expected result object in your question

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda