【发布时间】:2021-04-16 15:59:40
【问题描述】:
我可以为下面的Mixin() 函数定义一个返回类型,该函数将解析为任何参数类型的交集类型吗?
function Mixin(...classRefs: any[]) {
return merge(class {}, ...classRefs);
}
function merge(derived: any, ...classRefs: any[]) {
classRefs.forEach(classRef => {
Object.getOwnPropertyNames(classRef.prototype).forEach(name => {
if (name !== 'constructor') {
Object.defineProperty(
derived.prototype,
name,
Object.getOwnPropertyDescriptor(classRef.prototype, name) as PropertyDescriptor
);
}
});
});
return derived;
}
class Foo {
foo() {}
}
class Bar {
bar() {}
}
class Baz {
baz() {
console.log('baz');
}
}
class MyClass extends Mixin(Foo, Bar, Baz) {}
const my = new MyClass();
my.baz();
如果没有展开运算符,使用泛型会相当简单。如何确保类型系统匹配实际发生的情况?
编辑:我修改了示例以匹配我实际使用的 mixin 函数。
编辑:两个后续问题:
- 如何确保
...classRefs中的所有类都扩展了一些公共基类?假设我创建了abstract class Mergable {},然后只能将后代传递给merge。 - 静态属性/函数呢?我添加了第二个循环来获取它们,但经过一些实验后,我不确定如何让类型系统意识到这一点:
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).forEach(name => {
const descriptor = Object.getOwnPropertyDescriptor(classRef, name);
if (name !== 'name' && name !== 'prototype' && name !== 'length' && descriptor) {
Object.defineProperty(
derived,
name,
descriptor
)
}
});
// Static Properties
Object.getOwnPropertyNames(classRef).forEach(name => {
// you can get rid of type casting in this way
const descriptor = Object.getOwnPropertyDescriptor(classRef.prototype, name)
if (name !== 'name' && name !== 'prototype' && name !== 'length' && descriptor) {
Object.defineProperty(
derived.prototype,
name,
descriptor
);
}
});
// Instance Properties
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;
}
【问题讨论】:
-
我不明白。 The code as written 出现运行时错误;
merged.baz()在 JavaScript 中不起作用。大概通过“按预期工作”你的意思是别的......你能把它设为minimal reproducible example,所以它实际上在运行时工作吗?如果问题只是“你能输入一个输出是输入交集的函数吗”,答案是yes。但我不认为这是extend()应该做的(因为构造签名的交集不构造实例的交集),也不是它在实践中所做的。救命! -
在我努力创建一个最小示例的过程中,我似乎弄坏了一些东西。将使用工作版本进行更新。
标签: typescript typescript-typings typescript-generics