Я использую Proxy (), чтобы обеспечить «сохранение при изменении» для простого объекта настроек. Сам объект в конечном итоге представляется как простой объект, похожий на карту, так что вызов Settings.connectionString
возвращает то, чем является connectionString в файле JSON (или более поздней версии, Database), и затем сохраняется директива, такая как Settings.connectionCount = 2
обновленный connectionCount к базе данных и локальному объекту.
Мой инициализатор (и определение) выглядит следующим образом:
import * as fs from "fs";
import { EventEmitter } from "events";
// EventEmitter is so you can listen for the "SettingsLoaded" event rather than polling
class SettingsFactory extends EventEmitter {
public isLoaded:boolean = false;
public settings:Map<string, any>;
constructor() {
super();
// Initial load from file.
fs.readFile("settings.json", (err, data) => {
if (err) {
throw err;
}
const json = JSON.parse(data.toString());
for (const key in json) {
if (json.hasOwnProperty(key)) {
this.settings.set(key, json[key]);
}
}
// Database loading should go here, overriding the file values, but for now we can do without it.
this.isLoaded = true;
this.emit("SettingsLoaded", this);
});
}
}
const ProxiedSettings = new SettingsFactory();
// Doing this provides us with a singleton, which is nice.
export default new Proxy(ProxiedSettings, {
get: (target, name:string) => {
if (target.isLoaded) {
if (target.settings.has(name)) {
return target.settings.get(name);
} else {
return target[name];
}
} else {
throw new Error("Settings not loaded yet");
}
},
set: (target, name:string, value) => {
// update value
if (target.isLoaded) {
target.settings.set(name,value);
return true;
} else {
return false;
}
}
});
Как видите, экспортированный объект Proxy переопределяет get и setвозвращать значения из Map (), но при доступе к нему я получаю сообщение об ошибке: Property 'connectionString' does not exist on type 'SettingsFactory'
.
Я ожидаю, что смогу получить доступ (получить / установить) любое произвольное значение в настройках без проблем с помощью if (!target.settings.has(name)) { return target[name]; }
разрешает доступ к обработчику «on» EventEmitter, но сейчас я даже не захожу так далеко.
Любые идеи о том, как я могу сказать TypeScript, что Settings["*"]
существует в этом случае?