首页 > 解决方案 > 在类型“{ order_graph_1: any; order_graph_2:任何;}'

问题描述

interface MyProps {
    order_graph_1: any;
    order_graph_2: any;setOrder: any}

class Setup extends React.Component<MyProps, MyState>{
    orders: { order_graph_1: any; order_graph_2: any; };
    constructor(props: MyProps){
        super(props);
        this.orders = {
            "order_graph_1":this.props.order_graph_1,
            "order_graph_2":this.props.order_graph_2
        }; 
    }
    
    setOrders(event: { target: { name: React.ReactText; value: string; }; }){
        this.orders[event.target.name] = parseInt(event.target.value);
    }

我正在尝试将 JS 代码更改为 TS,但出现以下错误:

this.orders[event.target.name]
Element implicitly has an 'any' type because expression of type 'ReactText' can't be used to index type '{ order_graph_1: any; order_graph_2: any; }'.
  No index signature with a parameter of type 'string' was found on type '{ order_graph_1: any; order_graph_2: any; }'.

我怎样才能解决这个问题?

标签: javascriptreactjstypescripttypescript-typingsreact-props

解决方案


Typescript 不知道stringfromevent.target.namethis.orders. 您需要断言name与您的可接受值相匹配as

这是一个很常见的问题,我打算将您重定向到另一个答案,但我想解决此代码中的其他一些危险信号。

您正在将有状态数据存储在 state 之外。不要这样做!您的组件不会在正确的时间以正确的值重新渲染。应该是的orders一部分this.state,无论是在此处还是在父级中。我不确定为什么在此处更新道具时要从道具传递值,这让我想知道这个组件是否应该没有状态并且应该只使用回调在父级中设置状态。React 建议你不应该基于 props herehere创建你的 state 。但我暂时忽略这一点,并假设这些是初始值。

抛弃any. 当您any用作类型时,您将失去打字稿的好处。你的值setOrders来自于parseInt,所以我们知道order_graph_1并且order_graph_2应该是 type number。为什么不这么说?

代码:

import React from "react";

interface Orders {
  order_graph_1: number;
  order_graph_2: number;
}

interface MyProps extends Orders {
  setOrder: (...args: any) => void; // function which takes args...??
}

interface MyState extends Orders {
  otherProperty: string;
}

class Setup extends React.Component<MyProps, MyState> {
  // don't need a constructor just to set state
  state = {
    // it is best not to derive state from props
    order_graph_1: this.props.order_graph_1,
    order_graph_2: this.props.order_graph_2,
    // just to show that we can have other properties alongside the orders
    otherProperty: ""
  };

  // needs to be an arrow function to access `this` properly
  // could use ( event: React.ChangeEvent<HTMLInputElement>)
  // could avoid the assertion by passing the name as an argument
  setOrders = (event: { target: { name: React.ReactText; value: string } }) => {
    // I don't love this solution, but we can avoid the TS errors by copying the previous state
    this.setState((prevState) => ({
      ...prevState,
      [event.target.name]: parseInt(event.target.value)
    }));
  };

  // helper function avoids having to duplicate info for the two inputs
  // can set any of these atrributes: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number
  // or https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attributes
  renderInput = (name: keyof Orders) => (
    <>
      <label htmlFor={name}>{name}</label>
      <input
        id={name} // label htmlFor matches id
        name={name}
        value={this.state[name]}
        onChange={this.setOrders}
        type="number"
        min={0} // don't allow negatives
        step={1} // allow whole numbers only
      />
    </>
  );

  render() {
    return (
      <div>
        {this.renderInput("order_graph_1")}
        {this.renderInput("order_graph_2")}
      </div>
    );
  }
}

推荐阅读