typescript - 如何使用对枚举通用的类扩展通用接口(interface)?

标签 typescript typescript-generics

我正在使用一个库来序列化对象,它支持自定义转换器来序列化/反序列化数据。

为了对枚举执行此操作,您需要使用扩展以下接口(interface)的自定义转换器。

export interface JsonCustomConvert<T> {
    serialize(data: T): any;
    deserialize(data: any): T;
}

这是我目前拥有的:

@JsonConverter
export class MyEnumConverter implements JsonCustomConvert<MyEnumConverter> {
  serialize(val: MyEnumConverter): string {
    return MyEnumConverter[val];
  }
  deserialize(val: any): MyEnumConverter {
    const possibleValidEnum = (<any>MyEnumConverter)[val];
    if (possibleValidEnum === undefined) {
      throw Error();
    }
    return <MyEnumConverter>possibleValidEnum;
  }
}

问题显然是每个枚举都需要一个转换器。有什么方法可以在类上为任何字符串索引枚举使用泛型类型来实现这一点?

自从我学习这门语言以来,没有必要展示我到目前为止得到的例子,任何尝试只会导致随机错误。

编辑:

这是我的问题的运行示例,每个枚举值都需要一个转换器。

https://stackblitz.com/edit/typescript-t2kdyx

最佳答案

我们可以创建一个返回类的工厂函数。所有枚举的实现都是相同的,但实际枚举将作为参数传递给工厂函数:

import {
  JsonObject,
  JsonProperty,
  JsonConvert,
  JsonConverter,
  JsonCustomConvert,
} from "json2typescript";

enum A {
  a = "aa",
  b = "bb"
}

enum X {
  x = "xx",
  z = "zz"
}

function createConverter<T extends Record<keyof T, string | number>>(e: T){
  const reverseLookup = {} as  Record<T[keyof T], keyof T>
  for (const key of Object.keys(e) as Array<keyof T>) {
    reverseLookup[e[key]] = key;
  }
  @JsonConverter
  class EnumConverter implements JsonCustomConvert<T[keyof T]> {
    serialize(val: T[keyof T]): keyof T {
      return reverseLookup[val];
    }
    deserialize(val: keyof T): T[keyof T] {
      const possibleValidEnum = e[val];
      if (possibleValidEnum === undefined) {
        throw Error();
      }
      return possibleValidEnum as T[keyof T];
    }
  }
  return EnumConverter;
}


const XEnumConverter = createConverter(X);
const AEnumConverter = createConverter(A);

@JsonObject("User")
class User {
  @JsonProperty("aEnum", AEnumConverter)
  aEnum: A = A.a;
  @JsonProperty("xEnum", XEnumConverter)
  xEnum: X = X.x;
}

const jsonObj = {
  "aEnum": "a",
  "xEnum": "x"
};

let jsonConvert: JsonConvert = new JsonConvert();
let user: User = jsonConvert.deserializeObject(jsonObj, User);
console.log(user); // User {aEnum: "aa", xEnum: "xx"}

let r: User = jsonConvert.serializeObject(user);
console.log(r); // {aEnum: "a", xEnum: "x"}

关于typescript - 如何使用对枚举通用的类扩展通用接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56166448/

相关文章:

javascript - typescript 减去两个 bool 值

typescript - 我应该使用 Typescript >2 或 TSLint 中的内置 linter 吗?

javascript - 如何通过查看源代码来区分 typescript 和 javascript?

typescript 通用参数未正确解析

typescript - 如何获得带有允许循环引用的点访问路径的深层 Keyof

angular - 无法解析 '@angular/material/typings/'

angular - Ionic serve 404 未能加载 main.js 和 main.css 资源

typescript - 通过 TS 定义嵌套属性

TypeScript:在运行时访问类型信息

typescript - 为什么 'null' 或 'undefined' "is assignable"到 'string' 类型的参数?