Here's a type-safe functional solution that accepts two string enums as parameters (so you can reuse it for other cases):
TS Playground link
type StringEnum = Record<string, string>;
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;
};
};
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;
}
// Use:
enum RequestType {
Request = 'Request',
Success = 'Success',
Failure = 'Failure',
}
// Overloaded function declaration (classic)
// function createActions <
// P extends StringEnum,
// C extends StringEnum,
// >(enumParent: P, enumChild: C): NestedCombinedStringEnum<P, C>;
// function createActions <P extends StringEnum>(enumParent: P): NestedCombinedStringEnum<P, typeof RequestType>;
// function createActions <
// P extends StringEnum,
// C extends StringEnum,
// >(enumParent: P, enumChild?: C) {
// return nestAndCombineStringEnums(enumParent, enumChild ?? RequestType);
// }
// Overloaded function expression (you'll see this style less often, but the two are equivalent)
const createActions: {
<P extends StringEnum, C extends StringEnum>(enumParent: P, enumChild: C): NestedCombinedStringEnum<P, C>;
<P extends StringEnum>(enumParent: P): NestedCombinedStringEnum<P, typeof RequestType>;
} = <C extends StringEnum, P extends StringEnum>(
enumParent: P,
enumChild?: C,
) => nestAndCombineStringEnums(enumParent, enumChild ?? RequestType);
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
createActionsshould combine the keys of two enums and pascal case them? Will the resultant object contain 9 properties?