簡體   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