繁体   English   中英

在 TypeScript 中从带有附加字符串的枚举创建联合

[英]Create a union from an enum with an appended string in TypeScript

我想用翻译库为我的枚举的单数和复数版本添加类型定义。 翻译库查找键名的附加字符串。 IE

foo_one: "foo",
foo_other: "foos"

我想定义一个类型来匹配我的实现:

settings: {
  day_type: {
    [DayType.BusinessDay + "_one"]: "Business day",
    [DayType.BusinessDay + "_other"]: "Business days",
    [DayType.CalendarDay + "_one"]: "Business day",
    [DayType.CalendarDay + "_other"]: "Calendar days",
  },
},

我目前的定义:

enum DayType {
  BusinessDay = 'BUSINESS_DAY',
  CalendarDay = 'CALENDAR_DAY'
}


type SettingTranslations = {
  day_type: {
    [key in DayType | string]: string; // <- fix this
  };
};

您可以使用模板文字类型将枚举转换为相应的字符串文字类型并连接字符串文字:

interface SettingTranslations {
    day_type: {
        [K in `${DayType}${"_one" | "_other"}`]: string;
    };
};

这会为day_type产生以下属性:

/* (property) SettingTranslations.day_type: {
    BUSINESS_DAY_one: string;
    BUSINESS_DAY_other: string;
    CALENDAR_DAY_one: string;
    CALENDAR_DAY_other: string;
} */

不幸的是,您的实现不会进行类型检查:

const settings: SettingTranslations = {
    day_type: { // error! Type '{ [x: string]: string; }'
        [DayType.BusinessDay + "_one"]: "Business day",
        [DayType.BusinessDay + "_other"]: "Business days",
        [DayType.CalendarDay + "_one"]: "Business day",
        [DayType.CalendarDay + "_other"]: "Calendar days",
    }
};

这是因为使用+运算符的字符串连接不会在类型级别执行字符串文字的连接; 它只产生string 因此,编译器认为 object 具有string 索引签名{[x: string]: string} ,不知道它是否具有所需的键。

缺少文字类型连接是有意的; 请参阅microsoft/TypeScript#51583关于 microsoft/TypeScript#44905 的评论 这样做最终会破坏太多现实世界的代码,生成的联合类型太大而无法表示。

如果您想在类型级别和运行时都获得字符串连接,您可以改用模板文字字符串

const settings: SettingTranslations = {
    day_type: { // error! Type '{ [x: string]: string; }'
        [`${DayType.BusinessDay}_one`]: "Business day",
        [`${DayType.BusinessDay}_other`]: "Business days",
        [`${DayType.CalendarDay}_one`]: "Business day",
        [`${DayType.CalendarDay}_other`]: "Calendar days",
    },
}

糟糕,那仍然没有用,你仍然得到string 默认情况下,模板文字字符串没有模板文字类型。 该行为实际上是在microsoft/TypeScript#41891中实现的,但它破坏了太多代码(出于与+问题相同的原因)并在microsoft/TypeScript#42588中恢复。

幸运的是,有一种方法可以明确选择为模板文字字符串使用模板文字类型。 那就是使用const断言,如microsoft/TypeScript#40707中所实现的那样:

const settings: SettingTranslations = {
    day_type: { // okay
        [`${DayType.BusinessDay}_one` as const]: "Business day",
        [`${DayType.BusinessDay}_other` as const]: "Business days",
        [`${DayType.CalendarDay}_one` as const]: "Business day",
        [`${DayType.CalendarDay}_other` as const]: "Calendar days",
    },
} 

现在代码类型检查是因为编译器可以验证每个计算出的键都是正确的字符串文字类型。

游乐场代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM