TypeScript 3: свойство отсутствует в типе - PullRequest
0 голосов
/ 01 сентября 2018

Я работаю над приложением ReactJS с TypeScript. Я использовал TypeScript 2.8 без проблем, но 2.9 и 3 выдают новую ошибку.

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;

Я получаю следующую ошибку:

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; }'.

Я думаю, что система типов хочет гарантировать, что переданное значение будет действительным (то есть «firstName» или «lastName»). Я не уверен, какую конструкцию применять (и как применять) для добавления компилятора. Я думаю, что мне нужно извлечь интерфейс и использовать его в двух местах: где я определяю состояние в компоненте и где-то в методе handleChange.

Любые предложения будут оценены.

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

Я думаю, чтобы получить более надежную проверку типов, вы можете добавить обработчик для каждого ввода, как это

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

Затем добавить обработчик

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

Если вы полагаетесь на идентификатор ввода, вы не можете гарантировать, что поле состояния будет совпадать, оно может скомпилироваться, но фактически это не будет проверка типа.

0 голосов
/ 01 сентября 2018

Проблема в том, что ваше состояние определено в машинописном тексте yes как Record с ключами firstname и lastname. Когда event.target.id является более широким типом string, хотя в вашем случае он почему-то распознается как number.

Одним из способов было бы привести его к any как (ОБНОВЛЕНО):

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

В этом случае я полагаю, что это не будет иметь большого значения, потому что в этом утверждении с самого начала нет безопасности типов

...