简体   繁体   中英

TypeScript 3: property is missing in type

I'm working on a ReactJS app with TypeScript. I was using TypeScript 2.8 with no problem, but 2.9 and 3 give me a new error.

import * as React from 'react';


class ExampleComponent extends React.Component<{}, {
        firstName: string, lastName: string
    }> {
    clearState() {
        this.setState({
            firstName: "",
            lastName: ""
        });
    }

    constructor(props) {
        super(props);
        this.state = {
            firstName: '', lastName: ''
        };

        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
       //***** This is the line that gives me an error ******
        this.setState({ [event.target.id]: event.target.value });

    }
    public render() {

        return <form>

            <div className="form-group">
                <div className="row">
                    <div className="col">
                        <label className="sr-only">First Name</label>
                        <input type="text" className="form-control name-element" id="firstName"
                            placeholder="First Name" value={this.state.firstName} onChange={this.handleChange} required={true} />
                    </div>

                    <div className="col">
                        <label className="sr-only">Last Name</label>
                        <input type="text" className="form-control name-element" id="lastName"
                            placeholder="Last Name" value={this.state.lastName} onChange={this.handleChange} required={true} />
                    </div>
                </div>
            </div>

        </form>

    }
}

// Wire up the React component to the Redux store
export default ExampleComponent;

I get the following error:

Error   TS2345  (TS) Argument of type '{ [x: number]: any; }' is not assignable to parameter of type '{ firstName: string; lastName: string; } | ((prevState: Readonly<{ firstName: string; lastName: string; }>, props: {}) => { firstName: string; lastName: string; } | Pick<{ firstName: string; lastName: string; }, "firstName" | "lastName">) | Pick<...>'.
  Type '{ [x: number]: any; }' is not assignable to type 'Pick<{ firstName: string; lastName: string; }, "firstName" | "lastName">'.
    Property 'firstName' is missing in type '{ [x: number]: any; }'.

I think that the type system wants a guarantee that the value passed will be a valid one (ie "firstName" or "lastName"). I'm not sure about what construct to apply (and how to apply it) to appese the compiler. I think I need to extract an interface and use it in two places: where I define the state in the component, and somewhere in the handleChange method.

Any suggestions would be appreciated.

The problem is that your state is defined, in typescript yes, as a Record with keys firstname and lastname . When event.target.id is a wider type string , although in your case it's recognised as number for some reason.

One way would be to cast it to any like (UPDATED):

handleChange(event) {
    this.setState({ [event.target.id]: event.target.value } as any);
}

In this case I suppose it wouldn't matter much, because there is no typesafety in this statement from the beginning

I think to get a more reliable type check you could add a handler for each input like this

function makeHandler(
    id: WhatEnumYourIdIs
): (event: React.SyntheticEvent<HTMLInputElement>) => void {
    return function(event: React.SyntheticEvent<HTMLInputElement>): void{
        this.setState({ id: target.value });
    }
}

Then to add a handler

<input onChange={this.makeHandler(Enum.FirstName)} />

If you rely on the input id you cannot guarantee that the state field will match, it may compile but it won't actually be type checking.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM