TypeScript 不允许您向 enum 元素添加属性,该元素在运行时只是一个原始字符串或数字。相反,您必须执行一些操作,例如创建一个新类型,该类型包含对这些元素的引用,并且还具有您想要的方法或属性。
这是一种可能的方法。从您的普通enum 开始,如下所示:
enum SampleEnum {
V, IV, III
}
让我们为您的扩展类型定义一个接口。它有一个name、一个description 和一个number。请注意,此类型是通用类型,因此我们可以很快缩小 name 和 number 类型:
interface ISample<N extends number, S extends string> {
readonly name: S;
readonly description: string;
readonly number: N;
}
这是一个函数,它可以获取您的 SampleEnum 对象并返回具有相同键但具有实现扩展接口的值的内容:
function makeSample<E extends Record<Extract<keyof E, string>, number>>(
mapping: E
): { [K in Extract<keyof E, string>]: ISample<E[K], K> } {
const ret = {} as { [K in Extract<keyof E, string>]: ISample<E[K], K> };
(Object.keys(mapping).filter(k => k !== (+k) + "") as
(Extract<keyof E, string>)[]
).forEach(k => {
ret[k] = {
name: k,
description: "Blah " + k,
number: mapping[k]
}
});
return ret;
}
这可能是很多类型的杂耍,但它基本上只是从SampleEnum 中提取字符串值键(并忽略在运行时将数字键添加到数字枚举的reverse mapping)并构建扩展的实例每个接口,以某种类型安全的方式。
最后,让我们创建代表enum 的Sample 值和类型:
const Sample = makeSample(SampleEnum);
type Sample = (typeof Sample)[keyof typeof Sample]
好的,让我们使用它:
const nameOfIV = Sample.IV.name; // "IV"
console.log(nameOfIV); // "IV"
const numberOfIII = Sample.III.number; // SampleEnum.III
console.log(numberOfIII); // 1
const descriptionOfV = Sample.V.description; // string
console.log(descriptionOfV); // "Blah V"
const goodSample: Sample = Sample.III; // okay
const badSample: Sample = {
name: "II",
description: "oops",
number: 3
}; // error, name doesn't match
在我看来是合理的。 See for yourself。当然还有其他方法可以解决它,但这应该会给你一个想法。希望有帮助。祝你好运!