2 votes

TypeScript : factory avec méthodes personnalisées - 3ème étape

Je travaille sur une usine ; j'ai besoin d'ajouter éventuellement des méthodes personnalisées. cette réponse y cette réponse nous avons réussi à le faire fonctionner presque comme prévu.

Presque parce qu'il ne fonctionne qu'avec les méthodes sans tout argument requis ; si nous essayons d'ajouter une méthode avec au moins un argument requis, nous obtenons une erreur de compilation.

J'ai essayé d'ajouter un tableau d'arguments de repos à la fois à la déclaration de l'option method argument et M (voir ci-dessous) mais cela n'aide que lors de l'appel des méthodes.

(this: E & S, ...args: unknonwn[]) => unknown

type Base = { id: string }
type Factory<E> = new () => E;

function factory<E extends Base>(name: string): Factory<E>;
function factory<E extends Base, M extends Record<string, <S extends M>(this: E & S, ...args: unknown[]) => unknown>>(
  name: string, methods: M & Record<string, ((this: E & M, ...args: unknown[]) => void)>
): Factory<E & M>;
function factory<E extends Base, M extends Record<string, <S extends M>(this: E & S) => unknown>>(
  name: string, methods?: M
): Factory<E> {
  const ret = function (this: Base) {
    this.id = "0"
  };

  Object.defineProperty(ret, "name", { value: name });

  if (methods) for (const method in methods) Object.defineProperty(ret.prototype, method, { value: methods[method] });

  return ret as unknown as Factory<E>;
}

const T1 = factory("T1");
const t1 = new T1();
console.log(t1, t1.id);

const T2 = factory(
  "T2",
  {
    foo: function (repeat: boolean) {
      const ret = ! repeat;
      if(repeat) this.foo(ret);
      return ret;
    }
  },
);
const t2 = new T2();
console.log(t2, t2.id, t2.foo(true));

Voici un terrain de jeux pour faire des expériences.

2voto

Serhii Bilyk Points 9

Veuillez considérer cet exemple qui représente votre cas d'utilisation :

const foo = (fn: (a: unknown) => unknown) => fn

foo((arg: number) => arg) // error

L'erreur : Type 'unknown' is not assignable to type 'number'

Veuillez consulter docs inconnus :

Tout est cessible à unknown mais unknown n'est pas assignable à autre chose que lui-même et n'importe qui sans une assertion de type ou une restriction basée sur le flux de contrôle.

Alors, pourquoi avons-nous une erreur si Anything is assignable to inconnu " ?

Voir ça :

const bar = (a: unknown) => a
bar(42) // ok

On dirait que quelque chose ne va pas ici. Non, ce n'est pas le cas. C'est à cause de contravariance . Dans le premier exemple, l'argument a est en position contravariante. Cela signifie que la flèche de l'héritage pointe dans la direction opposée. Veuillez consulter este répondre à l'aide de quelques exemples simples et este réponse.

Tout ce que vous avez à faire, c'est de changer unknown a any . Ne vous inquiétez pas, cela n'enlève rien à la sécurité de votre code. En fait, vous n'avez aucune restriction spécifique pour methods .

Solution :

type Base = { id: string }
type Factory<E> = new () => E;

function factory<E extends Base>(name: string): Factory<E>;

function factory<E extends Base, M extends Record<string, <S extends M>(this: E & S, ...args: any[]) => any>>(
  name: string, methods: M & Record<string, ((this: E & M, ...args: any[]) => void)>
): Factory<E & M>;

function factory<E extends Base, M extends Record<string, <S extends M>(this: E & S, ...args: any[]) => any>>(
  name: string, methods?: M
): Factory<E> {
  const ret = function (this: Base) {
    this.id = "0"
  };

  Object.defineProperty(ret, "name", { value: name });

  if (methods) for (const method in methods) Object.defineProperty(ret.prototype, method, { value: methods[method] });

  return ret as unknown as Factory<E>;
}

const T1 = factory("T1");
const t1 = new T1();
console.log(t1, t1.id);

const T2 = factory(
  "T2",
  {
    foo: function (repeat: boolean) {
      const ret = !repeat;
      if (repeat) {
        this.foo(ret);
      }
      return ret;
    }
  },
);
const t2 = new T2();
console.log(t2, t2.id, t2.foo(true));

Terrain de jeux

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X