我想使用material-ui,同时使用react和Typescript。我想将属性传递给组件,但无法弄清楚该怎么做。我正在使用material-UI存储库中的react-typescript示例。我尝试的方法如下:
添加属性界面:
const styles = (theme: Theme) =>
createStyles({
root: {
textAlign: 'center',
paddingTop: theme.spacing.unit * 20,
},
});
interface IndexProps
extends WithStyles<typeof styles> {
myText: string;
}
然后定义我的组件,并使用属性:
class Index extends React.Component<IndexProps> {
render() {
return (
<div className={this.props.classes.root}>
<Typography variant="display1" gutterBottom>
Material-UI
</Typography>
<Typography variant="subheading" gutterBottom>
example project text=[{this.props.myText}]
</Typography>
<Button variant="raised" color="secondary" >
Super Secret Password
</Button>
</div>
);
}
}
export default withRoot(withStyles(styles)(Index));
在“索引”页面上,我输入:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Index from './pages/index';
ReactDOM.render(<Index myText="Foo" />, document.querySelector('#root'));
但是出现编译错误:
(5,18): Type '{ myText: string; }' has no properties in common with type 'IntrinsicAttributes'.
我在这里做错了什么?任何帮助将不胜感激
为完整起见,我的packages.json
文件是:
{
"name": "create-react-app-with-typescript",
"version": "0.1.0",
"private": true,
"main": "src/index.tsx",
"dependencies": {
"@material-ui/core": "latest",
"@types/react": "*",
"@types/react-dom": "*",
"react": "latest",
"react-dom": "latest",
"react-scripts-ts": "latest"
},
"devDependencies": {
"@types/jest": "*",
"@types/node": "*",
"typescript": "latest"
},
"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
}
}
答案 0 :(得分:1)
我假设您正在使用this definition of withRoot
。如果将鼠标悬停在对withRoot
的呼叫上,则会看到其返回类型为:
(props: object) => JSX.Element
这是错误的:道具类型应为{myText: string}
,而不是object
。如果转到withRoot
的定义,您将看到它的来源:
function withRoot(Component: React.ComponentType) {
function WithRoot(props: object) {
这些行应替换为:
function withRoot<P>(Component: React.ComponentType<P>) {
function WithRoot(props: P) {
您可以考虑在原始示例中发送拉取请求以解决此问题。
(请参阅注释中的示例)
事实证明这与根本原因无关。我在src/App.tsx
第60行看到了错误:
let drawer = <ItemsList myText="asdf" history={history} />;
请参考src/components/ItemsList.tsx
底部的定义:
export default withStyles(styles)<{}>(connect(mapStateToProps)(withWidth()(ItemsList))
);
对于初学者,请摆脱该显式类型参数<{}>
,该参数将覆盖自动确定的所有参数;令我惊讶的是,它本身并没有给您带来任何错误。然后App.tsx
中的错误变为location
道具丢失。您可能已经认识到它是RouteComponentProps
之一,但是我没有,所以我通过将以下内容添加到ItemsList.tsx
中来着手研究最终组件的整个道具集:
type PropsOf<C> = C extends React.ComponentType<infer P> ? P : never;
const ItemsListWrapped = withStyles(styles)(connect(mapStateToProps)(withWidth()(ItemsList));
type FinalProps = PropsOf<typeof ItemsListWrapped>;
let x: FinalProps;
x. // look at completion menu here (Ctrl-Space in Visual Studio Code)
不幸的是,这些复杂的类型操作导致类型表达式难以理解,甚至在悬停弹出窗口中被截断,所以我发现查看所有道具的最佳方法是查看完成菜单,如下指示。然后,我们看到四个意外的道具:history
,location
,match
和staticContext
。如果我们查看这些来源可能来自的所有地方,希望它们可以被识别为来自ItemsList.Props extends RouteComponentProps<void>
。确实,该声明是错误的,因为您没有使用ItemsList
作为路线组件,也没有手动传递所有这些道具,ItemsList
实际上也没有使用除history
之外的任何道具。您再次声明(并通过)。因此,只需从扩展列表中删除RouteComponentProps<void>
。
我们已经看到,使用包装好的React组件时发生类型错误可能有许多不同的原因。希望我对您有所了解,您自己也可以找到此类错误。