Reputation: 1235
I have a Class based React Component that accepts a function as a prop.
The component was originally a stateless functional component that accepted the same function without any TypeScript errors.
Now that I've converted it to a class component I'm getting an error when I call the function: Property 'onRouteChange' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'
As well as an error when I de-structure it in the props: Property 'onRouteChange' is missing in type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' but required in type '{ onRouteChange: any; }'.
I initially tried to define it in the types declaration at the top of the file but that's not working either.
Component
type SignInState = {
signInEmail: string,
signInPassword: string
}
class SignIn extends Component<{}, SignInState> {
constructor(props: {}){
super(props);
this.state = {
signInEmail: '',
signInPassword: ''
}
}
onEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ signInEmail: e.target.value })
}
onPasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ signInPassword: e.target.value })
}
onSubmitSignIn = () => {
// fetch()
console.log(this.state);
// TS Error: Property 'onRouteChange' does not exist
this.props.onRouteChange('home');
}
render() {
// TS Error: Property 'onRouteChange' is missing in type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'
const { onRouteChange } : { onRouteChange: any} = this.props
return (
<Container>
<Main>
<Form>
<Fieldset>
<SignInTitle>Sign In</SignInTitle>
<EmailAddressSection>
<Label>Email</Label>
<EmailInput />
</EmailAddressSection>
<PasswordSection>
<Label>Password</Label>
<PasswordInput />
</PasswordSection>
</Fieldset>
<div>
<SignInButton
onClick={this.onSubmitSignIn}
type="submit"
value="Sign in"
/>
</div>
<AccountOptionsSection>
<AccountOption onClick={() => onRouteChange("register")}>
Register
</AccountOption>
</AccountOptionsSection>
</Form>
</Main>
</Container>
);
}
};
export default SignIn;
Upvotes: 1
Views: 3580
Reputation: 2849
Create a type
or an interface
for your props just as you did with your state.
Props Interface
// interface over type literal
interface IProps {
onRouteChange: (param: string) => void
}
Avoid Typing to any
Try to avoid typing something to any
. You are basically telling typescript this has no type. That defeats the purpose of TS. If you truly do not know, type it to unknown
.
But, you are passing a string
home so you have some information on it that you can use to type it a little better.
Here, I am guessing onRouteChange
is a function that accepts one parameter of type string and returns nothing (does a side effect). You can update this accordingly.
Typing Your Component Props
You do exactly what you did with your state type (prefer interface over types).
class SignIn extends Component<IProps, IState>
Now you should not have to type onRouteChange
when you destructure it.
const { onRouteChange } : { onRouteChange: any} = this.props
becomes
const { onRouteChange } = this.props
Upvotes: 1
Reputation: 2609
class SignIn extends Component<{}, SignInState>
The first param to Component type is props type , and you have not defined it, therefore the error.
Define a interface,
interface ISignInProp {
onRouteChange:any
}
and pass it to your Component
class SignIn extends Component<ISignInProp , SignInState>
Upvotes: 1