【问题标题】:TypeScript type error and way to enumerate object propsTypeScript 类型错误和枚举对象道具的方法
【发布时间】:2021-08-12 16:29:21
【问题描述】:

我正在使用 ts/react/redux 创建一个前端应用程序。我熟悉类型语言,但似乎还不够。

情况: 有 react 组件(这里我们不关心 JSX):

import React from 'react';
import './MathComponent.css';

interface MathData {
    mathExpectation: number,
    variance: number,
    standardDeviation: number,
}

interface Props {
  data: MathData,
}

export const MathComponent: React.FC<Props> = ({
   data,
}) => {

 const mathConvert = (num: number) => {
 // some logic here
    return number+1;
 }
 
 const myData = {...data};
 
 const newData = Object.keys(data).map((key:string)=>{
    myData[key] = mathConvert(myData[key]); 
 });
 
  return (
  ...JSX
  )
}

据我所知,这里有一个常见问题:myData[key] 下划线作为文本错误:

元素隐含地具有“任何”类型,因为类型的表达式 “字符串”不能用于索引类型“对象”。没有索引签名 在“对象”类型上找到“字符串”类型的参数。

我看到一些类似的问题,但不懂解释。

所以我们的想法是遍历所有属性并在每个属性上使用 mathConvert-fnc 改变“myData”对象。 我知道,mutate 对象通常是一种不好的方法,但我在这里看不到任何其他选项。

我认为,主要问题:如何修复类型错误,次要:也许有更好的方法来枚举 obj 道具并在其上使用我的 fnc?

【问题讨论】:

标签: typescript


【解决方案1】:

这不是一个反应,而是一个打字稿问题。

Object.keys(data) 返回一个字符串数组。 myDataMathData 类型,因为它是如何初始化的。

要修复错误,您应该告诉 typescript 要使用的键是对象的键之一,而不仅仅是任何字符串,方法是这样转换:

myData[key as keyof MathData] = ...

我知道,mutate 对象通常是一种不好的方法,但我看不到 这里还有其他选项。

如果你想在功能上做事,而不是改变 myData 你可以使用 reducer 返回一个与初始对象具有相同键的对象,并将你的 mathConvert 函数应用于返回的新对象的值。 你设置一个空对象作为初始值,新对象作为累加器返回,你减少的是对象键。 类似的东西:


type MathDataKey = keyof MathData;
const newData = Object.keys(data).reduce((acc: Partial<MathData>, key)=>{
    acc[key as MathDataKey] = mathConvert(myData[key as MathDataKey]); 
    return acc;
}, {});

或者你可以使用像 lodash 这样的库,它可以让你map over objects values

【讨论】:

  • 我需要更多时间来弄清楚“reduce”方法,但“keyof”方法有效。谢谢你的澄清。
【解决方案2】:

当涉及到这些事情时,Typescript 可能会让人头疼。我认为您可以通过以下方式之一避免出现此错误:

  • map() 函数中删除: string
  • 调整你的 typescript.config.json 以拥有"noImplicitAny": false 属性。这将忽略所有隐含的 anys,因此这可能不是您想要的。
  • 在受影响的行上方添加// @ts-ignore 注释。当然,这也会忽略该行上的其他 TS 警告,因此使用风险自负:)
  • 投那个混蛋:myData[key as any]

至于第二个问题,您可以使用for (var key in obj) {..,尽管我不会说那一定更好。只是不同。

此外,您的代码缺少变量名:

const  = Object.keys(data).******

【讨论】:

  • 1 - 没有帮助,2 - 是的,它的粗略方法,3 - 相同,4 - 不明白在哪里以及如何投射,你能澄清一下吗?
  • 如果你将某物转换为一种类型,它会告诉 TS '假设这个值/对象/任何指定类型的东西'。如果你这样做(myData[key] as string) = mathConvert(myData[key] as string);(不完全确定这是否可行,但你可以尝试)TS 假定myData[key] 是一个字符串,应该满足于它。或者,如果这不满足 TS,则转换为 any 而不是 string 以使其知道类型无关紧要。
  • 抱歉,key 本身就是我想的问题,而不是该属性的值。在这种情况下,它是myData[key as any]
  • 不幸的是,它没有工作。与 -> myData[key as any] 相同的错误消息:元素隐式具有 'any' 类型,因为类型 'any' 的表达式不能用于索引类型 '{ mathExpectation: number;方差:数量;标准偏差:数字; }'。
  • 您可以尝试的另一件事是将myData 转换为any 以使TS 不知道它是一个对象。否则,我不知道。出于这个原因,我们在我们的应用程序中配置了"noImplicitAny": false,非常烦人;)
猜你喜欢
  • 1970-01-01
  • 2018-10-18
  • 2013-05-16
  • 2019-04-03
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多