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:Why this fails
What happens:- The type of
querywhen created isA - The type with
last_nameselection isB(extendsAplus new selection info) - When you assign type
Btoqueryinside theif, it gets downcast toA
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:Solution 2: Using $if (recommended)
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.
Multiple conditions
$if shines when you have multiple conditions:
Conditional joins
You can also use$if for conditional joins:
Limitations of $if
A downside of$if is that it cannot result in discriminated union return types:
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.