代码之家  ›  专栏  ›  技术社区  ›  tru7

从泛型中传递的类型获取枚举对象

  •  0
  • tru7  · 技术社区  · 3 年前

    这是一个简化的例子,其思想是一组标签,每个标签由一个字符定义。对象“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 回复  |  直到 3 年前
        1
  •  1
  •   spender    3 年前

    这种缩短的编码真正给您带来了什么好处?

    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[] 在构造函数参数中,我们能够推断传递给它的元组中的各个类型。

    Playground Link

    Further reading about the downsides of enum

        2
  •  0
  •   lujcon    3 年前
    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>();