【发布时间】:2019-10-07 04:04:02
【问题描述】:
我有一个名为Mixin 的函数,它接受一个参数。参数应该是“类工厂混合”。
例如,假设我有这个类工厂 mixin 函数:
type Constructor<T = any, A extends any[] = any[]> = new (...a: A) => T
const CoolMixin = <T extends Constructor>(Base: T) => {
return class CoolMixin extends Base {
coolProp = 42
}
}
const CoolFoo = CoolMixin(class Foo {
foo = 'asdf'
})
const c = new CoolFoo()
// it works:
c.foo
c.coolProp
如您所见,它接受一个基类并返回一个新类,并且工作正常。
我有一个 Mixin 实用程序,它采用 mixin 函数,并为其提供了很酷的功能,例如支持 hasInstance、缓存基类的重复应用程序以及其他功能。
在纯 JavaScript 中,我可以这样使用它:
// Mixin returns an application of the Mixin function (a class) with
// a default base class applied (Object by default):
const CoolMixin = Mixin((Base) => {
return class CoolMixin extends Base {
coolProp = 42
}
})
// Here, CoolMixin is `class CoolMixin extends Object {...}`,
// so we can use it like a regular class:
let CoolFoo = class Foo extends CoolMixin {
foo = 'asdf'
}
// Mixin returns that class with a static `.mixin` property containing
// the original mixin function, so we can also use it as a mixin:
CoolFoo = CoolMixin.mixin(class Foo {
foo = 'asdf'
})
// either of the two versions will work the same:
const c = new CoolFoo()
c.foo
c.coolProp
因此,我的实用程序的便利性(除了缓存、hasInstance 等功能之外)是可以使用但最方便。这里还有两个例子:
// suppose One and Two are mixins created with my Mixin utility.
// Use regular extension:
class Foo extends One {...}
class Bar extends Two {...}
// or compose them together:
class Baz extends One.mixin(Two) {...}
所以,我想弄清楚如何在 TypeScript 中为这个 Mixin 实用程序进行输入。
我的第一次尝试是以下,它不起作用,但我认为它显示了我正在尝试做的事情的想法:
type Constructor<T = any, A extends any[] = any[]> = new (...a: A) => T
type MixinFunction = <TSub, TSuper>(base: Constructor<TSuper>) =>
Constructor<TSub & TSuper>
declare function Mixin<TSub, TSuper, T extends MixinFunction>(mixinFn: T):
Constructor<TSub & TSuper> & {mixin: T}
// Then using it like so:
const CoolMixinFunction = <T extends Constructor>(Base: T) => {
return class CoolMixin extends Base {
coolProp = 42
}
}
const CoolMixin = Mixin(CoolMixinFunction)
const CoolFoo = CoolMixin.mixin(class Foo {
foo = 'asdf'
}
const c = new CoolFoo()
c.foo
c.coolProp
const CoolBar = class Bar extends CoolMixin {
bar = 'asdf'
})
const b = new CoolBar()
b.bar
b.coolProp
正如您可能推断的那样,我正在尝试键入Mixin 工具,以便它接受一个mixin 函数,并且Mixin 调用的返回类型应该是一个从mixin 函数生成的类,并且返回的类还应该有一个 .mixin 属性,它与传入的 mixin 函数的类型相同。
我知道我做错了。我不清楚如何在这里使用类型推断。
似乎新的"Higher order function type inference" 功能在这里可能有用。
我怎样才能实现这种Mixin 实用程序输入?如果没有更高阶的功能,我可以做到吗?以及如何使用该功能?
【问题讨论】:
-
我的猜测是高阶支持将在 TS3.5 中得到更好的支持,它将合并 this pull request,因为您在这里专门查看构造函数类型。但这只是目前的猜测。
标签: typescript typescript-typings typescript-generics