打字稿泛型中的自定义枚举过于复杂
Posted
技术标签:
【中文标题】打字稿泛型中的自定义枚举过于复杂【英文标题】:Custom enum in typescript generics is overcomplicated 【发布时间】:2018-09-28 20:53:24 【问题描述】:如果有更简单的方法来写下来,因为这非常重复并且看起来非常错误......
const FolderVisibility = new Enum<
PUBLIC: 'public',
PRIVATE: 'private'
>(
PUBLIC: 'public',
PRIVATE: 'private'
) as Enum<
PUBLIC: 'public',
PRIVATE: 'private'
> &
PUBLIC: 'public',
PRIVATE: 'private'
我希望 IDE 能够告诉我 FolderVisibility.PUBLIC == 'public'
作为参数无论如何都是只读的。
这里是Enum
类,它自己的属性很少,只有一个功能
export default class Enum<T extends [index: string]: string >
private readonly map: T;
public readonly values: (T[keyof T])[];
constructor(enums: T)
Object.defineProperty(this, 'map', value: );
for (let prop in enums)
if (enums.hasOwnProperty(prop))
const value = enums[prop]
if(typeof value != 'string')
throw new EnumError(value)
this.map[prop] = value
Object.defineProperty(this, prop, value );
Object.defineProperty(this, 'values', value: Object.values(this.map) );
isValid(text: any)
if (!text) return true
return this.values.includes(text)
关键是,如果我将构造函数中使用的对象复制 4 次,它甚至会告诉我 FolderVisibility.values
的类型是 'public' | 'private'
PS:我已经尝试过了,但它会给我string
为FolderVisibility.values
。此外,它仍然很长。
常量数据 =
公共:'公共',
私人:'私人'
const FolderVisibility = new Enum<typeof data>(data) as Enum<typeof data> & typeof data
【问题讨论】:
你为什么不能只使用一个简单的打字稿枚举enum FolderVisibilityEnum PUBLIC = 'public', PRIVATE = 'private'
?您可以为枚举创建这些方法,它看起来会更好..
我们有多个枚举,它们都共享同一个类,因此使用相同的函数似乎是合适的。另外,如果添加枚举不需要太多努力,那就太好了。
第二个好处是可以更好地学习如何在 TS 中使用泛型类型。有这么多功能,但很难找到它们的教程
【参考方案1】:
对象字面量和字面量类型的问题在于,您无法让编译器推断出对象字面量属性的字面量类型。这就是为什么需要指定泛型类型参数的原因。
你的方法中有一部分是绝对可以简化的,那就是枚举之后的转换。不要使用构造函数,使用简单的函数,因为它可以更灵活地返回什么:
function Enum<T extends [P in keyof T]: string >(enums: T)
let map : [index: string]: string =
for (let prop in enums)
if (enums.hasOwnProperty(prop))
const value = enums[prop]
if(typeof value != 'string')
throw new EnumError(value)
map[prop] = value;
let result = Object.assign(, enums ,
values: Object.values(map),
isValid(text: string)
if (!text) return true
return this.values.includes(text)
);
// maybe frees the enum so no values are chanegd ?
return Object.freeze(result);
const FolderVisibility = Enum<
PUBLIC: 'public',
PRIVATE: 'private'
>(
PUBLIC: 'public',
PRIVATE: 'private'
);
console.log(FolderVisibility.isValid("")) // Works
console.log(FolderVisibility.PRIVATE === "private" ) // And const fields of string literal type
我们也可以使用上面的函数来增加一个实际的枚举,而不需要明确的输入:
enum FolderVisibilityProto
PUBLIC ='public',
PRIVATE= 'private'
const FolderVisibility = Enum(FolderVisibilityProto);
或者我们可以稍微更改Enun
函数以获取在内部创建枚举的回调,从而永远无法访问非增强枚举:
function Enum<T extends [P in keyof T]: string >(enumsCreator: () => T)
let enums = enumsCreator();
…
const FolderVisibility = Enum(()=>
enum FolderVisibility
PUBLIC ='public',
PRIVATE= 'private'
return FolderVisibility;
);
【讨论】:
以上是关于打字稿泛型中的自定义枚举过于复杂的主要内容,如果未能解决你的问题,请参考以下文章