#typescript #database-connection #javascript-objects #knex.js #dotenv
Вопрос:
Я хочу написать в своем коде два разных соединения: одно предназначено для производства, а другое-для разработки. Я также хочу выбрать между этими соединениями с .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;
Но поступая таким образом, я получаю эту ошибку:
Элемент неявно имеет тип «любой», поскольку выражение типа «строка» не может использоваться для типа индекса » {производство: Knex<любой, неизвестный[]>; разработка: Knex<любой, неизвестный[]><любой, неизвестный[]>; }». В типе «{производство: Knex<любой, неизвестный[]>; разработка: Knex<любой, неизвестный[]><любой, неизвестный []>;} «не была найдена подпись индекса с параметром типа «строка».
Есть ли способ решить эту проблему? Если да, то как? А если нет, то как мне написать свой код?
Ответ №1:
Проблема в том, что компилятор знает только, что APP_MODE
это string
(или на самом деле string | undefined
), чего недостаточно для компилятора, чтобы быть уверенным, что это ключ connectionsList
. Насколько известно компилятору, APP_MODE === "testing"
, а затем вы ищете connectionsList.testing
то, чего не существует.
Вы можете либо явно протестировать APP_MODE
, после чего компилятор будет доволен:
if (APP_MODE !== "production" amp;amp; APP_MODE !== "development")
throw new Error("Uh oh, bad APP_MODE");
const connection = connectionsList[APP_MODE]; // okay
Или вы можете просто утверждать, что APP_MODE
это одно из этих двух значений, а не string
:
const connection = connectionsList[APP_MODE as "development" | "production"]; // okay
Явное тестирование безопаснее, чем утверждение (поскольку первое улавливает крайние случаи, а второе-нет), но оба способа позволяют компилятору знать, что APP_MODE
это можно рассматривать как ключ connectionsList
.
Комментарии:
1. Спасибо за ответ!