TypeScript 抱怨我使用属性访问器的 setState 语句

IT技术 reactjs typescript
2021-05-14 22:54:17

在下面的代码示例中,我尝试为多个输入设置一个 onInputChange 处理程序,TypeScript 在语句中给出了以下错误{[name]: value}

[ts]
Argument of type '{ [x: number]: string | boolean; }' is not assignable to parameter of type 'SoftwareLicenseCodesState | ((prevState: Readonly<SoftwareLicenseCodesState>, props: Readonly<SoftwareLicenseCodesProps>) => SoftwareLicenseCodesState | Pick<SoftwareLicenseCodesState, "count" | ... 4 more ... | "distributor"> | null) | Pick<...> | null'.
  Type '{ [x: number]: string | boolean; }' is not assignable to type 'Pick<SoftwareLicenseCodesState, "count" | "oneTimeUsage" | "duration" | "validFrom" | "validTo" | "distributor">'.
    Property 'count' is missing in type '{ [x: number]: string | boolean; }'.

这里有什么问题?我该如何解决?

import * as React from 'react';
import './SoftwareLicenseCodes.css';

interface SoftwareLicenseCodesProps {
}

interface SoftwareLicenseCodesState {
    count: string;
    oneTimeUsage: boolean;
    duration: string;
    validFrom: string;
    validTo: string;
    distributor: string;
}

class SoftwareLicenseCodes extends React.Component<SoftwareLicenseCodesProps, SoftwareLicenseCodesState> {
    constructor(props: SoftwareLicenseCodesProps) {
        super(props);

        this.state = {
            distributor: '',
            count:'',
            oneTimeUsage: false,
            duration: '',
            validFrom: '',
            validTo: ''
        };

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

    handleSubmit(event: React.FormEvent<HTMLFormElement>) {
        alert('submit');
        event.preventDefault();
    }

    onInputChange = (event: React.FormEvent<HTMLInputElement>) => {
        const value = event.currentTarget.type === 'checkbox' ? event.currentTarget.checked : event.currentTarget.value;

        this.setState({
            [name]: value
        });
    }

    render() {
        return (
            <div className="user-container software-codes">
                <div className="user-single-container">
                    <h1>Software License Codes</h1>

                    <form className="software-codes__form" onSubmit={this.handleSubmit}>
                        <label>
                            <span className="software-codes__input-element">Count</span>
                            <input
                                name="count"
                                type="number"
                                value={this.state.count}
                            />
                        </label>

                        <label>
                            <span className="software-codes__input-element">Distributor</span>
                            <input
                                name="distributor"
                                type="text"
                                value={this.state.distributor}
                            />
                        </label>

                        <label>
                            <span className="software-codes__input-element">One time usage</span>
                            <input
                                name="oneTimeUsage"
                                type="checkbox"
                                checked={this.state.oneTimeUsage}
                            />
                        </label>

                        <label>
                            <span className="software-codes__input-element">Duration</span>
                            <input
                                name="duration"
                                type="number"
                                value={this.state.duration}
                            />
                        </label>
                        <input className="software-codes__input-element" type="submit" value="Submit" />
                    </form>
                </div>
            </div>
        );
    }
}

export default SoftwareLicenseCodes;
1个回答

您还没有显示错误抱怨的接口 ( LicenseCodesState, Pick),但我假设它们的定义与您引用的SoftwareLicenseCodesState.

要允许像您的 动态属性分配this.setState({[name]: value});,您需要执行以下两项操作之一:

  1. 添加对定义的动态属性访问(但请继续阅读):

    interface SoftwareLicenseCodesState {
        count: string;
        oneTimeUsage: boolean;
        duration: string;
        validFrom: string;
        validTo: string;
        distributor: string;
        [key: string]: any;            // <===
    }
    

    手册将其称为“字符串索引签名”,它包含在Interfaces

    这样做的问题在于,当然,这意味着您会丢失类型检查——不仅是在您使用它的地方,而且基本上是在您使用SoftwareLicenseCodesState.

  2. setState调用的地方使用类型断言你有几个选择。您可以在 上使用断言name

    const name = event.currentTarget.name as keyof SoftwareLicenseCodesState;
    this.setState({[name]: value});
    

    或在您传递的状态对象上:

    this.setState({[event.currentTarget.name]: value} as Partial<SoftwareLicenseCodesState>);
    

    这会丢失对该调用的类型检查,但将其保留在其他地方。