Reputation: 175
I'm a little unsure as to how I'm supposed to add my props for type checking within a component. Here is my component thus far:
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>
)
}
}
The error I'm getting here is:
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; }'.
I understand (I think) that TS is trying to validate something more specific than a data type of an object (perhaps the actual state object itself?).
The only way I seem to be able to get this error to not be thrown is by setting display to type of 'any' but that doesn't really give us any actual detail.
My other assumption would be that I could set calculatorDisplay to a type of string independently (as that is what we want it to return, and ultimately all that I care about), which is what I've done above.
This is how CalculatorDisplay is being used in App.tsx:
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)
Would love some insight into how I'm approaching this incorrectly. Thank you.
Upvotes: 0
Views: 3536
Reputation: 626
You need to shape the display
property of your props
interface to how it should look. Take a look at your numberpad
object in your redux store, to figure out what display
should look like. Here's how I believe it should look given your component. Note: I've removed the namespace as there is no need for it in this component.
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>
)
}
}
Upvotes: 1