0
votes

I am getting the following error:

Argument of type '{ [x: number]: any; }' is not assignable to parameter of type 'PostState | ((prevState: Readonly, props: Readonly<{}>) => PostState | Pick | null) | Pick<...> | null'. Property 'posts' is missing in type '{ [x: number]: any; }' but required in type 'Pick'.

on this line:

handleChange = ({target} : any) => {
        const {name, value} = target;
        this.setState({[name]: value}); // I GET THE ERROR HERE
    };

Here is my code:

interface Post{
name: string;
body: string;
title: string;
_id: number | string;
date: Date;
}

interface PostState{
posts: Post[];
}
class ABC extends React.Component <{},PostState> {
    state = {
        title: '',
        name: '',
        date: '',
        body: '',
        posts: []
    };

    handleChange = ({target} : any) => {
        const {name, value} = target;
        this.setState({[name]: value});
    };
    submit = (event : any) => {
        event.preventDefault();
        const payload = {
            title: this.state.title,
            body: this.state.body,
            name: this.state.name
        };

        axios({url: 'http://localhost:8080/api/save/', method: 'POST', data: payload}).then(() => {
            console.log("Data has been sent to the server");
            this.resetUserInputs();
        }).catch(() => {
            console.log("Internal server error");
        })
    };

    resetUserInputs = () => {
        this.setState({title: '', body: '', name: ''})
    };

    render() {
        console.log('state', this.state);
        return (
            <div>
                <Nav/>
                <Box>
                    <Title>
                        <TextName>New Question</TextName>
                    </Title>
                    <form onSubmit={this.submit}>

                        <div className="form-input">
                            <H5 >Name
                                <InputName
                                    type="text"
                                    name="name"
                                    placeholder="Enter your full name here"
                                    value={this.state.name}
                                    onChange={this.handleChange}/>
                            </H5>
                        </div>

                        <div className="form-input">
                            <H5 >Title
                                <InputTitle
                                    type="text"
                                    name="title"
                                    placeholder="What's your question? Be specific"
                                    value={this.state.title}
                                    onChange={this.handleChange}/>
                            </H5>
                        </div>

                        <div className="form-input">
                            <QuestionText >Question</QuestionText>
                            <Questionbox
                                placeholder="Start your question with What OR How OR Why"
                                name="body"
                                rows={4}
                                cols={30}
                                value={this.state.body}
                                onChange={this.handleChange}/>
                        </div>

                        <Footer>
                            <div className="post-form-buttons">

                                <Button>Add Question</Button>
                                <Cancel>
                                    <Link href={`/`}>
                                        <A>
                                            Cancel
                                        </A>
                                    </Link>
                                </Cancel>
                            </div>
                        </Footer>

                    </form>
                </Box>
            </div>
        );
    }
}

export default ABC
1

1 Answers

0
votes

The problem error you are seeing is due to an index being used in this.setState and no index signature being defined in your PostState interface.

Adding the index signature like so will squelch this error.

  interface PostState{
    posts: Post[];
    [key: string]: any;
  }

Also as an aside, you can define your target as an event and tell typescript that the target is an input having the name and value properties for a bit more type safety

  handleChange = ({target}: Event) => {
      const {name, value} = target as HTMLInputElement;
      this.setState({[name]: value});
  };

One other thing that I noticed is that you seem to be setting the state keys as keys of an individual post, but defining the state to have an array of posts.

Elaboration of advance fixes

Yes you can fix this in a more type-safe way, although you will need to use Multiple types and some more advanced features of TypeScript.

Something like the below code will get you close, but there will still be the minor issue that your state is defined with the date property as a string, and in your Post interface it's defined as an instance of Date. You'll have to decide how you want to address that, either by defining a union or by creating another separate interface that defines the date property as a string.

interface Post {
  name: string;
  body: string;
  title: string;
  _id?: number | string;
  date: Date;
}

interface PostsArray {
  posts: string[];
}

type JoinedTypes = Post & PostsArray;

type PostState = {[P in keyof JoinedTypes]: JoinedTypes[P]}