有没有办法用 TypeScript 中的对象文字来组织我的数据库连接?
Is there a way to organize my database connections with object literals in TypeScript?
我想在我的代码中写两个不同的连接:一个用于生产,另一个用于开发。我还想在这些连接与 .env
文件之间进行选择。我尝试了几种方法,找到了这个解决方案:
// Modules
import dotenv from "dotenv";
import knex from "knex";
// Environment variables
dotenv.config();
const { PG_HOST, PG_PORT, PG_USER, PG_PASSWORD, PG_DB, IS_APP_IN_PRODUCTION } = process.env;
// Connections
const connectionsList = [
knex({
client: "pg",
connection: {
host: PG_HOST,
port: (PG_PORT as any),
user: PG_USER,
password: PG_PASSWORD,
database: PG_DB
}
}),
knex({
client: "sqlite3",
connection: {
filename: "./development/dev.sqlite3",
database: "dev-db"
}
})
];
// Setting the connection
const connection = connectionsList[IS_APP_IN_PRODUCTION == "true" ? 0 : 1];
// Export
export default connection;
这有效并解决了我的问题,但在我看来,这不是最佳解决方案。我不喜欢使用数组来组织连接的想法;因此,我的第一个尝试是使用对象文字来组织,以这种方式:
// Modules
import dotenv from "dotenv";
import knex from "knex";
// Environment variables
dotenv.config();
const { PG_HOST, PG_PORT, PG_USER, PG_PASSWORD, PG_DB, APP_MODE } = process.env;
// Connections
const connectionsList = {
production: knex({
client: "pg",
connection: {
host: PG_HOST,
port: (PG_PORT as any),
user: PG_USER,
password: PG_PASSWORD,
database: PG_DB
}
}),
development: knex({
client: "sqlite3",
connection: {
filename: "./development/dev.sqlite3",
database: "dev-db"
}
})
};
// Setting the connection
const connection = connectionsList[APP_MODE as string]; // APP_MODE is a string that can be "production" or "development"
// Export
export default connection;
但是这样做会给我这个错误:
The element implicitly has a type 'any' because the expression of type 'string' cannot be used for the index type '{ production: Knex<any, unknown[]>; development: Knex<any, unknown[]>; }'.
No index signature with a parameter of type 'string' was found in type '{ production: Knex<any, unknown[]>; development: Knex<any, unknown[]>; }'.
有没有办法解决这个问题?如果是,如何?如果不是,我应该如何编写代码?
问题是编译器只知道APP_MODE
是一个string
(或者实际上是string | undefined
),这不足以让编译器确定它是一个connectionsList
的键。就编译器所知,APP_MODE === "testing"
,然后您正在查找不存在的 connectionsList.testing
。
您可以显式测试 APP_MODE
,之后编译器会很高兴:
if (APP_MODE !== "production" && APP_MODE !== "development")
throw new Error("Uh oh, bad APP_MODE");
const connection = connectionsList[APP_MODE]; // okay
或者,您可以 assert APP_MODE
是这两个值之一,而不是 string
:
const connection = connectionsList[APP_MODE as "development" | "production"]; // okay
显式测试比断言更安全(因为前者捕获边缘情况而后者不捕获),但两种方式都让编译器知道 APP_MODE
可以被视为 connectionsList
的键.
我想在我的代码中写两个不同的连接:一个用于生产,另一个用于开发。我还想在这些连接与 .env
文件之间进行选择。我尝试了几种方法,找到了这个解决方案:
// Modules
import dotenv from "dotenv";
import knex from "knex";
// Environment variables
dotenv.config();
const { PG_HOST, PG_PORT, PG_USER, PG_PASSWORD, PG_DB, IS_APP_IN_PRODUCTION } = process.env;
// Connections
const connectionsList = [
knex({
client: "pg",
connection: {
host: PG_HOST,
port: (PG_PORT as any),
user: PG_USER,
password: PG_PASSWORD,
database: PG_DB
}
}),
knex({
client: "sqlite3",
connection: {
filename: "./development/dev.sqlite3",
database: "dev-db"
}
})
];
// Setting the connection
const connection = connectionsList[IS_APP_IN_PRODUCTION == "true" ? 0 : 1];
// Export
export default connection;
这有效并解决了我的问题,但在我看来,这不是最佳解决方案。我不喜欢使用数组来组织连接的想法;因此,我的第一个尝试是使用对象文字来组织,以这种方式:
// Modules
import dotenv from "dotenv";
import knex from "knex";
// Environment variables
dotenv.config();
const { PG_HOST, PG_PORT, PG_USER, PG_PASSWORD, PG_DB, APP_MODE } = process.env;
// Connections
const connectionsList = {
production: knex({
client: "pg",
connection: {
host: PG_HOST,
port: (PG_PORT as any),
user: PG_USER,
password: PG_PASSWORD,
database: PG_DB
}
}),
development: knex({
client: "sqlite3",
connection: {
filename: "./development/dev.sqlite3",
database: "dev-db"
}
})
};
// Setting the connection
const connection = connectionsList[APP_MODE as string]; // APP_MODE is a string that can be "production" or "development"
// Export
export default connection;
但是这样做会给我这个错误:
The element implicitly has a type 'any' because the expression of type 'string' cannot be used for the index type '{ production: Knex<any, unknown[]>; development: Knex<any, unknown[]>; }'. No index signature with a parameter of type 'string' was found in type '{ production: Knex<any, unknown[]>; development: Knex<any, unknown[]>; }'.
有没有办法解决这个问题?如果是,如何?如果不是,我应该如何编写代码?
问题是编译器只知道APP_MODE
是一个string
(或者实际上是string | undefined
),这不足以让编译器确定它是一个connectionsList
的键。就编译器所知,APP_MODE === "testing"
,然后您正在查找不存在的 connectionsList.testing
。
您可以显式测试 APP_MODE
,之后编译器会很高兴:
if (APP_MODE !== "production" && APP_MODE !== "development")
throw new Error("Uh oh, bad APP_MODE");
const connection = connectionsList[APP_MODE]; // okay
或者,您可以 assert APP_MODE
是这两个值之一,而不是 string
:
const connection = connectionsList[APP_MODE as "development" | "production"]; // okay
显式测试比断言更安全(因为前者捕获边缘情况而后者不捕获),但两种方式都让编译器知道 APP_MODE
可以被视为 connectionsList
的键.