drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
24.54k stars 643 forks source link

[BUG]: Type Error when using the .select method #1129

Closed sstefdev closed 11 months ago

sstefdev commented 1 year ago

What version of drizzle-orm are you using?

0.28.5

What version of drizzle-kit are you using?

0.19.12

Describe the Bug

When trying to use the .select method, Typescript is complaining about the arguments. So the error comes up when I always add any argument to the method.

The error that comes up: Expected 0 arguments, but got 1.ts(2554)

For example the code in question:

 const upvotedCount = await db
      .select({
        count: sql`COUNT(*)`,
      })
      .from(upvotesModel)
      .where(eq(upvotesModel.upvotedId, auditorProfile.id));

Expected behavior

No response

Environment & setup

No response

sifferhans commented 1 year ago

I get this as well using the SQLite driver. Which database driver are you using?

nasso commented 1 year ago

same, using mysql!

Angelelz commented 1 year ago

I can't reproduce. Can you put together a minimal reproduction repo?

mauriciabad commented 1 year ago

Same issue here.

I noticed that in my case the cause is that db variable is of the type:

const db: MySql2Database<typeof schema> | PlanetScaleDatabase<typeof schema>

Because I'm setting it up conditionally based on an env variable, this way I can test in local while developing.

import { drizzle as drizzleMysql } from 'drizzle-orm/mysql2'
import { drizzle as drizzlePlanetscale } from 'drizzle-orm/planetscale-serverless'

export const db =
  process.env.USE_LOCAL_DB === 'true'
    ? drizzleMysql(
        createConnection({
          host: '127.0.0.1',
          user: 'root',
          password: 'unsafePaswordOnlyForLocalhost',
          database: 'database',
        }),
        {
          schema,
          mode: 'planetscale',
        }
      )
    : drizzlePlanetscale(
        connect({
          host: env.DATABASE_HOST,
          username: env.DATABASE_USERNAME,
          password: env.DATABASE_PASSWORD,
        }),
        { schema }
      )

I didn't expect this would be an issue because planetscale is actually a mysql database. When I remove the condition, and leave just 1, the type error is gone.

I guess this is not the right way to setup two environments. How should I do it then?

sifferhans commented 1 year ago

@mauriciabad I have the same problem! I am using a local SQLite database in development, but a Turso database in production. Both are SQLite, or SQLite-ish (Turso is libsql, a fork of SQLite)

mauriciabad commented 1 year ago

The workaround I found is to add as unknown as PlanetScaleDatabase<typeof schema> on the Mysql declaration. It is not ideal, but at least if there are any errors due to wrong types it will be only in development.

import { drizzle as drizzleMysql } from 'drizzle-orm/mysql2'
import { drizzle as drizzlePlanetscale } from 'drizzle-orm/planetscale-serverless'

export const db =
  env.USE_LOCAL_DB === 'true'
    ? (drizzleMysql(
        createConnection({
          host: '127.0.0.1',
          user: 'root',
          password: 'unsafePaswordOnlyForLocalhost',
          database: 'descobreix-begur-app',
        }),
        {
          schema,
          mode: 'planetscale',
        }
      ) as unknown as PlanetScaleDatabase<typeof schema>) // <-- This line
    : drizzlePlanetscale(
        connect({
          host: env.DATABASE_HOST,
          username: env.DATABASE_USERNAME,
          password: env.DATABASE_PASSWORD,
        }),
        { schema }
      )
Angelelz commented 1 year ago

The workaround I found is to add as unknown as PlanetScaleDatabase<typeof schema> on the Mysql declaration. It is not ideal, but at least if there are any errors due to wrong types it will be only in development.

import { drizzle as drizzleMysql } from 'drizzle-orm/mysql2'
import { drizzle as drizzlePlanetscale } from 'drizzle-orm/planetscale-serverless'

export const db =
  env.USE_LOCAL_DB === 'true'
    ? (drizzleMysql(
        createConnection({
          host: '127.0.0.1',
          user: 'root',
          password: 'unsafePaswordOnlyForLocalhost',
          database: 'descobreix-begur-app',
        }),
        {
          schema,
          mode: 'planetscale',
        }
      ) as unknown as PlanetScaleDatabase<typeof schema>) // <-- This line
    : drizzlePlanetscale(
        connect({
          host: env.DATABASE_HOST,
          username: env.DATABASE_USERNAME,
          password: env.DATABASE_PASSWORD,
        }),
        { schema }
      )

This is a good workaround. The problem is that Typescript doesn't like calling methods that comes from unions, unless they're generic. Please take a look at this discord discussion for additional information