英文:
How to use "as const" on dynamically generated objects in TypeScript?
问题
我一直在尝试各种可能的方式和在线解决方案,以在动态对象上使用 "as const",但毫无运气,所以我将非常感激任何帮助。
我试图实现的目标是生成一个对象 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 显示以下消息;
(property) LIGHT: "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 提示以下消息;
Property
LIGHT
does not exist on type{}
有人能告诉我我做错了什么吗?
英文:
As the title suggests I've been trying every possible way and solution that I could find online to use "as const" on a dynamic object but no luck whatsoever so I would greatly appreciate any help.
What I'm trying to achieve is generating an object THEME_NAME_LIST
of the keys used in another object THEME
, so that I don't have to manually maintain the THEME_NAME_LIST
object every time some supposedly new key gets to the THEME
object.
I've been easily able to generate const types from my object up until this point only on statically typed objects like this;
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];
And when I hover over theTHEME_NAME_LIST.LIGHT
, the IDE shows the following message;
> (property) LIGHT: "light"
Now everything up until this point works great!
However, when I change THEME_NAME_LIST
to the example below, the THEME_NAME_LIST
breaks!
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();
});
So when I hover THEME_NAME_LIST.LIGHT
, the IDE prompts the following message;
> Property LIGHT
does not exist on type {}
Is anybody able to tell me what I'm doing wrong?
答案1
得分: 1
const
断言并不适用于动态对象。它告诉编译器你的对象是只读的。你上面的代码导致错误 ,当你尝试操作这个对象时。
元素具有 'any' 类型,因为类型为 'string' 的表达式不能用于索引类型为 '{}' 的类型。
在类型 '{}' 上找不到参数类型为 'string' 的索引签名。(7053)
不要将const
应用于你正在创建的对象,而是应用于你原始的对象,并从那里派生类型。我建议创建一个映射类型,如下所示:
type ThemeNameList = {
[ThemeName in keyof typeof THEME as Uppercase<ThemeName>]: Lowercase<ThemeName>;
};
请注意,诸如Object.keys
之类的函数不能保留字符串字面量。你可以在任何时候放置断言,但我建议在导出之前将ThemeNameList
作为断言应用于你的新对象。
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;
英文:
const
assertions are not meant for dynamic objects. It tells the compiler your object is readonly. Your above code gives an error when you try to manipulate the object.
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)
Instead of applying const
to the object you're trying to create, apply the const
assertion on your original object, and derive types from there. I would suggest creating a mapped type like so:
type ThemeNameList = {
[ThemeName in keyof typeof THEME as Uppercase<ThemeName>]: Lowercase<ThemeName>;
};
Note that functions like Object.keys
won't help preserve string literals. You can place assertions at any point in time, but my suggestion would be to only apply the ThemeNameList
as an assertion to your new object right before you export.
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;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论