如何在TypeScript中动态生成的对象上使用“as const”?

zbdgwd5y  于 2023-06-07  发布在  TypeScript
关注(0)|答案(1)|浏览(130)

正如标题所示,我一直在尝试各种可能的方法和解决方案,我可以在网上找到使用“作为常量”的动态对象,但没有运气,所以我将非常感谢任何帮助。
我试图实现的是生成一个对象THEME_NAME_LIST,它包含另一个对象THEME中使用的键,这样我就不必在每次有新键到达THEME对象时手动维护THEME_NAME_LIST对象。
到目前为止,我已经能够很容易地从我的对象生成const类型,只在像这样的静态类型对象上;

export const THEME_NAME_LIST = {
    DARK: 'dark',
    LIGHT: 'light',
} as const;

const THEME_ARRAY = Object.values(THEME_NAME_LIST);
export type ThemeType = typeof THEME_ARRAY[number];

当鼠标悬停在THEME_NAME_LIST.LIGHT上时,IDE显示以下消息:
(属性)LIGHT:“光”
现在一切都到这一点工作得很好!但是,当我将THEME_NAME_LIST更改为下面的示例时,THEME_NAME_LIST中断了!

const THEME = {
    // ...
    DARK: {
        // ...
    },
    LIGHT: {
        // ...
    },
    // ...
};

export const THEME_NAME_LIST = {} as const;
Object.keys(THEME).forEach((key) => {
    const THEME_NAME = key.toUpperCase();
    THEME_NAME_LIST[THEME_NAME] = key.toLowerCase();
});

因此,当我将鼠标悬停在THEME_NAME_LIST.LIGHT上时,IDE会提示以下消息:
类型{}上不存在属性LIGHT
有人能告诉我我做错了什么吗?

laximzn5

laximzn51#

constAssert不适用于动态对象。它告诉编译器你的对象是只读的。当你试图操作对象时,上面的代码给出了一个错误。

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
  No index signature with a parameter of type 'string' was found on type '{}'.(7053)

不要将const应用于您试图创建的对象,而是将constAssert应用于原始对象,并从那里派生类型。我建议像这样创建一个Map类型:

type ThemeNameList = {
  [ThemeName in keyof typeof THEME as Uppercase<ThemeName>]: Lowercase<ThemeName>;
};

请注意,像Object.keys这样的函数不会帮助保留字符串文字。您可以在任何时间点放置Assert,但我的建议是仅在导出之前将ThemeNameList作为Assert应用于新对象。

const _THEME_NAME_LIST: Record<string, unknown> = {};
Object.keys(THEME).forEach((key) => {
  const THEME_NAME = key.toUpperCase();
  _THEME_NAME_LIST[THEME_NAME] = key.toLowerCase();
});

export const THEME_NAME_LIST = _THEME_NAME_LIST as ThemeNameList;

相关问题