7

I added onChange method in my project(React, TS, Mobx), but I am getting an error: Argument of type '{ [x: number]: any; }' is not assignable to parameter of type

I am new to TypeScript and not sure why it's happening. What can be the problem?

(parameter) event: {
    target: {
        name: any;
        value: any;
    };
}

Argument of type '{ [x: number]: any; }' is not assignable to parameter of type 'IAddPlayerFormState | ((prevState: Readonly, props: Readonly) => IAddPlayerFormState | Pick | null) | Pick<...> | null'.

enter image description here

import React, { Component } from 'react';
import ViewStore from '../../../store/ViewStore';
import { TextField } from './../../../utils';

interface IAddPlayerFormProps {
  viewStore?: ViewStore; // Optional ViewStore
}

interface IAddPlayerFormState {
  playerName: string;
  isDisabled: boolean;
}

class AddPlayerForm extends Component<IAddPlayerFormProps, IAddPlayerFormState> {
  constructor(props: Readonly<IAddPlayerFormProps>) {
    super(props);

    this.state = {
      isDisabled: false,
      playerName: '',
    };
  }

  public onChange(event: { target: { name: any; value: any; }; }) {
    this.setState({ [event.target.name]: event.target.value });
    console.log('On Change!');
  }

  public handleSubmit = () => {
    console.log('On submit!');
  }

  public render() {
    const { isDisabled } = this.state;

    return (
      <form onSubmit={this.handleSubmit}>
        <TextField
          type="text"
          name="name"
          value={name}
          placeholder="Add player"
          onChange={this.onChange}
          disabled={isDisabled}
        />

        <input type="submit" />
      </form>
    );
  }
}

export default AddPlayerForm;
Vincent D'amour
  • 3,746
  • 1
  • 27
  • 39
lecham
  • 2,294
  • 6
  • 22
  • 41
  • are you using any UI library? if so see the type of input element there. otherwise no need to detruct the type inline just `event:React.FormEvent` which is a synthetic event contains all the types for target name and target value – Amir-Mousavi Apr 17 '19 at 14:47

4 Answers4

10

You need to tell Typescript that your object will have one or more property from IAddPlayerFormState, but not necessarily all properties. You can do it like this:

public onChange(event: { target: { name: any; value: any; }; }) {
  const newState = { [name]: value } as Pick<IAddPlayerFormState, keyof IAddPlayerFormState>;
  this.setState(newState);
  console.log("On Change!");
}
Itamar
  • 119
  • 1
  • 6
Vincent D'amour
  • 3,746
  • 1
  • 27
  • 39
10

Using this syntax got rid of the error for me:

const myFunction = (e) => {
    return this.setState({...this.state, [e.target.id]: e.target.value});
}

Amartya Mishra
  • 145
  • 3
  • 7
  • Can you explain "...this.state" – JayC Jan 27 '21 at 20:08
  • @Jesse sure, ...this.state will expand/destructure the state object, then you are adding more objects to/modifying the destructured object. Finally, you take all of this and assign it to the current state using this.setState. – Amartya Mishra Jan 29 '21 at 03:12
2

Your state shape is this:

interface IAddPlayerFormState {
  playerName: string;
  isDisabled: boolean;
}

and you are calling setState with this:

{any: any}

You can change only values: playerName and isDisabled not any. If you rewrite function signature as

public onChange(event: { target: { name: "playerName"|"isDisabled"; value: any; }; })

or better

public onChange(event: { target: { name: keyof IAddPlayerFormState ; value: any; }; })

it should be ok for typescript. Btw this code will not work though. Change input name :). I hope this answer is clear, if not i will edit that.

1

All u need to do is specify which item you want to update/change

this.setState({value:value});
type ItemState = {
    value?: string;// The state I want to update
};

#In your case would be

this.setState({playerName : new_value});
JPilson
  • 1,075
  • 11
  • 10