Typescript generi c сопоставленный тип, сохраняющий пару ключ-значение - PullRequest
1 голос
/ 10 марта 2020

Предположим, я пишу библиотеку, которая позволяет пользователю обрабатывать какие-то объекты. У объекта может быть определено свойство строки type, и я хотел бы иметь возможность расширять библиотеку с помощью плагинов, которые дополнительно обрабатывают объекты с указанным типом c. Давайте проиллюстрируем это следующим кодом:

type Entry = {
  [key: string]: any;
};

type TypedEntry<T extends string> = Entry & {
  type: T;
};

type PluginDefinition<T extends string = any> = {
  type: T;
  process(entry: TypedEntry<T>): void;
};

class Library {
  private plugins: Record<string, PluginDefinition> = {};

  registerPlugin(plugin: PluginDefinition): void {
    this.plugins[plugin.type] = plugin;
  }

  getPlugin<T extends string>(type: T): PluginDefinition<T> {
    return this.plugins[type];
  }
}

Пока это работает, но это не оптимально - например, это не ошибка:

this.plugins['foo'] = {
  type: 'bar',
  process(entry) {},
};

Также единственная причина, по которой getPlugin метод не выбрасывает ошибки, он видит this.plugins[whatever] как PluginDefinition<any>, что удовлетворяет PluginDefinition<T>.

Обе эти проблемы связаны с тем, что я не могу переписать this.plugins как сопоставленный тип, потому что на данном этапе нет известного списка типов и, следовательно, нечего отображать. Но в теории ни одна из этих двух проблем не касается, в частности, того, какими будут фактические типы, просто то, что ключ соответствует свойству type значения.

Есть ли способ переписать Record<string, PluginDefinition> и Ко. так что эти две проблемы исчезают в пустоте или, возможно, никогда? Я одинаково счастлив с любым из них.

...