微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

打字稿 - “字符串”类型的表达式不能用于索引类型

如何解决打字稿 - “字符串”类型的表达式不能用于索引类型

// common.js

const BoxNames = ['one','two'];

module.exports {
  BoxNames,}
const common = require("./common.js");
const BoxNames = common.BoxNames;
const messages = {
  'one': {
      id: 'some id',text: 'some text',},'two': {
    id: 'some id',};
const disabled = BoxNames.map((key: string) => messages[key]);

上面的代码messages[key] 语句产生了 TypeScript 错误

TS7053:元素隐式具有“任何”类型,因为表达式为 类型 'string' 不能用于索引类型 '{ one: { id: string;文本: 细绳; };二:{id:字符串;文本:字符串; }; }'。无索引 在类型 '{ 一: { ID:字符串;文本:字符串; };二:{id:字符串;文本:字符串; }; }'。

我将 key 声明为字符串,而 messages 的键是字符串,所以有什么问题?

(此处值得注意的是,messages 是使用 defineMessages 库中的 react-intl 方法生成的。)

(我在 StackOverflow 上看到过一些与 Object.keys 类似的答案,但我不确定这与我的 TypeScript 错误有什么关系。)

解决方法

对象 messages 的键不是 string 类型,而是 "one" | "two" 类型。换句话说,它们是字符串字面量,它是一种比简单的 string 更窄的类型,并且不能被更广泛的 string 类型索引。

编译示例的一种简单方法是将键数组转换为元组:

const boxNames = ['one','two'] as const;

这有效地将类型从 string[] 更改为 ["one","two"],现在当您映射它们时,它们将是正确的类型来索引您的对象。附带说明一下,没有必要显式设置 key 的类型,因为这可以从用法中推断出来。

const disabled = boxNames.map((key) => messages[key]); // this is now fine

另一种输入方式是将 messages 的键分配给数组:

const messages = {
  'one': {
      id: 'some id',text: 'some text',},'two': {
    id: 'some id',};

const boxNames: (keyof typeof messages)[] = ['one','two'];

const disabled = boxNames.map((key) => messages[key]);

这比使用元组更具动态性,并且它将保持类型安全,因为您将不允许在 boxNames 中包含比 messages 键存在的字符串更多的字符串。我想象这仍然适用于您所描述的 require 场景,尽管我现在没有设置环境来测试它。

我认为这里的主要内容是 boxNames 需要获得更具体的类型,或者 messages 需要不太具体的类型。我假设这些键必须完全匹配,但也许你的情况实际上更适合通过分配 messages 一个 string 索引类型 - 我认为这还不够上下文在这里假设任何一种方式。这意味着处理代码中的可能性,即您实际上并不知道数组和对象在运行时是否匹配。

,

Typescript 不知道 boxNames 的元素是 messages 的键。

stringkeyof 之间有明显的区别。

有几种方法可以告诉 TS 字符串是对象的键。

无需亲自测试,您也许可以做到这一点:

boxNames.map((key: keyof typeof messages) => messages[key])

要查询如何使用keyof关键字,需要在严格模式下索引对象。

,

当你创建一个像下面这样的对象而不给出类型时,该对象的推断类型将是 Record<'one' | 'two',string>

const numberCounter = {
 one: 'one',two: 'two'
}

所以,我们在这里必须记住,对象的键总是文字类型的联合,对象的值将是值类型的联合。

在下面的例子中,键是'一'和'二'的并集,值只是字符串类型(字符串和字符串的并集是一个字符串。)

我曾经像下面这样输入对象,所以我从来没有遇到过这样的问题。这里我明确说我的对象键是字符串类型的。

const boxNames = ['one','two'] ;

interface Type {
  id: string;
  text: string;
}
const messages: Record<string,Type> = {
  one: {
      id: 'some id',two: {
    id: 'some id',};
// key is already inferred as string
const disabled = boxNames.map(key => messages[key]);
console.log(disabled);

如果您不想明确说明对象键是字符串,那么@lawrence-witt answer 最适合这里。

还有一种方法可以使键成为“一”和“二”的并集。

const boxNames = ['one','two'];

const messages = {
  one: {
      id: 'some id',};

type Key = keyof typeof messages;

// here we are doing type cast of string into union of `one` and `two`.
//boxNames key are of string type
const disabled = boxNames.map(key => messages[key as Key]);
console.log(disabled);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?