drizzle-orm
drizzle-orm copied to clipboard
Feat: infer type helpers for relations
close #695
- Added
InferManyRelationalResultandInferFirstRelationalResultgeneric types to infer the resulting object shape. - Added
db.query.<tableName>.$inferFindManyArgsanddb.query.<tableName>.$inferFindFirstArgsto infer the parameter offindManyandfindFirstrespectively. - Added type tests
Assuming you have the following schema:
export const posts = sqliteTable("posts", {
id: integer("id").primaryKey({ autoIncrement: true }),
content: text("content").notNull(),
authorId: integer("author_id").notNull(),
json: text("json", { mode: "json" })
.notNull()
.$type<{ hola: string; hey: number }>(),
});
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, { fields: [posts.authorId], references: [users.id] }),
}));
export const users = sqliteTable("users", {
id: integer("id").primaryKey({ autoIncrement: true }),
name: text("name").notNull(),
managerId: integer("manager_id").references((): AnySQLiteColumn => users.id),
});
export const usersRelations = relations(users, ({ many, one }) => ({
posts: many(posts),
manager: one(users, { fields: [users.managerId], references: [users.id] }),
}));
export const db = drizzle(sqlite, {
schema: { posts, users, usersRelations, postsRelations },
});
This is how you could use the new type helpers:
type UsersWithPosts = InferManyRelationalResult<
typeof schema,
'users',
{ with: { posts: true } }
>;
/* Resulting type */
type UserWithPosts = {
id: number;
name: string;
managerId: number;
posts: {
id: number;
content: string;
authorId: number | null;
json: { hola: string, hey: number };
}[];
}[]
type UsersManyArgument = typeof db.query.users.$inferFindManyArgs;
/* Resulting type */
type UsersManyArgument = {
columns?: {
id?: boolean | undefined;
name?: boolean | undefined;
managerId?: boolean | undefined;
} | undefined;
with?: <Super Long Type> | undefined;
extras?: Record<string, SQL.Aliased<unknown>> | ((fields: <Long Type>, operators: {
sql: typeof sql;
}) => Record<string, SQL.Aliased<unknown>>) | undefined;
where?: SQL<unknown> | ((fields: <Long Type>, operators: <Long Type>) => SQL<unknown> | undefined) | undefined;
orderBy?: ValueOrArray<SQL<unknown> | AnyColumn> | ((fields: <Long Type>, operators: {
sql: typeof sql;
asc: (column: SQLWrapper | AnyColumn) => SQL<unknown>;
desc: (column: SQLWrapper | AnyColumn) => SQL<unknown>;
}) => ValueOrArray<SQL<unknown> | AnyColumn>) | undefined;
limit?: number | Placeholder<string, any> | undefined;
offset?: number | Placeholder<string, any> | undefined;
}
The InferManyRelationalResult and InferFirstRelationalResult are also very helpful because after the first type parameter (typeof schema), the table name has intelisense and the arguments have intelisense as well.
Any timeline on this release? Would love to be also to use it!
@Angelelz does this also cover nested relations? i.e.
type UsersWithPosts = InferManyRelationalResult<
typeof schema,
'users',
{
with: {
posts: {
categories: true
}
}
}
>;
@Angelelz does this also cover nested relations?
Yeah, it looks like I didn't include a specific test for this, it will in fact work.
Hi guys,
Is there any update on this and when will could be potentially released?
Thanks for the great job!
any updates please ?
LGTM, you can merge it!
Does the documentation need to be updated somewhere as well? Or is that a different repo?
Is there anything blocking the pull request?
I really this feature to make things clean. Is there something more to do? I can contribute to it.