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

如何使用格式化字符串作为键从只读对象中取值?

问题描述

存在一个只读对象errorMessages和一些字段,每个字段在errorMessages中对应多条错误信息,但无法使用格式化字符串作为键从该只读对象中取值。

代码示例:

import { useState } from "react";

const errorMessages = {
  emailInvalid: "Invalid email address",
  emailAlreadyExists: "This email is already exists",
  phoneInvalid: "Invalid phone number",
  phoneNotAllowed: "Phone region is not allowed"
} as const;

const fields = ["email", "phone"];

export default function App() {
  const [error, setError] = useState("");

  const handleClick = (field: string) => {
    const errorKey = `${field}Invalid`;
    setError(errorMessages[errorKey]); // 此处报错
  };

  return (
    <div>
      <h1>{error}</h1>
      {fields.map((field) => (
        <button key={field} onClick={() => handleClick(field)}>
          {field} error
        </button>
      ))}
    </div>
  );
}

报错信息:

Element implicitly has an 'any' type because expression of type
'string' can't be used to index type '{ readonly required: "This field
is required"; readonly emailInvalid: "Invalid email address"; readonly
phoneInvalid: "Invalid phone number"; }'. No index signature with a
parameter of type 'string' was found on type '{ readonly required:
"This field is required"; readonly emailInvalid: "Invalid email
address"; readonly phoneInvalid: "Invalid phone number"; }'.ts(7053)

需要解决两个问题:

  • 能否在不修改errorMessages的前提下修复类型报错?
  • 为何存在类型报错的代码仍能正常运行?
解决方案(不修改errorMessages)

因为errorMessages被as const标记为只读,TypeScript会严格限制其索引必须是自身的字面量键类型,而${field}Invalid被推断为宽泛的string类型,无法匹配具体的键。以下是几种可行的修复方式:

方式1:类型断言为目标键类型

直接将生成的键断言为errorMessages的键类型,告诉TypeScript这个键是合法的:

const handleClick = (field: string) => {
  const errorKey = `${field}Invalid` as keyof typeof errorMessages;
  setError(errorMessages[errorKey]);
};

注意:如果传入的field生成的键不在errorMessages中,运行时会得到undefined,需要确保field的取值范围是安全的。

方式2:缩小字段的类型范围

把fields数组的类型改为字面量联合类型,让field的类型从string变成具体的"email" | "phone",再配合类型断言:

// 用as const把数组转为只读字面量数组
const fields = ["email", "phone"] as const;

const handleClick = (field: typeof fields[number]) => {
  const errorKey = `${field}Invalid` as keyof typeof errorMessages;
  setError(errorMessages[errorKey]);
};

这种方式更安全,TypeScript会检查field的取值,避免传入无效字段。

方式3:用类型守卫验证键的合法性

添加类型守卫函数,确保生成的键确实存在于errorMessages中,同时让TypeScript自动推断类型:

const isErrorKey = (key: string): key is keyof typeof errorMessages => {
  return key in errorMessages;
};

const handleClick = (field: string) => {
  const errorKey = `${field}Invalid`;
  if (isErrorKey(errorKey)) {
    setError(errorMessages[errorKey]);
  } else {
    // 处理无效键的情况,比如设置默认错误信息
    setError("Invalid field error");
  }
};
代码能正常运行的原因

TypeScript的报错属于编译时类型检查,它的作用是提前提示开发者潜在的类型安全问题,但不会阻止代码被编译为JavaScript执行。只要代码本身符合JavaScript语法规范,即使存在TypeScript类型错误,编译后的JS代码依然能正常运行。

内容的提问来源于stack exchange,提问作者j-0-n-e-z

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:47:33