您不需要为 Scale 函数声明显式返回类型,因为 TypeScript 很聪明,可以推断返回类型。将鼠标悬停在Scale 上,您会看到返回类型为
{
new (...args: any[]): Scaling;
prototype: Scale<any>.Scaling;
} & TBase
此外,如果您想为Scale 使用显式返回类型,您应该在Scale 函数之外声明Scaling(内部类)。像这样:
class Scaling extends Base {
_scale = 1;
setScale(scale: number) {
this._scale = scale;
}
get scale(): number {
return this._scale;
}
}
function Scale<TBase extends Constructor>(Base: TBase) {
return Scaling
}
但是Base 应该是静态的。
这意味着我们应该创建Mixin函数,就像在docs - Alternative Pattern中一样:
// credits goes to credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
type ClassType = new (...args: any[]) => any;
function Mixin<T extends ClassType, R extends T[]>(...classRefs: [...R]):
new (...args: any[]) => UnionToIntersection<InstanceType<[...R][number]>> {
return merge(class { }, ...classRefs);
}
function merge(derived: ClassType, ...classRefs: ClassType[]) {
classRefs.forEach(classRef => {
Object.getOwnPropertyNames(classRef.prototype).forEach(name => {
// you can get rid of type casting in this way
const descriptor = Object.getOwnPropertyDescriptor(classRef.prototype, name)
if (name !== 'constructor' && descriptor) {
Object.defineProperty(
derived.prototype,
name,
descriptor
);
}
});
});
return derived;
}
class Foo {
tag = 'foo'
}
class Scaling extends Mixin(Foo) {
_scale = 1;
setScale(scale: number) {
this._scale = scale;
}
get scale(): number {
return this._scale;
}
}
const result = new Scaling();
result.tag // string
result.scale // number
您可以在medium 和in my blog 中找到我的文章的分步说明。
UnionToIntersection - 创建联合类型的交集。您可以在answer中找到完整的解释
ClassType - 几乎与您的Constructor 相同。它是任何类构造函数的类型。
Mixin - 在 variadic tuple types 的帮助下推断参数中提供的每个类构造函数,并将其所有实例合并到一个对象 UnionToIntersection<InstanceType<[...R][number]>>。
`[...R][number]` - takes a union of all provided class intstances
`InstanceType<[...R][number]>>` - replace every class constructor in the union
with class instance accordingly
`UnionToIntersection<InstanceType<[...R][number]>>` - merges all class instances
merge - 与来自docs 的applyMixins 相同
更新
由于Scaling 是在函数内部定义的,因此不可能添加包含Scaling 的显式返回类型,因为它还不存在于作用域中。