How can I get a type from SelectedFields<MySqlColumn, Table>?

Hi guys sorry to bother buy I'm trying to build a Repository Pattern with Drizzle and I stuck with a type. The interface with I came up is
interface BaseRepository<T extends MySqlTable,
S extends SelectedFields<MySqlColumn, T>> {
findAll(): Promise<S[]>;
findById(id: number): Promise<S | null>;
create(data: InferInsertModel<T>): Promise<number>;
delete(id: number): Promise<void>;
findAllPaginated(page: number, limit: number, condition?: SQL<unknown>): Promise<Pagination<S>>;
}

export abstract class CrudRepository<
M extends MySqlTable & { id: SQLWrapper, deletedAt: SQLWrapper },
S extends SelectedFields<MySqlColumn, M>
> implements BaseRepository<M, S> {
// ....implementation
}

export const userTable = mysqlTable("user", {
id: int('id').primaryKey().autoincrement().notNull(),
email: varchar("email", { length: 255 }).notNull(),
password: varchar("password", { length: 255 }).notNull(),
name: varchar("name", { length: 255 }).notNull(),
deletedAt: timestamp("deleted_at"),
});

const userSelect = {
id: userTable.id,
email: userTable.email,
name: userTable.name,
};

export class UserRepository extends CrudRepository<typeof userTable, typeof userSelect> {
constructor(db: DbConnection) {
super(userTable, db, userSelect);
}
}

const userRepository = new UserRepository(db);

const allUsers = userRepository.findAll();
interface BaseRepository<T extends MySqlTable,
S extends SelectedFields<MySqlColumn, T>> {
findAll(): Promise<S[]>;
findById(id: number): Promise<S | null>;
create(data: InferInsertModel<T>): Promise<number>;
delete(id: number): Promise<void>;
findAllPaginated(page: number, limit: number, condition?: SQL<unknown>): Promise<Pagination<S>>;
}

export abstract class CrudRepository<
M extends MySqlTable & { id: SQLWrapper, deletedAt: SQLWrapper },
S extends SelectedFields<MySqlColumn, M>
> implements BaseRepository<M, S> {
// ....implementation
}

export const userTable = mysqlTable("user", {
id: int('id').primaryKey().autoincrement().notNull(),
email: varchar("email", { length: 255 }).notNull(),
password: varchar("password", { length: 255 }).notNull(),
name: varchar("name", { length: 255 }).notNull(),
deletedAt: timestamp("deleted_at"),
});

const userSelect = {
id: userTable.id,
email: userTable.email,
name: userTable.name,
};

export class UserRepository extends CrudRepository<typeof userTable, typeof userSelect> {
constructor(db: DbConnection) {
super(userTable, db, userSelect);
}
}

const userRepository = new UserRepository(db);

const allUsers = userRepository.findAll();
This is working fine but my problem is that the type of allUsers is
const allUsers: Promise<{
id: MySqlColumn<...>;
email: MySqlColumn<...>;
name: MySqlColumn<...>;
}[]>
const allUsers: Promise<{
id: MySqlColumn<...>;
email: MySqlColumn<...>;
name: MySqlColumn<...>;
}[]>
and I'm trying to get something like
const allUsers: Promise<{
id: number;
name: string;
email: string;
}>
const allUsers: Promise<{
id: number;
name: string;
email: string;
}>
So i want to do something like InferSelectModel<S> but I can't and I'm not sure how to do it, any hint on how can i solve it o what documentation can i read to understand a bit more and solve it? Thanks
11 Replies
Angelelz
Angelelz15mo ago
You'll have to use one of the internal drizzle types In this specific case, since you'll be selecting only single tables you could do it this way:
interface BaseRepository<
T extends MySqlTable,
S extends SelectedFields<MySqlColumn, T>,
> {
findAll(): Promise<SelectResult<S, "single", {}>[]>;
findById(id: number): Promise<SelectResult<S, "single", {}> | null>;
create(data: InferInsertModel<T>): Promise<number>;
delete(id: number): Promise<void>;
findAllPaginated(
page: number,
limit: number,
condition?: SQL<unknown>,
): Promise<SelectResult<S, "single", {}>[]>;
}

