【问题标题】:Forcing objects within objects to be of same type in TypeScript在 TypeScript 中强制对象中的对象具有相同的类型
【发布时间】:2018-11-24 21:39:08
【问题描述】:

我需要创建一个常量列表,例如,

const Days = {
  YESTERDAY: -1,
  TODAY: 0,
  TOMORROW: 1,
}

我想要一种方法来约束Days中所有属性的类型,即如果我添加一个属性BAD_DAY: true,我希望编译器抱怨。

我从创建类似的东西开始

type ObjectOf<T> = {[k: string]: T};

const Days: ObjectOf<number> = {
   A: true;
}

这确实给了我一个错误,但是,当我在Days. 之后按 ctrl-space 时,我没有得到类型完成。我明白这是因为我将其设为键控对象类型。

我可以像第一个示例一样获得代码完成,也可以通过第二个示例获得编译器帮助。我可以把我的蛋糕也吃掉吗?我想我想要一些行为类似于 Java Enums 的东西,因为它是同类型对象的已知列表。

enum Days{
   Today("SUN"), MONDAY("MON"), TUESDAY("TUES"), WEDNESDAY("WED"),
   THURSDAY("THURS"), FRIDAY("FRI"), SATURDAY("SAT");
   private String abbreviation;
   public String getAbbreviation() {
       return this.abbreviation;
   }
   Days(String abbreviation) {
      this.abbreviation = abbreviation;
   }
}

【问题讨论】:

    标签: typescript generics


    【解决方案1】:

    拥有你的蛋糕并吃掉它。关于const,您需要一个通用的辅助函数。辅助函数将强制执行约束,但会推断传入对象字面量的真实类型:

    type ObjectOf<T> = {[k: string]: T};
    function createObjectOfNumber<T extends ObjectOf<number>>(v:T){
        return v;
    }
    const Days = createObjectOfNumber({
       A: 1
       // B: true // would be an error
    });
    Days.A // ok
    

    或者更通用的版本:

    function createObjectOf<TValue>(){
        return function<T extends ObjectOf<TValue>>(v:T){
            return v;
        }
    }
    const Days = createObjectOf<number>()({
       A: 1
       // B: true // would be an error
    });
    Days.A // ok
    

    如果你想要 Java 枚举之类的东西,Typescript 中没有对此的语言支持,但你可以模拟它们,见 this answer

    【讨论】:

    • 这正是我想要的。我正在创建类似的东西,但我没有想到有一个返回另一个函数的函数。只有一个函数,没有办法说其中一种泛型类型是从参数中推断出来的,而另一种是在调用中指定的,因为您使之成为可能
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    • 2021-06-25
    • 2012-10-30
    • 1970-01-01
    • 2022-01-11
    • 1970-01-01
    相关资源
    最近更新 更多