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

如何正确将TypeScript枚举映射为自定义PickerOption对象?

问题

我定义了一个TypeScript字符串枚举:

export enum LanguagesEnglish  {
  'enUS'= 'English',
  'zhHant'= 'Mandarin, Traditional',
};

想要用它生成选择器组件的选项,组件要求的选项类型是:

type pickerOption = {
  code: string,
  label: string,
};

我尝试修改类型定义并编写生成函数:

type pickerOption = {
  code: keyof LanguagesEnglish,
  label: LanguagesEnglish,
};

function generateOption(key: keyof LanguagesEnglish): pickerOption {
  return {
      code: key,
      label: LanguagesEnglish[key],
  }
}

最后用Object.keys()映射生成数组时:

const options = Object.keys(LanguagesEnglish).map(generateOption);

出现了类型错误:

Element implicitly has an 'any' type because expression of type 'number | unique symbol | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | ... 35 more ... | "at"' can't be used to index type 'typeof LanguagesEnglish'.
No index signature with a parameter of type 'number' was found on type 'typeof LanguagesEnglish'. (lsp)

明明指定了key的类型是keyof LanguagesEnglish,为什么还会报错?正确的枚举映射方式是什么?

原因
  1. Object.keys()的类型缺陷:TypeScript中Object.keys()的返回值被定义为string[],而非枚举的具体键类型keyof LanguagesEnglish,直接传给generateOption会触发类型不匹配。
  2. 字符串枚举的双向映射:TypeScript编译字符串枚举时,会生成同时包含键→值和值→键的双向映射对象,Object.keys()会把数值形式的反向键也包含进去,进一步导致类型错误。
正确解决方案

方案一:过滤无效键+类型断言

先过滤掉双向映射产生的数值键,再对Object.keys()的结果做类型断言,确保传入的是合法枚举键:

export enum LanguagesEnglish  {
  'enUS'= 'English',
  'zhHant'= 'Mandarin, Traditional',
};

type pickerOption = {
  code: keyof typeof LanguagesEnglish,
  label: LanguagesEnglish,
};

function generateOption(key: keyof typeof LanguagesEnglish): pickerOption {
  return {
    code: key,
    label: LanguagesEnglish[key],
  };
}

// 过滤数值键,同时断言类型为枚举键
const options = Object.keys(LanguagesEnglish)
  .filter(key => isNaN(Number(key)))
  .map(key => generateOption(key as keyof typeof LanguagesEnglish));

方案二:直接用Object.entries()处理键值对

跳过单独的生成函数,直接遍历枚举的键值对并过滤无效项:

export enum LanguagesEnglish  {
  'enUS'= 'English',
  'zhHant'= 'Mandarin, Traditional',
};

type pickerOption = {
  code: string,
  label: string,
};

const options: pickerOption[] = Object.entries(LanguagesEnglish)
  .filter(([key]) => isNaN(Number(key)))
  .map(([code, label]) => ({ code, label }));

方案三:预定义合法键数组(类型最安全)

手动定义枚举的合法键数组,完全避免类型断言,同时保证类型严格:

export enum LanguagesEnglish  {
  'enUS'= 'English',
  'zhHant'= 'Mandarin, Traditional',
};

// 定义只读的枚举键数组
const languageKeys = ['enUS', 'zhHant'] as const;
// 推导键的类型
type LanguageKey = typeof languageKeys[number];

type pickerOption = {
  code: LanguageKey,
  label: LanguagesEnglish,
};

// 直接映射生成选项,类型完全安全
const options = languageKeys.map(key => ({
  code: key,
  label: LanguagesEnglish[key],
}));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:07:46