abstract class CrudRepository<
M extends MySqlTable & { id: SQLWrapper; deletedAt: SQLWrapper },
S extends SelectedFields<MySqlColumn, M>,
> implements BaseRepository<M, S>
{
constructor(
private table: M,
private db: DB,
private select: S,
) {}
findAll(): Promise<SelectResult<S, "single", {}>[]> {
throw new Error("Method not implemented.");
}
findById(id: number): Promise<SelectResult<S, "single", {}> | null> {
throw new Error("Method not implemented.");
}
create(data: InferInsertModel<M>): Promise<number> {
throw new Error("Method not implemented.");
}
delete(id: number): Promise<void> {
throw new Error("Method not implemented.");
}
findAllPaginated(
page: number,
limit: number,
condition?: SQL<unknown>,
): Promise<SelectResult<S, "single", {}>[]> {
throw new Error("Method not implemented.");
}
}
interface BaseRepository<
T extends MySqlTable,
S extends SelectedFields<MySqlColumn, T>,
> {
findAll(): Promise<SelectResult<S, "single", {}>[]>;
findById(id: number): Promise<SelectResult<S, "single", {}> | null>;
create(data: InferInsertModel<T>): Promise<number>;
delete(id: number): Promise<void>;
findAllPaginated(
page: number,
limit: number,
condition?: SQL<unknown>,
): Promise<SelectResult<S, "single", {}>[]>;
}

abstract class CrudRepository<
M extends MySqlTable & { id: SQLWrapper; deletedAt: SQLWrapper },
S extends SelectedFields<MySqlColumn, M>,
> implements BaseRepository<M, S>
{
constructor(
private table: M,
private db: DB,
private select: S,
) {}
findAll(): Promise<SelectResult<S, "single", {}>[]> {
throw new Error("Method not implemented.");
}
findById(id: number): Promise<SelectResult<S, "single", {}> | null> {
throw new Error("Method not implemented.");
}
create(data: InferInsertModel<M>): Promise<number> {
throw new Error("Method not implemented.");
}
delete(id: number): Promise<void> {
throw new Error("Method not implemented.");
}
findAllPaginated(
page: number,
limit: number,
condition?: SQL<unknown>,
): Promise<SelectResult<S, "single", {}>[]> {
throw new Error("Method not implemented.");
}
}
GabrielC
GabrielCOP15mo ago
that looks really good but I am no able to import that type on my code, i'm using drizzle-orm 0.28.6 how can i import that type?
GabrielC
GabrielCOP15mo ago
GitHub
drizzle-orm/drizzle-orm/src/query-builders/select.types.ts at a7dc7...
TypeScript ORM that feels like writing SQL. Contribute to drizzle-team/drizzle-orm development by creating an account on GitHub.
GabrielC
GabrielCOP15mo ago
how to import it in my code
GabrielC
GabrielCOP15mo ago
GitHub
[BUG]: Missing proper export for SelectResult · Issue #637 · drizzl...
What version of drizzle-orm are you using? 0.26.1 What version of drizzle-kit are you using? 0.18.1 Describe the Bug SelectResult is currently not exported from drizzle-orm/mysql-core or drizzle-or...
Angelelz
Angelelz15mo ago
import { SelectResult } from "drizzle-orm/query-builders/select.types"; That will get you out of the pinch while the issue is being resolved
GabrielC
GabrielCOP15mo ago
yes i tried that but is now working for me
GabrielC
GabrielCOP15mo ago
No description
Angelelz
Angelelz15mo ago
Yeah, it's a bug A workaround would be to just define the the type:
export type SelectResultField<T, TDeep extends boolean = true> = T extends Table
? Equal<TDeep, true> extends true
? SelectResultField<T["_"]["columns"], false>
: never
: T extends Column<any>
? GetColumnData<T>
: T extends SQL | SQL.Aliased
? T["_"]["type"]
: T extends Record<string, any>
? SelectResultFields<T, true>
: never;

export type SelectResultFields<
TSelectedFields,
TDeep extends boolean = true,
> = {
[Key in keyof TSelectedFields & string]: SelectResultField<
TSelectedFields[Key],
TDeep
>;
} & {};

export type SelectResult<TResult> = SelectResultFields<TResult>;
export type SelectResultField<T, TDeep extends boolean = true> = T extends Table
? Equal<TDeep, true> extends true
? SelectResultField<T["_"]["columns"], false>
: never
: T extends Column<any>
? GetColumnData<T>
: T extends SQL | SQL.Aliased
? T["_"]["type"]
: T extends Record<string, any>
? SelectResultFields<T, true>
: never;

export type SelectResultFields<
TSelectedFields,
TDeep extends boolean = true,
> = {
[Key in keyof TSelectedFields & string]: SelectResultField<
TSelectedFields[Key],
TDeep
>;
} & {};

export type SelectResult<TResult> = SelectResultFields<TResult>;
* This is a workaround, use it at your own risk
Dan
Dan15mo ago
looks like the type is not exported correctly. Could you create an issue on GH for that?
GabrielC
GabrielCOP15mo ago
hi @Dan Kochetov the issue is already created by another user https://github.com/drizzle-team/drizzle-orm/issues/637
GitHub
[BUG]: Missing proper export for SelectResult · Issue #637 · drizzl...
What version of drizzle-orm are you using? 0.26.1 What version of drizzle-kit are you using? 0.18.1 Describe the Bug SelectResult is currently not exported from drizzle-orm/mysql-core or drizzle-or...
Want results from more Discord servers?
Add your server