drizzle-team / drizzle-team/drizzle-orm
[BUG]: Relational query where clause incompatible with branded/nominal types via `$type<>()`
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
### Report hasn't been filed before.
- [x] I have verified that the bug I'm about to report hasn't been filed before.
### What version of `drizzle-orm` are you using?
1.0.0-beta.12
### What version of `drizzle-kit` are you using?
1.0.0-beta.12
### Other packages
_No response_
### Describe the Bug
When using `$type<>()` to add branded types to columns (e.g., for type-safe IDs), the relational query API's where clause rejects the values with type errors.
### Schema:
```ts
type TypeId = string & { readonly __brand: T }
const users = pgTable("users", {
id: text("id").$type>().primaryKey(),
// ...
})
const members = pgTable("members", {
userId: text().$type>().notNull(),
// ...
})
```
### Query:
```ts
const user: { id: TypeId<"user"> } = /* ... */
db.query.members.findFirst({
where: { userId: user.id } // Error!
})
```
### Error:
```
Type 'TypeId<"user">' is not assignable to type 'RelationsFieldFilter> | undefined'.
```
### Workaround:
Cast with as {}
```ts
db.query.members.findFirst({
where: { userId: user.id } as {}
})
```
### Notes:
- The standard query builder works fine: eq(members.userId, user.id)
- Casting to string doesn't help - the filter rejects both the branded type AND the base string type
Contributor guide
Research direction
Start by reproducing the TypeScript example with pgTable, branded $type<> columns, and db.query.members.findFirst({ where: { userId: user.id } }); compare it with the working eq(members.userId, user.id) query. Trace the relational query where filter types and verify that branded and base string values are accepted without the {} workaround, while the standard query builder remains working.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, typescript
- Domain
- database
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100