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

TypeScript中使用变量动态访问对象属性报类型错误如何解决

报错原因

TypeScript 做静态类型检查时,字符串拼接表达式的推导类型默认是string,编译器无法在编译阶段确认拼接结果一定是Budget接口的合法属性名,因此抛出 Type 'string' is not assignable to type 'keyof Budget' 的类型错误。
直接给budget_month赋值字符串字面量'budget_july'时,TS可以直接识别到该字面量属于Budget的合法键范围,因此不会触发报错。

另外原始代码存在隐藏运行时风险:toLocaleString('default', { month: 'long' })会跟随运行环境的默认语言返回对应语言的月份名,如果环境默认语言不是英文,会返回类似七月的非英文字符串,拼接出来的属性名和接口定义完全不匹配,哪怕绕过TS检查,运行时也会写入错误的属性。

实现方案

方案1:类型断言(最简洁,适合确定逻辑无错的场景)

直接通过类型断言告诉TS,你确认拼接结果是Budget的合法键,即可绕过类型检查。注意这里最好把toLocaleString的locale固定为en-US,避免环境语言差异导致的运行时错误:

const budgets: Budget[] = [{}]; // 原代码数组初始为空,直接取[0]会报错,需要先初始化第一个元素
const datestr = '2022-07-01';
const monthStr = new Date(datestr).toLocaleString('en-US', { month: 'long' }).toLowerCase();
const budget_month = `budget_${monthStr}` as keyof Budget;
budgets[0][budget_month] = 5000;

注意:该方案需要自行保证拼接逻辑的正确性,TS不会做额外校验。

方案2:固定月份映射表(类型安全最高,无运行时风险)

完全放弃依赖toLocaleString的返回值,手动建立JS Date月份索引(0=1月,11=12月)到Budget属性名的固定映射,从根源避免环境差异和拼写错误,TS也可以完整做类型校验:

// 月份索引对应Date.prototype.getMonth()的返回值
const MONTH_BUDGET_MAP: Record<number, keyof Budget> = {
  0: 'budget_january',
  1: 'budget_february',
  2: 'budget_march',
  3: 'budget_april',
  4: 'budget_may',
  5: 'budget_june',
  6: 'budget_july',
  7: 'budget_august',
  8: 'budget_september',
  9: 'budget_october',
  10: 'budget_november',
  11: 'budget_december'
};

const budgets: Budget[] = [{}];
const datestr = '2022-07-01';
const dateIns = new Date(datestr);
const budget_month = MONTH_BUDGET_MAP[dateIns.getMonth()];
budgets[0][budget_month] = 5000;

这个方案没有任何隐式依赖,不管运行环境是什么语言、什么时区,只要传入的日期合法,就能拿到正确的属性名,是生产环境优先推荐的写法。

方案3:运行时校验(兼顾灵活性和安全性)

如果不想维护固定映射表,可以先把Budget的所有合法键存为集合,拼接完属性名后先做合法性校验,再执行赋值,既保留了动态拼接的灵活性,也能避免非法属性写入:

const VALID_BUDGET_KEYS = new Set([
  'budget_july', 'budget_august', 'budget_september',
  'budget_october', 'budget_november', 'budget_december',
  'budget_january', 'budget_february', 'budget_march',
  'budget_april', 'budget_may', 'budget_june'
] as const);

const budgets: Budget[] = [{}];
const datestr = '2022-07-01';
const monthStr = new Date(datestr).toLocaleString('en-US', { month: 'long' }).toLowerCase();
const budgetKey = `budget_${monthStr}`;

if (VALID_BUDGET_KEYS.has(budgetKey as keyof Budget)) {
  budgets[0][budgetKey as keyof Budget] = 5000;
} else {
  throw new Error(`生成的预算属性名非法:${budgetKey}`);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:01:02