2 votes

Typescript enum mapping générique

Bonjour à la communauté Stack, J'ai les éléments suivants enum classe de cartographie :

export class RestEnumMpapper<T> {

  constructor() {}

  getEnumAsString<T>(o: T, key: string | number): string {
    if (typeof key === 'string') {
      return (o as T)[(o  as T)[key]];
    } else if (typeof key === 'number') {
      return (o as T)[key];
    } else {
      throw new Error(`Unable to parse enum from ${typeof(key)}`);
    }
  }
  /* ... Rest of enum converting class code ... */
}

Le cas d'utilisation typique est le suivant :

    export class PositionEvent {
    private static statusEnumMapper: RestEnumMpapper<EventState> = new RestEnumMpapper<EventState>();
    /* ... */
    this.status = PositionEvent.statusEnumMapper.getEnumAsString(EventState, iPos.status) as EventState;
}

Cela fonctionne plutôt bien, mais je suis en train de lister mon code et linter se plaint de l'ombre du type générique T en RestEnumMpapper ici :

export class RestEnumMpapper<T> {

et ici :

getEnumAsString<T>(o: T, key: string | number): string {

Il est donc rationnel et logique de laisser le type générique comme type de classe. Cependant, lorsque j'abandonne T sur la déclaration de fonction à chaque appel, j'obtiens ce qui suit TypeScritp erreur :

[ts] L'argument de type "typeof EventState" n'est pas assignable à un paramètre de type "EventState".

Il est possible de la forcer à fonctionner en lui passant la valeur d'un enum (ou tout autre nombre simple), mais la fonction échoue manifestement lorsqu'elle tente de résoudre une déclaration du type 2[3] .
Je serais reconnaissant pour toute suggestion sur la façon de résoudre ce problème. Avant d'abandonner le type générique dans la fonction, TypeScritp était capable de résoudre T en tant qu'objet avec des propriétés et un simple nom d'énumération suffisait pour fonctionner.

4voto

devilmaster Points 439

Cela est dû au fait que vous ne transmettez pas à la fonction une valeur de l'énumération, qui serait du type EventState mais plutôt l'objet contenant les enums qui est de type typof EventState . Ainsi, en supprimant le paramètre de type de la méthode, mais en passant par typeof EventState à la classe devrait fonctionner correctement :

let statusEnumMapper = new RestEnumMpapper<typeof EventState>();

Par ailleurs, si la classe est liée à une seule énumération, comme cela semble être le cas, vous pourriez tout aussi bien la passer au constructeur et ajouter une signature d'index à T pour permettre l'indexation sans coulée :

export class RestEnumMpapper<T extends { [name: string]: any }> {

    constructor(public enumObject: T) { }

    getEnumAsString(key: string | number): string {
        if (typeof key === 'string') {
            return this.enumObject[this.enumObject[key]];
        } else if (typeof key === 'number') {
            return this.enumObject[key];
        } else {
            throw new Error(`Unable to parse enum from ${typeof (key)}`);
        }
    }
    /* ... Rest of enum converting class code ... */
}

enum EventState {
    Test = "Test",
    One = "One",
}

let statusEnumMapper = new RestEnumMpapper(EventState);
let statusStr = "One";
let status = statusEnumMapper.getEnumAsString(statusStr) as EventState;

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