The type-check of partial-select doesn't work well

description On the code
import { sql } from "drizzle-orm";
import {
mysqlTable,
varchar,
} from "drizzle-orm/mysql-core";

const users = mysqlTable("users", {
id: varchar("id", { length: 255 }).notNull().primaryKey(),
name: varchar("name", { length: 255 })
});

export const getUsers = async () => {
const result = await db.select({
field1: users.id,
field2: users.name,
}).from(users);
const { field1, field2 } = result[0];
return result;
}
import { sql } from "drizzle-orm";
import {
mysqlTable,
varchar,
} from "drizzle-orm/mysql-core";

const users = mysqlTable("users", {
id: varchar("id", { length: 255 }).notNull().primaryKey(),
name: varchar("name", { length: 255 })
});

export const getUsers = async () => {
const result = await db.select({
field1: users.id,
field2: users.name,
}).from(users);
const { field1, field2 } = result[0];
return result;
}
ref: https://orm.drizzle.team/docs/select#partial-select I bumped into the type error.
Expected 0 arguments, but got 1.ts(2554)
Expected 0 arguments, but got 1.ts(2554)
drizzle-orm/mysql-core/db.d.ts
1. select(): MySqlSelectBuilder<undefined, TPreparedQueryHKT>;
2. select<TSelection extends SelectedFields>(fields: TSelection): MySqlSelectBuilder<TSelection, TPreparedQueryHKT>;
drizzle-orm/mysql-core/db.d.ts
1. select(): MySqlSelectBuilder<undefined, TPreparedQueryHKT>;
2. select<TSelection extends SelectedFields>(fields: TSelection): MySqlSelectBuilder<TSelection, TPreparedQueryHKT>;
I want to use 2, but type check is executed as 1. How can I fix this...?? Please help me. version
"@tidbcloud/serverless": "^0.2.0",
"drizzle-orm": "^0.32.1",
"@tidbcloud/serverless": "^0.2.0",
"drizzle-orm": "^0.32.1",
Drizzle ORM - Select
Drizzle ORM is a lightweight and performant TypeScript ORM with developer experience in mind.
10 Replies
rphlmr âš¡
rphlmr ⚡•4mo ago
👋 do you have strict mode set to true in your tsconfig?
monarisa
monarisaOP•4mo ago
Thank you for your comment. This is my tsconfig. And strict mode set to true, but even when set to false, I cannot solve the problem.
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/*"]
},
"types": [
"@cloudflare/workers-types/2023-07-01"
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
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/*"]
},
"types": [
"@cloudflare/workers-types/2023-07-01"
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
rphlmr âš¡
rphlmr ⚡•4mo ago
good, strict should always be true. I have tried with the same code and no error 😦
rphlmr âš¡
rphlmr ⚡•4mo ago
No description
rphlmr âš¡
rphlmr ⚡•4mo ago
I wonder what could cause that I have set up a nextjs project with @cloudflare/workers-types too, still no issues if you run next lint, do you also have this error or is it just in your editor?
monarisa
monarisaOP•4mo ago
Thank you for trying...!!! And when I use your code, it works. But my code is this. And I found out the global definition make it broken. (please try it again..??)
import { drizzle as drizzleTiDB } from "drizzle-orm/tidb-serverless";
import { drizzle as drizzleProxy } from "drizzle-orm/mysql-proxy";
import { connect } from "@tidbcloud/serverless";

declare global {
var _db: ReturnType<typeof drizzleTiDB> | ReturnType<typeof drizzleProxy> | undefined;
}

const getDb = () => {
if (process.env.NODE_ENV === "production") {
const client = connect({
url: "",
});
return drizzleTiDB(client);
} else {
return drizzleProxy(async (sql, params, method) => {
try {
const response = await fetch("http://localhost:8000/query", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sql, params, method }),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: any[] = await response.json();
return { rows: data };
} catch (e: any) {
console.error("Error from mysql proxy server: ", e.message);
return { rows: [] };
}
});
}
};

const db = globalThis._db || getDb()

if (process.env.NODE_ENV !== "production") {
globalThis._db = db;
}

export { db };

// normally I use the following code in other file.
export const getUsers = async () => {
const result = await db.select({
field1: users.id,
field2: users.name,
}).from(users);
const { field1, field2 } = result[0];
return result;
}
import { drizzle as drizzleTiDB } from "drizzle-orm/tidb-serverless";
import { drizzle as drizzleProxy } from "drizzle-orm/mysql-proxy";
import { connect } from "@tidbcloud/serverless";

declare global {
var _db: ReturnType<typeof drizzleTiDB> | ReturnType<typeof drizzleProxy> | undefined;
}

const getDb = () => {
if (process.env.NODE_ENV === "production") {
const client = connect({
url: "",
});
return drizzleTiDB(client);
} else {
return drizzleProxy(async (sql, params, method) => {
try {
const response = await fetch("http://localhost:8000/query", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sql, params, method }),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: any[] = await response.json();
return { rows: data };
} catch (e: any) {
console.error("Error from mysql proxy server: ", e.message);
return { rows: [] };
}
});
}
};

const db = globalThis._db || getDb()

if (process.env.NODE_ENV !== "production") {
globalThis._db = db;
}

export { db };

// normally I use the following code in other file.
export const getUsers = async () => {
const result = await db.select({
field1: users.id,
field2: users.name,
}).from(users);
const { field1, field2 } = result[0];
return result;
}
Actually I switch driver according to whether the env is local or production.(local: drizzleProxy, production: drizzleTiDB) And I use global variable because I don't want to make many db instances. What should I define the type of the global variable?? Or are there any other best practices?
rphlmr âš¡
rphlmr ⚡•4mo ago
declare global {
var _db: TiDBServerlessDatabase | undefined;
}

const getDb = () => {
if (process.env.NODE_ENV === "production") {
const client = connect({
url: "",
});
return drizzleTiDB(client);
} else {
if (global._db) {
return global._db;
}

const db = drizzleProxy(async (sql, params, method) => {
try {
const response = await fetch("http://localhost:8000/query", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sql, params, method }),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: any[] = await response.json();
return { rows: data };
} catch (e: any) {
console.error("Error from mysql proxy server: ", e.message);
return { rows: [] };
}
}) as unknown as TiDBServerlessDatabase;

global._db = db;
return db;
}
};

const db = getDb();

if (!db) {
throw new Error("db is not defined");
}

export { db };
declare global {
var _db: TiDBServerlessDatabase | undefined;
}

const getDb = () => {
if (process.env.NODE_ENV === "production") {
const client = connect({
url: "",
});
return drizzleTiDB(client);
} else {
if (global._db) {
return global._db;
}

const db = drizzleProxy(async (sql, params, method) => {
try {
const response = await fetch("http://localhost:8000/query", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sql, params, method }),
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: any[] = await response.json();
return { rows: data };
} catch (e: any) {
console.error("Error from mysql proxy server: ", e.message);
return { rows: [] };
}
}) as unknown as TiDBServerlessDatabase;

global._db = db;
return db;
}
};

const db = getDb();

if (!db) {
throw new Error("db is not defined");
}

export { db };
I see what your tried the SelectedFields are incompatible (not the same type) so TS can't infer the partial select at this point, it is safe to force cast the dev db client + I would store the db in global only in the else branch to prevent issues
monarisa
monarisaOP•4mo ago
Oh...!!! Thank you so much...!!! It works!! And what you care about storing the global db is amazing.
normausome
normausome•2mo ago
i'm getting a similar problem. i'm not really sure what it is. can you help me with this?
No description
No description
normausome
normausome•2mo ago
i want to select a certain property, but it's not letting me
Want results from more Discord servers?
Add your server