Búsqueda de sitios web

¿Es un antipatrón de TypeScript llamar dinámicamente a una función miembro almacenada en un literal?


En mi clase de componente de Angular tengo el siguiente patrón utilizado para manejar eventos:

private keyHandlers = {
  'ArrowDown': function ($event) {
    this.handleArrowDown($event);
  },

  'ArrowUp': function ($event) {
    this.handleArrowUp($event);
  },
};

y luego un @HostListener de la siguiente manera:

@HostListener('keydown', ['$event'])
  onKeyDown($event: KeyboardEvent) {
    if (typeof this.kbdHandlers[$event.code] === 'function') {
      this.keyHandlers[$event.code]($event);
    }
  }

Luego, más abajo tengo esos manejadores individuales especificados como miembros privados de la clase:

private handleArrowDown($event) {
  // ...
}

private handleArrowUp($event) {
    // ...
}

Sin embargo, la regla "noUnusedLocals": true, parece no gustarle, quejándose de que los métodos handleArrow* nunca se usan. Así que mi pregunta es: ¿se considera este tipo de enfoque un antipatrón en TypeScript, o hay alguna manera de satisfacer al compilador y notar estos miembros?

Respuesta #1

La respuesta es sí y no.

TypeScript no fomenta la referencia dinámica ya que no puede analizar tu código y detectar dicho uso. Por lo tanto, desafortunadamente, se quejará en este caso.

Tiene la buena intención de ayudarte, pero no está haciendo lo correcto. O dicho de otra manera, no tiene suficiente conocimiento para hacer lo correcto.

Por otro lado, definitivamente no debería "prohibir" dicho uso porque TypeScript es JavaScript. Por lo tanto, debería haber una manera de mitigar esta situación.

De hecho, está en una discusión: https://github.com/Microsoft/TypeScript/issues/9448

Por ahora, recomendaría desactivar noUnusedLocals (lo sé, duele. Y duele de cualquier manera).

Señalado por @jmlopez, aquí hay dos soluciones alternativas:

export class SomeComponent {
  private keyHandlers = {
    // Specifying `this` will be processed by the compiler to make the function as used.
    'ArrowDown': function (this: SomeComponent, $event) {
      this.handleArrowDown($event);
    },
    // Arrow function will have the same effect.
    'ArrowUp': ($event) => {
      this.handleArrowUp($event);
    }
  }
  onKeyDown($event) {
    if (typeof this.keyHandlers[$event.code] === 'function') {
      this.keyHandlers[$event.code]($event);
    }
  }
  private handleArrowDown(_event) {
    // ...
  }

  private handleArrowUp(_event) {
    // ...
  }
}