drizzle-team / drizzle-team/drizzle-orm
[BUG]: Composition of not and or/and yields compile error
- 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?
0.39.3
### What version of `drizzle-kit` are you using?
0.30.4
### Other packages
_No response_
### Describe the Bug
I have this function:
```
// undeletable sessions
const DEFAULT_SESSION_NAME = "Default Session";
const BASE_SESSION_NAME = "Base Scramble";
export async function deleteSession(userId: number, sessionId: number) {
await db.delete(dbSessions).where(
and(
eq(dbSessions.id, sessionId),
eq(dbSessions.userId, userId),
not(
or(
eq(dbSessions.name, DEFAULT_SESSION_NAME),
eq(dbSessions.name, DAILY_SCRAMBLE_SESSION_NAME)
)
)
)
);
}
```
This throws the compile error:
```
./sessions.ts:32:9
Type error: Argument of type 'SQL | undefined' is not assignable to parameter of type 'SQLWrapper'.
Type 'undefined' is not assignable to type 'SQLWrapper'.
30 | eq(dbSessions.userId, userId),
31 | not(
> 32 | or(
| ^
33 | eq(dbSessions.name, DEFAULT_SESSION_NAME),
34 | eq(dbSessions.name, DAILY_SCRAMBLE_SESSION_NAME)
35 | )
```
I would assume that composing `not` and `or` like this should work. It also breaks for `and`.
I have this `tsconfig.json`:
```
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
```
The `strict` flag is set, but i this should still work even with the flag set, shouldn't it?
For reproducability here is the relevant schema.ts:
```
export const sessions = pgTable("sessions", {
id: serial("id").primaryKey(),
userId: integer("userId").references(() => users.id, { onDelete: "cascade" }).notNull(),
name: text("name").notNull().default(""),
}, (table) => ({
namePerUserUnique: uniqueIndex().on(table.name, table.userId),
}));
```
This issue can be easily overcome by utilizing De Morgan’s Law:
```
await db.delete(dbSessions).where(
and(
eq(dbSessions.id, sessionId),
eq(dbSessions.userId, userId),
ne(dbSessions.name, DEFAULT_SESSION_NAME),
ne(dbSessions.name, DAILY_SCRAMBLE_SESSION_NAME)
)
);
```
But i would still like to be able to rewrite it to the first form for better readability.
Contributor guide
Research direction
The reproduction is in sessions.ts and the schema example is in schema.ts; start by locating the TypeScript definitions and return types of not, or, and and under strict mode. Reproduce the error with the supplied tsconfig.json, then verify that both nested compositions compile without producing SQLWrapper | undefined.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, typescript
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100