假设我正在编写一个库,该库允许用户处理某种对象。该对象可能定义了字符串type
属性,并且我希望能够使用可以进一步处理特定类型对象的插件来扩展该库。让我们用一些代码来说明:
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
重写为映射类型这一事实,因为在此阶段尚无类型的已知列表,因此没有要映射的内容。但是从理论上讲,这两个问题都没有特别在乎 actual 类型是什么,只是键符合值的type
属性。
有什么方法可以重写Record<string, PluginDefinition>
&co。从而使这两个问题消失在虚无之中,或者甚至永远消失?我对其中任何一个都感到满意。