type Dict = { [K in keyof T]: (string | number)[] }; export const splitByComma = >( obj: T, ): Dict => { return Object.entries(obj).reduce( (acc, [key, value]) => { if (key === 'properties' && typeof value === 'object') { const nested = splitByComma(value as any); return { ...acc, ...nested }; } else if (typeof value === 'string') { return { ...acc, [key]: value.split(',') }; } else { return { ...acc, [key]: [value] }; } }, {} as Dict, ); }; export const generateCombinations = >( obj: Dict, ): T[] => { const keys = Object.keys(obj) as (keyof T)[]; return keys.reduce( (results, key) => results.flatMap((result) => obj[key].map((value) => ({ ...result, [key]: value })), ), [{}] as Partial[], ) as T[]; }; export const generateObjectCombinations = >( obj: T, ): T[] => { const splitObj = splitByComma(obj); return generateCombinations(splitObj); };