React+Typescript:在更改处理程序中动态设置值时出现类型错误

React+Typescript : Getting type error when values are dynamically set in the change handler

我正在尝试基于对象数组动态创建表单。

此处的目标是通过单击“添加用户”按钮动态创建用户帐户,并将用户的整个状态对象提交到后端。

出现此错误'元素隐式具有 'any' 类型,因为类型 '{ name: string;年龄:字符串; }'没有索引签名'.

我是新来的!帮助将不胜感激。

我做错了什么?

import * as React from "react";

interface State{
  users:User[]
}
interface Props{

}
interface User{
  name:string,
  age:number;
}

class App extends React.Component<Props,State> {

   state = {
      users: [{name:"", age:""}],
   }

   handleChange = (value:number,event  : React.ChangeEvent<HTMLInputElement>) => {
    let users = [...this.state.users];
    console.log(event.target.value);
    users[value][event.target.name] = event.target.value;
    this.setState({ users }, () => console.log(this.state.users))
   }

   addUser = () => {    
    this.setState((prevState) => ({
      users: [...prevState.users, {name:"", age:""}],
    }));
   }

   handleSubmit = (e:any) => { 
       e.preventDefault();
       console.log(this.state.users) 
   }

   render() {
     let { users} = this.state
     return (
      <form onSubmit={this.handleSubmit} >
        <button onClick={this.addUser}>Add new cat</button>
        {
          users.map((val, id)=> {
            return (
              <div key={id}>
                <input
                  type="text"
                  name="name"                 
                  value={users[id].name}                   
                  onChange = {(e) =>this.handleChange(id,e)}
                />

                <input
                  type="text"
                  name="age"
                  value={users[id].age}                  
                  onChange = {(e) => this.handleChange(id,e)}
                />
              </div>
            )
          })
        }
        <input type="submit" value="Submit" /> 
      </form>
    )
  }
}
export default App;

首先User的界面是错误的。 age 被转换为一个数字,而您将 age 设置为一个空字符串 "".

其次,当您使用 Array.prototype.map 时,您没有使用索引 [id]。 map() 函数的实现看起来有点奇怪。来自 MDN

The map() method creates a new array with the results of calling a provided function on every element in the calling array.

您可以阅读更多关于地图的信息here

import * as React from "react";

interface Props{

}

interface User {
  name: string;
  age: number | string;
}

interface State {
  users: User[];
}

class App extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      users: [{ name: "", age: "" }]
    };
  }

  handleChange = (value: number, event: React.ChangeEvent<HTMLInputElement>) => {
    let users = [...this.state.users];
    users[value][event.target.name] = event.target.value;
    this.setState({ users }, () => console.log(this.state.users));
  };

  addUser = () => {
    this.setState(prevState => ({
      users: [...prevState.users, { name: "", age: "" }]
    }));
  };

  handleSubmit = (e: any) => {
    e.preventDefault();
    console.log(this.state.users);
  };

  render() {
    const { users } = this.state;
    return (
      <form onSubmit={this.handleSubmit}>
        <button onClick={this.addUser}>Add new cat</button>
        {users.map((user, id) => {
          return (
            <div key={id}>
              <input
                type="text"
                name="name"
                value={user.name}
                onChange={e => this.handleChange(id, e)}
              />

              <input
                type="text"
                name="age"
                value={user.age}
                onChange={e => this.handleChange(id, e)}
              />
            </div>
          );
        })}
        <input type="submit" value="Submit" />
      </form>
    );
  }
}
export default App;

event.target.value 的类型是字符串,不一定 'name' | 'age' 所以当你调用时:

users[value][event.target.name] = event.target.value;

Typescript 不能确定 users[value] 会有这个索引。这就是您可以更改用户界面的原因:

interface User {
    name:string,
    age:number;
    [key: string]: string | number
}

或者您可以检查密钥是否符合您的预期:

const keyName = event.target.name
if (keyName === 'name' || keyName === 'age') {
    users[value][keyName] = event.target.value;
}