如何修复 Element 隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型?

时间:2021-04-05 05:31:39

标签: javascript reactjs typescript react-hooks react-typescript

为 React 项目尝试 TypeScript 时,我遇到了这个错误。

<块引用>

TS7053:元素隐式具有“any”类型,因为“string”类型的表达式不能用于索引类型“{ paymentMethod: string;数量:字符串;收据代码:字符串;付款日期:字符串;付款来源ID:字符串; }'。在类型“{ paymentMethod: string;”上找不到带有“string”类型参数的索引签名。数量:字符串;收据代码:字符串;付款日期:字符串;付款来源ID:字符串; }'

当我尝试 setInputs()

<块引用>

setInputs(inputs => ({...inputs, [inputs.field[eventName]]: eventValue}));

这是我的组件。

import React, {useState} from 'react';
import {DatePicker} from "jalali-react-datepicker";
import axios from "axios";
import PaymentFormClasses from './PaymentForm.module.css';
import PaymentCard from "../../Cards/PaymentCard/PaymentCard";
import Card from "../../Cards/Card";

interface PaymentForm {
    field: {
        paymentMethod: string,
        amount: string,
        receiptCode: string,
        paymentDate: string,
        paymentSourceID: string
    }
}

const PaymentForm = () => {
    const [inputs, setInputs] = useState<PaymentForm>({
        field: {
            paymentMethod: '',
            amount: '',
            receiptCode: '',
            paymentDate: '',
            paymentSourceID: 'paymentSourceID'
        }
    });

    const changedHandler = (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLSelectElement>) => {
        console.log(typeof e.target.name);
        const eventName = e.target.name;
        const eventValue = e.target.value;

        setInputs(inputs => ({...inputs, [inputs.field[eventName]]: eventValue}));
        console.log(e.target.value);
    }
   

    return (
        <>

        </>
    );
};

export default PaymentForm;

2 个答案:

答案 0 :(得分:2)

您需要断言 e.target.name(始终只是 string)实际上是 inputs.field 的有效键。

const eventName = e.target.name as keyof PaymentForm['field'];

但是您的更新语法不正确。您正在设置输入的顶级属性,并使用 inputs.field[eventName]value 作为属性名称。

您可以进行嵌套更新:

setInputs(inputs => ({ 
  ...inputs, 
  field: { 
    ...inputs.field, 
    [eventName]: eventValue 
  }
}));

但是为什么我们需要这个 field 属性呢?它是 inputs 中唯一的属性,所以我们为什么不让它成为整个状态。

interface Fields {
  paymentMethod: string;
  amount: string;
  receiptCode: string;
  paymentDate: string;
  paymentSourceID: string;
}

const PaymentForm = () => {
  const [fields, setFields] = useState<Fields>({
    paymentMethod: "",
    amount: "",
    receiptCode: "",
    paymentDate: "",
    paymentSourceID: "paymentSourceID"
  });

  const changedHandler = (
    e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    setFields((fields) => ({
      ...fields,
      [e.target.name as keyof Fields]: e.target.value
    }));
  };

  return <></>;
};

答案 1 :(得分:0)

您的 eventName 可以是字段键的联合。试试这个。

type EventName = 'paymentMethod' | 'amount' | 'recieptCode' ...etc;
const eventName = e.target.name as EventName; // OR

const eventName = e.target.name as keyof PaymentForm['field'];