【问题标题】:Unable to validate prop types with Typescript无法使用 Typescript 验证道具类型
【发布时间】:2017-05-22 18:44:02
【问题描述】:

我有点不确定我应该如何添加我的道具以在组件中进行类型检查。到目前为止,这是我的组件:

import * as React from 'react';
import { connect } from 'react-redux';

export namespace CalculatorDisplay {
  export interface Props {
    display: object,
    calculatorDisplay: string,
  }

  export interface State {

  }
}

// TODO: How do we get displayString to be properly recognized in props validation?
export default class CalculatorDisplay extends React.Component<CalculatorDisplay.Props, CalculatorDisplay.State> {

  render() {

    let calculatorDisplay = this.props.display.displayString;
    return (
      <div className="display">
        <div className="displayText">
          { calculatorDisplay }
        </div>
      </div>
    )
  }

}

我在这里遇到的错误是:

ERROR in [at-loader] ./src/components/CalculatorDisplay.tsx:23:48 
    TS2339: Property 'displayString' does not exist on type 'object'.

ERROR in [at-loader] ./src/containers/App.tsx:22:24 
    TS2322: Type '{ display: any; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<CalculatorDisplay> & Readonly<{ children?: ReactNo...'.
  Type '{ display: any; }' is not assignable to type 'Readonly<Props>'.
    Property 'calculatorDisplay' is missing in type '{ display: any; }'.

我理解(我认为)TS 试图验证比对象的数据类型更具体的东西(也许是实际的状态对象本身?)。

我似乎能够让这个错误不被抛出的唯一方法是将显示设置为“任何”类型,但这并没有真正给我们任何实际的细节。

我的另一个假设是我可以独立地将calculatorDisplay 设置为一种字符串(因为这是我们希望它返回的,最终也是我所关心的),这就是我在上面所做的。

这是在 App.tsx 中使用 CalculatorDisplay 的方式:

import * as React from 'react'
import PropTypes from 'prop-types'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import Calculator from '../components/Calculator'
import CalculatorDisplay from '../components/CalculatorDisplay'
import * as CalculatorActions from '../actions'
import { RouteComponentProps } from 'react-router'

export namespace App {
  export interface Props extends RouteComponentProps<void> {
    actions: typeof CalculatorActions;
  }

  export interface State {
    /* empty */
  }
}

const App = ({todos, actions, display}) => (
  <div>
    <CalculatorDisplay display={display}/>
    <Calculator actions={actions}/>
  </div>
)

const mapStateToProps = state => ({
  todos: state.todos,
  display: state.numberpad
})

const mapDispatchToProps = dispatch => ({
    actions: bindActionCreators(CalculatorActions as any, dispatch)
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App)

希望能深入了解我是如何错误地处理这个问题的。谢谢。

【问题讨论】:

  • 你如何在App.tsx 中使用CalculatorDisplay
  • 我已将 App.tsx 添加到说明中。

标签: reactjs typescript redux


【解决方案1】:

您需要将props 接口的display 属性调整为应有的外观。看看你的 redux 存储中的 numberpad 对象,找出 display 应该是什么样子。这是我认为给定您的组件的外观。注意:我已删除命名空间,因为此组件中不需要它。

export interface Props {
    display: {
        displayString: string,
        // Other properties of display go here.

    };
    calculatorDisplay: string;
}

export interface State {}

export default class CalculatorDisplay extends React.Component<Props, State> {
    render() {

        const calculatorDisplay = this.props.display.displayString;
        return (
            <div className="display">
              <div className="displayText"> { calculatorDisplay }</div>
            </div>
    )
    }

}

【讨论】:

  • 嗯,有道理,出于某种原因,我并没有建立联系,我希望完全按照我的 reducer 中声明的方式来塑造属性。谢谢。
  • 它们不需要与初始状态的形状相同,这取决于您从mapStateToProps 中的状态映射的内容。例如,您可以只映射您所在州的 displayString 属性,例如displayString: state.numberpad.displayString,那么你的 Props 界面将有 displayString: string,而不是 display。在大多数情况下,您只想映射组件所需的内容。
猜你喜欢
  • 2018-12-10
  • 2021-01-27
  • 2017-09-26
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
  • 2018-09-03
相关资源
最近更新 更多