Reputation: 963
I'd like to take advantage of the static and strong typing in TypeScript, but only for the state since I don't intend to take in any props.
When I attempt to pass the interface as such, I end up with an error:
import * as React from 'react';
import {Link} from 'react-router-dom';
import Constants from '../Constants';
interface ILoginState {
email: string;
password: string;
remember: boolean;
error: string;
isLoading: boolean;
}
class LoginView extends React.Component<{}, ILoginState> {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
remember: false,
error: '',
isLoading: false
};
}
render() {
return (<div>Login goes here</div>
);
}
}
export default LoginView;
I end up with a compile error:
ERROR in [at-loader] ./src/scripts/pages/LoginView.tsx:41:21
TS2345: Argument of type '{ [x: number]: any; }' is not assignable to parameter of type 'ILoginState | ((prevState: Readonly<ILoginState>, props: {}) => ILoginState | Pick<ILoginState, "...'.
Type '{ [x: number]: any; }' is not assignable to type 'Pick<ILoginState, "email" | "password" | "remember" | "error" | "isLoading">'.
Property 'email' is missing in type '{ [x: number]: any; }'.
I've also tried using 'any' in place of the empty brackets but that doesn't work either.
Here's the line 41 (this.SetState...) that the trace is referring to:
handleChange = event => {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
this.setState({
[target.name]: value
});
}
Here are all examples where that's used:
<input name="email" type="email" value={this.state.email} onChange={this.handleChange} />
<input name="password" type="password" value={this.state.password} onChange={this.handleChange} />
<input name="remember" type="checkbox" checked={this.state.remember} onChange={this.handleChange} />
Upvotes: 15
Views: 8497
Reputation: 1
If you do not have props you can just do that :
export interface IMyClassState {
menuItems: MenuItem[];
}
export default class MyClass extends Component <Record<string, never>, IMyClassState>{
constructor(props = {}) {
super(props);
this.state = {
menuItems: []
} as IMyClassState;
}
...
Upvotes: 0
Reputation: 5074
Option 1
class LoginView extends React.Component<{}, ILoginState> {
constructor({}) {
}
}
Option 2
class LoginView extends React.Component<null, ILoginState> {
constructor(null) {
}
}
Since props default value is an empty object, I personally prefer option 1.
Edit: it appears latest typescript versions do not support option 1. I'll suggest one of the following methods (tested on TS 3.7):
class LoginView extends React.Component<{}, ILoginState> {
constructor() {
super({});
}
}
// OR
class LoginView extends React.Component<{}, ILoginState> {
constructor(props = {}) {
super(props);
}
}
Thanks to @Andy who brought this update to my attention.
Upvotes: 12