首页 > 解决方案 > 链接静态 .plugin() 类方法以多次扩展实例 API

问题描述

我有一个插件架构,我允许我这样做

const fooPlugin = () => ({ foo: 'foo' })
const barPlugin = () => ({ bar: 'bar' })

const BaseWithPlugin = Base.plugin(fooPlugin)
const baseWithPlugin = new BaseWithPlugin()
baseWithPlugin.foo // ✅ string

const BaseWithPlugins = Base.plugin([fooPlugin, barPlugin])
const baseWithPlugins = new BaseWithPlugins()
baseWithPlugins.foo // ✅ string
baseWithPlugins.bar // ✅ string

但它无法做到这一点

const BaseWithPlugins2 = Base.plugin(fooPlugin).plugin(barPlugin)
const baseWithPlugins2 = new BaseWithPlugins2()
baseWithPlugins2.foo // ❌ Property 'foo' does not exist on type 'plugin<() => { bar: string; }>.BaseWithPlugins & { bar: string; }'.
baseWithPlugins2.bar // ✅ string

如果我创建另一个扩展BaseWithPlugin并具有与静态方法完全相同的实现的类plugin,我会得到预期的结果

class Workaround extends BaseWithPlugin {
  static plugin<T extends TestPlugin | TestPlugin[]>(plugin: T) {
    const currentPlugins = this.plugins;

    const WorkaroundWithPlugins = class extends this {
      static plugins = currentPlugins.concat(plugin);
    };

    type Extension = ReturnTypeOf<T>;
    return WorkaroundWithPlugins as typeof WorkaroundWithPlugins & Constructor<Extension>;
  }
}

const BaseWithPlugins3 = Workaround.plugin(barPlugin)
const baseWithPlugins3 = new BaseWithPlugins3()
baseWithPlugins3.foo // ✅ string
baseWithPlugins3.bar // ✅ string

我希望找到一种不需要这种解决方法的方法。这看起来像microsoft/TypeScript#5863中报告的错误。线程中提到了一些解决方法,但我认为它们中的任何一个都不适用于我的情况。

这是带有完整代码的游乐场。我还创建了一个存储库,其中包含 2 个重现问题的失败测试用例。我无法弄清楚如何进行链接.plugin().plugin().plugin().defaults()工作,或者今天的 TypeScript 是否有可能。我真的很感激任何帮助!

标签: typescript

解决方案


这是带有解决方案的游乐场

class Base {
  static plugin<S extends Constructor<any> & { plugins: any[] }, T extends TestPlugin | TestPlugin[]>(this: S, plugin: T) {
    const currentPlugins = this.plugins;

    const BaseWithPlugins = class extends this {
      static plugins = currentPlugins.concat(plugin);
    };

    type Extension = ReturnTypeOf<T>;
    return BaseWithPlugins as typeof BaseWithPlugins & Constructor<Extension>;
  }
}

您缺少的部分是您应该让plugin静态函数也推断this.


推荐阅读