Reputation: 66488
I have react app based on react-redux-typescript-boilerplate I've created this file:
import * as React from 'react';
import { connect } from 'react-redux';
import { RootState } from 'app/reducers';
export namespace LasarTitle {
export interface Props {
title: string;
loading: boolean;
};
};
@connect(
(state: RootState): LasarTitle.Props => {
return { title: state.title, loading: state.loading };
},
() => { }
)
export class LasarTitle extends React.Component<LasarTitle.Props> {
static defaultProps: Partial<LasarTitle.Props> = {
title: ''
};
constructor(props: LasarTitle.Props, context?: any) {
super(props, context);
}
render() {
const title = this.props.loading ? 'loading...' : this.props.title;
return (
<div>
<input readOnly={true} value={title} />
</div>
);
}
}
which is exactly the same as containers/App/index.tsx it have namespace and connect on component with the same name.
What's wrong with my code? I've didn't notice any typos or errors. What's the difference between my code and boilerplate?
Upvotes: 4
Views: 1095
Reputation: 249556
The error is pretty explicit. You just need to move the namespace declaration after the class.
import * as React from 'react';
import { connect } from 'react-redux';
import { RootState } from 'app/reducers';
@connect(
(state: RootState): LasarTitle.Props => {
return { title: state.title, loading: state.loading };
},
() => { }
)
export class LasarTitle extends React.Component<LasarTitle.Props> {
static defaultProps: Partial<LasarTitle.Props> = {
title: ''
};
constructor(props: LasarTitle.Props, context?: any) {
super(props, context);
}
render() {
const title = this.props.loading ? 'loading...' : this.props.title;
return (
<div>
<input readOnly={true} value={title} />
</div>
);
}
}
export namespace LasarTitle {
export interface Props {
title: string;
loading: boolean;
};
}
Since the namespace and the class have the same name, they will be merged. One of the things merging will do is that there will be only one object at runtime representing the combined class-namespace. For reason of implementation such a merger requires that the class object be created first and then namespace members be added to it.
Edit
If your namespace only contains types this rule will not be applied, if it contains code (such as function or variable declarations) the rule will apply. The boiler-plate works because it contains no code. While not obvious, your namespace does contain code, the ;
at the end of the interface will be transpiled to empty JS statements, and thus the rule is enforced.
The better solution would be to remove the ;
import * as React from 'react';
import { connect } from 'react-redux';
import { RootState } from 'app/reducers';
export namespace LasarTitle {
export interface Props {
title: string;
loading: boolean;
}
};
@connect(
(state: RootState): LasarTitle.Props => {
return { title: state.title, loading: state.loading };
},
() => { }
)
export class LasarTitle extends React.Component<LasarTitle.Props> {
static defaultProps: Partial<LasarTitle.Props> = {
title: ''
};
constructor(props: LasarTitle.Props, context?: any) {
super(props, context);
}
render() {
const title = this.props.loading ? 'loading...' : this.props.title;
return (
<div>
<input readOnly={true} value={title} />
</div>
);
}
}
Upvotes: 7