drizzle-orm icon indicating copy to clipboard operation
drizzle-orm copied to clipboard

[BUG]: TypeScript error for nested `select` expressions

Open emdede opened this issue 2 years ago • 1 comments

What version of drizzle-orm are you using?

0.25.3

What version of drizzle-kit are you using?

0.17.6

Describe the Bug

Using db.select() with intermediate key mappings breaks TS inference, but works fine during runtime.

E.g.:

const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: varchar('name')
})

const customers = pgTable('customers', {
  user: integer('user_id').references(() => users.id),
  name: varchar('name')
})

// Works fine
const result = db.select({
  name: users.name,
  customers
}).from(users).leftJoin(customers, eq(customers.user, users.id))

// TS Error
const result = db.select({
  name: users.name,
  intermediateLayer: {
    customers
  }
}).from(users).leftJoin(customers, eq(customers.user, users.id))

The result is correct, though. I could post the TS Error but it's really long with a bunch of ellipsis and not very informative afaict.

Expected behavior

No TS Error, so I can access the fields of my query result without problems.

Environment & setup

No response

emdede avatar May 01 '23 04:05 emdede

Changing SelectedFields to a mapped type solves it:

type SelectedFields<TColumn extends AnyColumn, TTable extends Table> = { [K: string]: SelectedFieldsFlat<TColumn>[string] | TTable | SelectedFieldsFlat<TColumn> | SelectedFields<TColumn, TTable> };

I don't know all the places where this needs to be changed so I won't be opening a PR.

emdede avatar May 03 '23 22:05 emdede

You need to use the spread operator for this case. Sorry for so late response on this issue

const result = db.select({
  name: users.name,
  intermediateLayer: {
    ...customers
  }
}).from(users).leftJoin(customers, eq(customers.user, users.id))

AndriiSherman avatar Jul 21 '23 17:07 AndriiSherman

@AndriiSherman I am trying something like below but it gives a type error. Although I get the expected result

const result = await db.select({
  ...users,
  intermediateLayer: {
    ...customers
  }
}).from(users).leftJoin(customers, eq(customers.user, users.id))

I want the result to be spread out in the first place. Like for eg., instead of having the users property in the result, I want the users property spread out.

Here's a screenshot. After the select() there are a bunch on innerJoins image

max-programming avatar Dec 22 '23 11:12 max-programming