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

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 中报告的错误。线程中提到了一些解决方法,但我认为它们中的任何一个都不适用于我的情况。

这是 the Playground with the full code 。我也有 created a repository with 2 failing test cases that reproduce the problem 。我无法弄清楚如何使 .plugin().plugin().plugin().defaults() 的链接工作,或者是否可以使用今天的 TypeScript。我真的很感激任何帮助!

最佳答案

这是 the Playground with solution

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 的类型。

关于typescript - 链接静态 .plugin() 类方法以多次扩展实例 API,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58636914/

10-14 11:49