Problems typing a generic withPerson helper

Aautobotkilla4/14/2023
First I want to say that I'm in love with Kysely! It's amazing. I could use some help getting the types right for a helper function I'm creating.

I'm trying to follow the relations recipe (the withPets and withMom example from the docs), but I want to make it slightly more reusable.

I have a withPerson method

export function withPerson<As extends string>(
    builder: ExpressionBuilder<DB, keyof DB>,
    personIdCol: ReferenceExpression<DB, keyof DB>,
    as: As = 'person' as As
) {
    return jsonObjectFrom(
        builder
            .selectFrom('Person')
            .whereRef('Person.id', '=', personIdCol)
            .select([
                'Person.id', 
                'Person.givenName', 
                'Person.familyName', 
                'Person.picture80', 
                'Person.picture144'
            ])
    ).as(as);
}


When I try and use it like this

const result = db
        .selectFrom('Prospect')
        .select((eb) => withPerson(eb, 'person'))
        .execute();

I get a typescript error: Argument of type 'ExpressionBuilder<DB, "Prospect">' is not assignable to parameter of type 'ExpressionBuilder<DB, keyof DB>'
Aautobotkilla4/14/2023
So I tried making the function more generic.

export function withPerson<
    TDB extends DB,
    TTB extends keyof TDB,
    As extends string>(
    builder: ExpressionBuilder<TDB, TTB>,
    personIdCol: ReferenceExpression<TDB, TTB>,
    as: As = 'person' as As
) {
    return jsonObjectFrom(
        builder
            .selectFrom('Person')
            .whereRef('Person.id', '=', personIdCol)
            .select([
                'Person.id', 
                'Person.givenName', 
                'Person.familyName', 
                'Person.picture80', 
                'Person.picture144'
            ])
    ).as(as);
}


This fixes the typescript error when I call the function, but messes up the typing inside the function on the .whereRef and .select calls.

Argument of type 'string' is not assignable to parameter of type 'ReferenceExpression<TDB, TTB | ("Person" extends keyof TDB ? keyof TDB & "Person" : never)>'.

I just can't seem to figure this out. I'd really appreciate any help.
Aautobotkilla4/14/2023
I'm trying to make it so that any table that has a foreign key to the person table can load the same person data, but pass in the column reference for that table. For example, Message.senderId or Project.ownerId both point to the person table.
Aautobotkilla4/14/2023
Here's a repro on Kysely playground https://kyse.link/?p=s&i=8gXYLeE8i8LQVeEFSjsv
IIgal4/14/2023
Hey 👋

Thanks for the playground repro, will take a look
IIgal4/14/2023
wasn't able to crack it yet. seems like classic TS not narrowing stuff in a function
Aautobotkilla4/16/2023
Thanks for looking at this @Igal. The workaround isn't terrible actually since it allows me to limit the callers to tables with a foreign key.