You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中如何为动态生成的对象使用`as const`?

动态生成对象时如何保留as const的类型特性?

需求背景

我想从THEME对象的键自动生成THEME_NAME_LIST,这样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];

此时IDE悬停THEME_NAME_LIST.LIGHT会显示:

(property) LIGHT: "light"

但改用动态生成的方式就失效了:

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();
});

此时IDE提示:

Property LIGHT does not exist on type {}

问题原因

  1. as const会把对象类型锁定为只读的字面量类型,但后续用forEach动态修改对象的操作,TypeScript无法追踪,所以类型还是初始的{}。
  2. Object.keys()返回的类型是string[],不是THEME的键字面量类型,TypeScript无法推断出key的具体值,自然也无法推导THEME_NAME_LIST的键值对类型。

解决方案

用TypeScript的类型工具和函数式推导替代循环赋值,既保留类型安全,又能自动同步THEME的键:

步骤1:锁定THEME的类型为字面量类型

先给THEME加上as const,让TypeScript记住它的键的具体字面量:

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

步骤2:用工具类型生成目标类型

定义一个类型,把THEME的键转换为大写键+小写值的结构:

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

步骤3:用断言+映射生成对象

写一个辅助函数来生成对象,让TypeScript能正确推断类型:

function createThemeNameList<T extends Record<string, unknown>>(theme: T): {
    [K in keyof T as Uppercase<K & string>]: Lowercase<K & string>
} {
    const result = {} as any;
    (Object.keys(theme) as Array<keyof T & string>).forEach(key => {
        result[key.toUpperCase()] = key.toLowerCase();
    });
    return result;
}

export const THEME_NAME_LIST = createThemeNameList(THEME);

现在悬停THEME_NAME_LIST.LIGHT,IDE会显示:

(property) LIGHT: "light"

而且当THEME新增键(比如SYSTEM: { ... })时,THEME_NAME_LIST会自动新增SYSTEM: "system"的键值对,类型也会同步更新。

额外说明

  • TypeScript的类型系统是静态的,无法追踪运行时的动态修改操作,必须通过静态的类型映射来让编译器识别对象的结构。
  • Uppercase和Lowercase是TypeScript内置的字符串字面量类型工具,专门用来转换字符串字面量的大小写。

内容的提问来源于stack exchange,提问作者FARZAD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 12:47:40