Skip to main content
Sometimes you need to select fields based on runtime conditions. For example:
If withLastName is true, the person object should include the last_name property, otherwise it shouldn’t.

The wrong approach

Your first instinct might be to do this:
While this compiles, the result type would be { first_name: string, kind: 'person' } without the last_name column, which is wrong.

Why this fails

What happens:
  1. The type of query when created is A
  2. The type with last_name selection is B (extends A plus new selection info)
  3. When you assign type B to query inside the if, it gets downcast to A
You can use this pattern for conditional where, groupBy, orderBy etc. that don’t change the query builder type. But it doesn’t work with select, returning, innerJoin etc. that do change the type.

Solution 1: Separate branches

For simple cases with one condition, use separate return statements:
This works for single conditions, but with multiple conditions the code explodes. You need a separate branch for every combination to maintain correct types.
The $if method provides type-safe conditional selections:

How $if works

Selections added inside the $if callback are added as optional fields to the output type. This is because Kysely can’t know if the selections were actually made before running the code.
This is the recommended approach for most use cases as it maintains type safety while being concise.

Multiple conditions

$if shines when you have multiple conditions:

Conditional joins

You can also use $if for conditional joins:
Be careful with duplicate joins when using $if with joins. See the DeduplicateJoinsPlugin for solutions.

Limitations of $if

A downside of $if is that it cannot result in discriminated union return types:
For discriminated unions, use the separate branches approach (Solution 1).

Combining with dynamic queries

You can combine $if with the dynamic module for powerful conditional queries:

Best practices

1

Use $if for optional fields

When you need optional fields in your result type, use $if.
2

Use branches for discriminated unions

When you need discriminated union types, use separate if/else branches.
3

Chain multiple $if calls

Don’t try to combine multiple conditions in one $if — chain them instead.
4

Consider query performance

Remember that conditional selections still result in a single SQL query with optimal performance.