© 2026 Hedgehog Software, LLC

TwitterGitHubDiscord
More
CommunitiesDocsAboutTermsPrivacy
Search
Star
Setup for Free
Drizzle TeamDT
Drizzle Team•3y ago•
1 reply
DiamondDragon

Help with proper types (values)

I've been working to try to get a dynamic method to related/unrelate records together on a join table


async linkEntities<TJoinTable extends Table>(
        joinTable: TJoinTable,
        sourceIdField: keyof TJoinTable,
        relatedEntityField: keyof TJoinTable,
        sourceId: string,
        relatedEntityIds: string[],
    ) {
        // 1. Fetch existing related entity IDs

        const column = joinTable[sourceIdField] as Column // required to cast to satisfy where/eq

        type ExpectedRowType = {
            // maps over keys in the join table to be string or null
            [K in keyof TJoinTable]: string | null
        }

        const existingRelatedEntities = (await this.db
            .select()
            .from(joinTable)
            .where(eq(column, sourceId))) as ExpectedRowType[] // to get existingIds to work

        const existingIds = existingRelatedEntities.map(
            row => row[relatedEntityField],
        )
        // 2. Diff to get to-be-deleted and to-be-added IDs
        const toBeDeleted = existingIds.filter(
            id => id !== null && !relatedEntityIds.includes(id), // check if null should be included??
        )
    
        const toBeAdded = relatedEntityIds.filter(
            id => !existingIds.includes(id),
        )

        // 3. Delete old relations
        
        await this.db.transaction(async tx => {
            if (toBeDeleted.length) {
                ...
            }
            if (toBeAdded.length) {
                const payload: Record<string, string>[] = toBeAdded.map(id => ({
                    [sourceIdField]: sourceId,
                    [relatedEntityField]: id,
                }))
                const insertedRecords = await tx
                    .insert(joinTable)
                    .values(payload) // TODO: proper type?
                    .returning()

            }
        })
    }
async linkEntities<TJoinTable extends Table>(
        joinTable: TJoinTable,
        sourceIdField: keyof TJoinTable,
        relatedEntityField: keyof TJoinTable,
        sourceId: string,
        relatedEntityIds: string[],
    ) {
        // 1. Fetch existing related entity IDs

        const column = joinTable[sourceIdField] as Column // required to cast to satisfy where/eq

        type ExpectedRowType = {
            // maps over keys in the join table to be string or null
            [K in keyof TJoinTable]: string | null
        }

        const existingRelatedEntities = (await this.db
            .select()
            .from(joinTable)
            .where(eq(column, sourceId))) as ExpectedRowType[] // to get existingIds to work

        const existingIds = existingRelatedEntities.map(
            row => row[relatedEntityField],
        )
        // 2. Diff to get to-be-deleted and to-be-added IDs
        const toBeDeleted = existingIds.filter(
            id => id !== null && !relatedEntityIds.includes(id), // check if null should be included??
        )
    
        const toBeAdded = relatedEntityIds.filter(
            id => !existingIds.includes(id),
        )

        // 3. Delete old relations
        
        await this.db.transaction(async tx => {
            if (toBeDeleted.length) {
                ...
            }
            if (toBeAdded.length) {
                const payload: Record<string, string>[] = toBeAdded.map(id => ({
                    [sourceIdField]: sourceId,
                    [relatedEntityField]: id,
                }))
                const insertedRecords = await tx
                    .insert(joinTable)
                    .values(payload) // TODO: proper type?
                    .returning()

            }
        })
    }
image.png
Drizzle TeamJoin
The official Discord for all Drizzle related projects, such as Drizzle ORM, Drizzle Kit, Drizzle Studio and more!
11,879Members
Resources
Was this page helpful?

Similar Threads

Recent Announcements

Similar Threads

sqliteTable wrapper which modifies fields, with proper types
Drizzle TeamDTDrizzle Team / help
3y ago
Pagination proper TypeScript return types generics
Drizzle TeamDTDrizzle Team / help
2y ago
help with column builder types
Drizzle TeamDTDrizzle Team / help
3y ago
Help with types relational query function
Drizzle TeamDTDrizzle Team / help
3y ago