【发布时间】:2022-01-16 19:48:29
【问题描述】:
我在工厂工作,最终需要添加自定义方法。我无法使用 overloads 添加自定义方法,但是当我开始添加自定义方法时,一切都无法正常工作。 :(
我能够成功涵盖没有提供自定义方法的情况以及自定义方法参数类型错误的情况。
type Base = { id: string }
type Methods<T> = { [key: string]: (this: T) => unknown };
function factory<T extends Base>(method: (this: T) => void): (new () => T);
function factory<
T extends Base & M,
M extends Methods<T>
>(method: (this: T) => void, methods: M): (new () => T);
function factory<
T extends Base & M,
M extends Methods<T>
>(method: (this: T) => void, methods?: M): (new () => T) {
return null as unknown as (new () => T);
}
// Ok: T = Base
factory(function() {
this.id = this.a();
});
// Ok: 0 is not valid value for argument methods (we don't care about T in this case)
factory(function() {
this.id = this.a();
}, 0);
如果我将有效值传递给自定义方法参数,则没有任何效果! playground是一个检查问题详情的强大工具。
// Nothing working as desired
factory(function() {
this.id = this.a();
}, {
a: function(): string {
this.a();
this.b();
return "0";
}
});
如果我们鼠标悬停在factory函数名上,我们可以看到它的类型是:
function factory<Base & Methods<unknown>, {
a: (this: Base & Methods<unknown>) => string;
}>
所以我们可以这么说
type T = Base & Methods<unknown>
type M = { a: (this: Base & Methods<unknown>) => string; };
这就是问题所在:既然T 是某种东西,为什么M 被解析为Methods<unknown> 而不是Methods<something>?
还有很多其他问题(b方法不被认为是错误,a方法被认为返回unknown而不是string作为对象的a属性传递为methods论点等)但似乎它们都是错误的M类型解析的副作用。
我强烈怀疑所有这些问题的根本原因是T 和M 之间以及T 和自身之间的循环依赖关系,但我不能没有因为
-
T需要依赖M为其提供自定义方法; -
M需要依赖T来推断自定义方法的隐式 this 参数的类型。
知道如何实现这个吗?
【问题讨论】:
-
TypeScript 从左到右解析泛型。在这种情况下,我认为最好对其进行一些重构。首先,您需要推断所有方法,然后推断您的工厂函数。见here。所以我只是替换了参数。让我知道它是否有帮助
-
谢谢@captain-yossarian,差不多!仍然不起作用的是自定义方法在其中不可见:playground中的详细信息
标签: typescript