jeudi 16 janvier 2020

How to define a generic constructor in typescript under inheritance?

I am using typescript and want to write a factory function to create a new object instance and provide an array of properties to be filled. Basically a converter from an existing object to a new instance of another (related) type. It should be used like this

const newA = A.from({ a: 1 });
const newC = C.from({ a: 1, b: 2, c: 9 });

I have this working (member variables omitted for clarity and Object.create could be simpler, see below for the reason)

class A {
  static from(data: Partial<A>) : A {
    const o = Object.create(A);
    Object.assign(o, data);
    return o;
  }
}

This works nicely as long as I inherit from this class. I do not want to recreate this function anytime like so

class A {
  static from(data: Partial<A>) : A {
    const o = Object.create(A);
    Object.assign(o, data);
    return o;
  }
}

class B extends A {
static from(data: Partial<B>) : B {
    const o = Object.create(B);
    Object.assign(o, data);
    return o;
  }
}

The following snippet works, but I need to specify the class when I call it twice

class A {
  ...
  static from<T extends A>(data: Partial<T>) : T {
    const o = Object.create(this);
    Object.assign(o, data);
    return o;
  }
}

const newC = C.from<C>({ ... });

and want to use some form of generic, i.e. I imagine something like this.

class A {
  static from<T extends this>(data: Partial<T>) : A {
    const o = Object.create(this);
    Object.assign(o, data);
    return o;
  }
}

const new C = C.from({ ... });

I would guess that this is theoretically possible, since at compile time the context of the static function is known and you could infer the class type, but I did not figure out on how to use this inherited type in the signature definition.

Is this a good (acceptable) pattern and if not, what should I do?

Any help is appreciated!

Aucun commentaire:

Enregistrer un commentaire