Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/dynamic/table-similarity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { AnyColumn } from '../util/type-utils.js'

export type TableSimilarity<DB, C extends AnyColumn<DB, keyof DB>> = {
TB: SimilarTables<DB, C>
DB: DatabaseWithSimilarTables<DB, C>
}

export type SimilarTables<DB, C extends AnyColumn<DB, keyof DB>> = {
[T in keyof DB]: HasEveryColumn<DB, T, C>
}[keyof DB]

export type HasEveryColumn<DB, TB extends keyof DB, C> = [C] extends [
keyof DB[TB],
]
? TB
: never

export type DatabaseWithSimilarTables<
DB,
C extends AnyColumn<DB, keyof DB>,
> = Omit<DB, SimilarTables<DB, C>> & {
[T in SimilarTables<DB, C>]: Pick<DB[T], keyof DB[SimilarTables<DB, C>]>
}

export type ScopedTableSimilarity<
DB,
TB extends keyof DB,
C extends AnyColumn<DB, TB>,
> = {
TB: ScopedSimilarTables<DB, TB, C>
DB: DatabaseWithScopedSimilarTables<DB, TB, C>
}

export type ScopedSimilarTables<
DB,
TB extends keyof DB,
C extends AnyColumn<DB, TB>,
> = {
[T in TB]: HasEveryColumn<DB, T, C>
}[TB]

export type DatabaseWithScopedSimilarTables<
DB,
TB extends keyof DB,
C extends AnyColumn<DB, TB>,
> = Omit<DB, ScopedSimilarTables<DB, TB, C>> & {
[T in ScopedSimilarTables<DB, TB, C>]: Pick<
DB[T],
keyof DB[ScopedSimilarTables<DB, TB, C>]
>
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export * from './schema/drop-view-builder.js'
export * from './schema/alter-column-builder.js'

export * from './dynamic/dynamic.js'
export * from './dynamic/table-similarity.js'

export * from './driver/driver.js'
export * from './driver/database-connection.js'
Expand Down
35 changes: 35 additions & 0 deletions test/typings/test-d/table-similarity.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expectError } from 'tsd'
import {
Expression,
expressionBuilder,
Kysely,
Selectable,
SelectQueryBuilder,
SelectType,
TableSimilarity,
} from '..'
import { Database } from '../shared'

async function test(db: Kysely<Database>) {
type NameSimilarity = TableSimilarity<Database, 'name'>

function selectByName<TB extends NameSimilarity['TB']>(
table: TB,
name: SelectType<NameSimilarity['DB'][TB]['name']>,
): Expression<Selectable<Database[TB]>> {
const eb = expressionBuilder<NameSimilarity['DB'], never>()

return eb
.selectFrom(db.dynamic.table<NameSimilarity['TB']>(table).as('t'))
.where('t.name', '=', name)
.selectAll() as never
}

selectByName('book', "The Hitchhiker's Guide to the Galaxy")
selectByName('pet', 'Fido')

// doesn't have a name column
expectError(selectByName('person', 'John Doe'))
// name is a string, not a number
expectError(selectByName('book', 2))
}