本文介绍了TypeScript 抱怨我使用属性访问器的 setState 语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

上给了我以下错误

[ts]'{ [x: number]: string | 类型的参数布尔值;}' 不可分配给类型为 'SoftwareLicenseCodesState | 的参数((prevState: Readonly, props: Readonly) => SoftwareLicenseCodesState | Pick | null) |选择<...>|空值'.输入 '{ [x: number]: 字符串 |布尔值;}' 不可分配到类型 'Pick<SoftwareLicenseCodesState, "count" |"oneTimeUsage" |持续时间" |"validFrom" |有效到" |分销商">'.类型 '{ [x: number]: string | 中缺少属性 'count'布尔值;}'.

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

import * as React from 'react';导入'./SoftwareLicenseCodes.css';界面 SoftwareLicenseCodesProps {}界面 SoftwareLicenseCodesState {计数:字符串;oneTimeUsage:布尔值;持续时间:字符串;有效从:字符串;有效到:字符串;分配器:字符串;}类 SoftwareLicenseCodes 扩展了 React.Component{构造函数(道具:SoftwareLicenseCodesProps){超级(道具);this.state = {经销商:'',数数:'',oneTimeUsage:假,期间: '',有效发件人:'',有效: ''};this.onInputChange = this.onInputChange.bind(this);}handleSubmit(事件:React.FormEvent){警报('提交');event.preventDefault();}onInputChange = (事件: React.FormEvent) =>{const value = event.currentTarget.type === 'checkbox' ?event.currentTarget.checked : event.currentTarget.value;this.setState({[名称]:值});}使成为() {返回 (<div className="user-container software-codes"><div className="user-single-container"><h1>软件许可代码</h1><form className="software-codes__form" onSubmit={this.handleSubmit}><标签><span className="software-codes__input-element">计数</span><标签><span className="software-codes__input-element">分销商</span><标签><span className="software-codes__input-element">一次使用</span><标签><span className="software-codes__input-element">持续时间</span><input className="software-codes__input-element" type="submit" value="Submit"/></表单>

);}}导出默认的 SoftwareLicenseCodes;

解决方案

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

要允许像您的 this.setState({[name]: value}); 这样的动态属性分配,您需要做以下两件事之一:

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

    interface SoftwareLicenseCodesState {计数:字符串;oneTimeUsage:布尔值;持续时间:字符串;有效从:字符串;有效到:字符串;分配器:字符串;[键:字符串]:任何;//<===}

    手册将其称为字符串索引签名",它包含在接口一>.

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

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

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

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

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

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

In the code example below, where I try to have one onInputChange handler for several inputs, TypeScript gives me the following error on the statement {[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; }'.

What is wrong here? How can I fix it?

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;
解决方案

You haven't shown the interfaces the errors complain about (LicenseCodesState, Pick), but I'm going to assume they're defined similarly to your quoted SoftwareLicenseCodesState.

To allow dynamic property assignment like your this.setState({[name]: value});, you need to do one of two things:

  1. Add dynamic property access to the definition (but keep reading):

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

    The handbook calls this a "string index signature," it's covered under Interfaces.

    The problem with this is that, of course, that means you lose type checking — not just where you use it, but basically anywhere you use SoftwareLicenseCodesState.

  2. Use a type assertion where you do the setState call. You have a couple of options there. You can use an assertion on name:

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

    or on the state object you're passing:

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

    This loses type checking on that call, but preserves it elsewhere.

这篇关于TypeScript 抱怨我使用属性访问器的 setState 语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 13:38