使用构造函数中的参数重建通用类

问题描述 投票:2回答:1

我正在尝试创建一个类方法,该方法将使用给定的数据重建该类。

例如,

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);
}

但是问题是,如果类在构造函数中需要参数,则将无法正常工作。

我该如何实现?

typescript
1个回答
0
投票

您可以使用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);
}

Playground Link

© www.soinside.com 2019 - 2024. All rights reserved.