首页 > 解决方案 > 在 TypeScript 中强制对象中的对象具有相同的类型

问题描述

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

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.. 我理解这是因为我将其设为键控对象类型。

我可以像第一个示例一样获得代码完成,也可以通过第二个示例获得编译器帮助。我可以把我的蛋糕也吃掉吗?我想我想要一些行为类似于 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;
   }
}

标签: typescriptgenerics

解决方案


有你的蛋糕,也吃它。关于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 中没有对此的语言支持,但您可以模拟它们,请参阅此答案


推荐阅读