/** * Generate is a helper type to generate a type from a type or a function. */ export type Generate = | T | ((...args: { [K in keyof U]: U[K] }) => T) | ((...args: { [K in keyof U]: U[K] }) => Promise); /** * Generated infers the type of a generated value. */ export type Generated = T extends Generate ? U : never; /** * ArgsOf infers the type of the arguments of a generated function. */ export type ArgsOf = T extends Generate ? U : never; /** * generateObject generates an object from a value or a function. */ export async function generateObject< T extends { [K in keyof T]: Generate }, >( object: T, argsMap: { [K in keyof T]: ArgsOf }, ): Promise<{ [K in keyof T]: Generated }> { const entries = Object.entries(object) as [ keyof T, Generate>, ][]; const promises = entries.map(([key, value]) => (async () => { const args = argsMap[key]; const generated = await generate(value, ...args); return [key, generated] as const; })() ); const generatedEntries = await Promise.all(promises); return Object.fromEntries(generatedEntries) as { [K in keyof T]: Generated; }; } /** * generate generates a value from a value or a function. */ export async function generate( data: Generate, ...args: U ): Promise { if (data instanceof Function) { return await data(...args); } return data; }