这是一个简化的示例,其思想是一组标签,每个标签由单个字符定义。对象“Flags”累积值 可能的值在枚举中定义。 目标是让源代码明确、简洁、可重构、由编译器验证,并且存储标志的对象紧凑(用于数据库存储)
class Flags<ENU>{
s: string = "";
set(v: ENU){
this.s += v;
return this;
}
has(v: ENU){
return this.s.includes(v);
}
}
enum TypeAnimal{
Winged = "w",
Legged = "l"
}
let flagsBird = new Flags<TypeAnimal>().set(TypeAnimal.Winged);
我想验证通过这个的枚举没有重复的值。 我认为一种可能性是将类型不是明确地作为泛型传递,而是作为构造函数中的参数传递,让 ts 推断泛型。它似乎几乎可以工作:
class Flags2<ENU>{
s: string = "";
constructor(enu: ENU){
// check here the values in enu, fine.
}
set(v: ENU){
this.s += v;
return this;
}
has(v: ENU){
return this.s.includes(v);
}
}
let flagsBird2 = new Flags2(TypeAnimal);
但这会产生错误:
flagsBird2.set(TypeAnimal.Winged); // Argument of type 'TypeAnimal' is not assignable to parameter of type 'typeof TypeAnimal'.ts(2345)
我尝试了一些没有奏效的组合(我必须承认有点盲目)。
有什么想法或想法吗? (我觉得这里我有一些关于 ts 和泛型的东西要学习)
答案 0 :(得分:1)
这种缩短的编码真正给您带来什么好处?
IMO,TypeScript 中的枚举真的不值得。
解决这个问题的惯用方法是使用类型(记住,类型可以是字符串),而不是枚举。 Set
课程免费为您提供重复删除功能。
class Flags3<T extends string>{
s: Set<string> = new Set();
constructor(enu: readonly T[]) {
// check here the values in enu, fine.
}
set(v: T) {
this.s.add(v)
return this;
}
has(v: T) {
return this.s.has(v);
}
}
// parameter type below is ("legged" | "winged")[], NOT string[]
const f3 = new Flags3(["legged", "winged"]);
// or
// const animalTypes=["legged","winged"] as const;
// const f3 = new Flags3(animalTypes)
f3.set("legged"); // OK
f3.set("foo"); // compile time error
通过在构造函数参数中指定 readonly T[]
,我们能够推断传递给它的元组中的各个类型。
答案 1 :(得分:0)
enum TypeAnimal{
Winged = "w",
Legged = "l"
}
// modified class from the question
class Flags2<ENU>{
s: string = "";
set(v: ENU){
this.s += v; // #todo avoid duplicates in this.s
return this;
}
has(v: ENU){
return this.s.includes(`${v}`);
}
}
// version with a Set instead of a string. No duplicates.
class Flags3<ENU>{
s: Set<ENU> = new Set();
set(v: ENU){
this.s.add(v);
return this;
}
has(v: ENU){
return this.s.has(v);
}
}
let flagsBird2 = new Flags2<TypeAnimal>();
let flagsBird3 = new Flags3<TypeAnimal>();