我正在尝试创建一个类方法,该方法将使用给定的数据重建该类。
例如,
class A {
constructor (one, two) {...}
public static from(data: A): A {
return Object.assign(new A(), data);
}
}
然后执行类似的操作:
let someObj = A.from({one: 'hello', two: 'world'}
这很好。但是,现在我想使此方法通用,以任何类调用它。
我已经尝试过
export function from<T>(type: { new (): T }, input: T): T {
return Object.assign(new type(), input);
}
但是问题是,如果类在构造函数中需要参数,则将无法正常工作。
我该如何实现?
您可以使用Object.create
创建具有指定原型的对象,而无需调用构造函数。通过将对象的原型设置为type.prototype
,它将成为类type
的实例,因此它将具有该类定义的方法,就像调用new type()
一样。
function from<T>(type: { new(...args: any[]): T }, input: T): T { return Object.assign(Object.create(type.prototype), input); }
必须说,这是对封装的明显违反,因此您必须保证将只使用它来创建具有有效内部状态的对象。由于未调用构造函数,因此对象没有机会验证其自身的状态。
示例:
来解决此问题class A { constructor(public x: number) { } getX() { return this.x; } } var a = new A(1); var b = from(A, a); var c = from(A, { x: 4 }); // type error here, unfortunately. console.log(b.getX()); // logs 1 console.log(c.getX()); // logs 4
不幸的是,类型注释
input: T
导致编译器抱怨参数{ x: 4 }
不具有getX
实例应具有的A
属性。我们可以通过构造a mapped type which excludes the methods:
type FieldsOf<T> = Pick<T, { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]>;
function from<T>(type: { new(...args: any[]): T }, input: FieldsOf<T>): T {
return Object.assign(Object.create(type.prototype), input);
}