Last active
November 3, 2023 17:19
-
-
Save wadefletch/668addf09e64c7bd162e87d270a4db0a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { eq } from "drizzle-orm"; | |
import { type DrizzleD1Database } from "drizzle-orm/d1"; | |
import { type GenericTable, project } from "./db/schema"; | |
// This is what I'd like to use, which is defined with my schema. | |
// (See import above, though the rest of the file shouldn't be relevant.) | |
// type GenericTable = typeof <tableA> | typeof <tableB> | ... | |
// I also tried this, but it doesn't work either. | |
// const Tables = { | |
// project, | |
// apiKey, // another sqliteTable from ./db/schema.ts | |
// } as const; | |
// type GenericTable = (typeof Tables)[keyof typeof Tables]; | |
// There isn't a type error when we avoid the union type and use a single table. | |
// type GenericTable = typeof project; | |
// Thanks for your help! | |
interface Reader<T extends GenericTable> { | |
// What's the difference between T["$inferSelect"] and InferSelectModel<T>? | |
findAll(): Promise<T["$inferSelect"][]>; | |
findOne(id: number): Promise<T["$inferSelect"] | undefined>; | |
} | |
export abstract class Repository<T extends GenericTable> implements Reader<T> { | |
constructor( | |
private readonly db: DrizzleD1Database, | |
private readonly table: T, | |
) {} | |
// 'T["$inferSelect"]' could be instantiated with an arbitrary type which could be unrelated to '{ [Key in keyof GetSelectTableSelection<T> & string]: SelectResultField<GetSelectTableSelection<T>[Key], true>; }'. | |
async findAll() { | |
return await this.db.select().from(this.table).all(); | |
} | |
// 'T["$inferSelect"]' could be instantiated with an arbitrary type which could be unrelated to '{ [Key in keyof GetSelectTableSelection<T> & string]: SelectResultField<GetSelectTableSelection<T>[Key], true>; }'. | |
async findOne(id: number) { | |
return (await this.db.select().from(this.table).where(eq(this.table.id, id)).execute()).at(0); | |
} | |
} | |
// Would it make a difference to pass the table type, rather than a generic? | |
// export class ProjectRepository extends Repository<typeof project> {} | |
class ProjectRepository<T extends GenericTable> extends Repository<T> {} | |
// Dummy DB, since we're not actually running this code, just type checking. | |
const db = null as unknown as DrizzleD1Database; | |
const projectRepository = new ProjectRepository(db, project); | |
const proj = await projectRepository.findOne(1); | |
console.log(proj); |
I couldn't make it work with an union, any reason why you want it like that?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Your problem is that your
GenericTable
is a union and Typescript is not sure if the$inferSelect
is correct, because it could be coming from any of those tables in your union. You have to find the common stuff in your tables and make the rest generic. I'll see if I can put together an example in a typescript playground so you can play with it.