KyselyK
Kysely2y ago
2 replies
Nikola

Dynamic return type based on provided select array

So I have this function:
 async getBillableUsers(select: SelectExpression<DB, 'user_data'>[]) {
    return this.db
      .selectFrom('user_data')
      .select(select)
      .where((eb) => eb.or([eb('billability_type', '=', 'Billable'), eb('billability_type', 'is', null)]))
      .execute();
  }

And when I call it I want the return type to contain only the fields that were provided in the select parameter.
const billableUsers = await this.getBillableUsers(['id', 'work_email']);

In the result above, billableUsers contains all user_data column values, how can I narrow it down? I tried a lot of things but I keep getting type errors.
I am using the kysely-codegen library for the types.

Thanks for the help!
Solution
Took 2 hours but I think I figured it out.
Here's my solution for anyone else who might stumble upon this problem.
Feel free to leave better/smarter/faster/shorter alternatives.

  async getBillableUsers<T extends SelectExpression<DB, 'user_data'>>(select: T[]) {
    return this.db
      .selectFrom('user_data')
      .select(select)
      .where((eb) => eb.or([eb('billability_type', '=', 'Billable'), eb('billability_type', 'is', null)]))
      .execute();
  }


Now:
const billableUsers = await this.getBillableUsers(['id', 'work_email']);

correctly resolves to:
const billableUsers: {id: string, work_email: string}[]
Was this page helpful?