#Infer return type fields conditionally

16 messages · Page 1 of 1 (latest)

desert bridge
#

This function allows the caller to optionally specify which fields to return from a database query.

export function selectActivitiesByActivityId(activityIds: number[], fields: Array<keyof ActivityHistoryTable> = []) {
  const db = createKysely();
  let query = db.selectFrom(ACTIVITIES_TABLE)
  if(fields.length){
    query = query.select(fields);
  } else {
    query = query.selectAll();
  }
  query = query.where('activity_id', 'in', activityIds);
  return query.execute();
}

If I remove the if statement and just use selectAll, the compiler can infer that the return type contains all of the fields from the ACTIVITIES_TABLE .
However, with the if statement, the compiler can’t infer the output and just specifies Promise<{}> as the return type. How do I help the compiler to infer the return type that is either all fields or the fields returned that match those that are passed in?

idle ocean
#

probably best to use overloads in this case

normal epoch
#

yes

#

but the main issue is the re-assignment

#

assinging a different value to a variable doesn't change its type

#

I'll explain using a simpler example

#
let foo: string | number = "foo";
if(Math.random() < 0.5) foo = 5;
else foo = "bar";
foo;
//^?
tawny merlinBOT
#
let foo: string | number = "foo";
if(Math.random() < 0.5) foo = 5;
else foo = "bar";
foo;
//^? - let foo: string | number
normal epoch
#

it's not possible for TS to know what the outcome will be

#

even if the branches are deterministic,
as long as they are multiple possible branches in the code, we won't know for sure

#

👉 one solution would be to use different query objects

#

👉 a simpler solution might be to simply capture using a generic the fields wanted, and use that generic type in the return type

#

👉 also you should not re-create your db connection inside of the function, but probide it as param or import it from a different module

#

but tbh, having that kind of function kinda ruins the purpose of kysely
the goal of kysely is having the correct return type inferred automatically right after writing the query

#

you added generics only complexifes the logic, and you'd need to repeat what already exists inside of kysely (select all vs select)

desert bridge
#

Thanks @normal epoch - I asked in the Kysely Discord too. Koskimas suggested using the $if() function for this referenced here
I'm playing with that but I don't currently see how to switch between selectAll and select based on runtime logic but I'll keep playing and post back here what I find

Sometimes you may want to select some fields based on a runtime condition.