aha*_*aha 7 typescript reactjs
我正在尝试使用 TypeScript(2.8)中的React文档(React 16.3)中的HOC实现示例Consuming Context,并且失败了.作为参考,来自React手册的代码:
const ThemeContext = React.createContext('light');
// This function takes a component...
export function withTheme(Component) {
// ...and returns another component...
return function ThemedComponent(props) {
// ... and renders the wrapped component with the context theme!
// Notice that we pass through any additional props as well
return (
<ThemeContext.Consumer>
{theme => <Component {...props} theme={theme} />}
</ThemeContext.Consumer>
);
};
}
Run Code Online (Sandbox Code Playgroud)
我能想到的最好的:
export interface ThemeAwareProps {
theme: string;
}
const ThemeContext = React.createContext('light');
export function withTheme<P extends ThemeAwareProps, S>(Component: new() => React.Component<P, S>) {
return function ThemedComponent(props: P) {
return (
<ThemeContext.Consumer>
{theme => <Component {...props} theme={theme} />}
</ThemeContext.Consumer>
);
};
}
class App extends React.Component {
public render() {
return (
<ThemeContext.Provider value={'dark'}>
<ThemedButton/>
</ThemeContext.Provider>
);
}
}
Run Code Online (Sandbox Code Playgroud)
ThemedButton.tsx:
interface ThemedButtonProps extends ThemeAwareProps {
}
interface ThemedButtonState{
}
class ThemedButton extends React.Component<ThemedButtonProps, ThemedButtonState> {
constructor(props: ThemedButtonProps) {
super(props);
}
public render() {
return (
<button className={this.props.theme}/>
)
}
}
export default withTheme(ThemedButton);
Run Code Online (Sandbox Code Playgroud)
问题是最后一行(export default withTheme(ThemedButton)
).TypeScript编译器抱怨说
类型的
typeof ThemedButton
参数不能分配给类型的参数new () => Component<ThemedButtonProps, ThemedButtonState, any>
.
我错过了什么?
kin*_*aro 15
大部分都是正确的,只是缺少一些东西:
for Component
,use React.ComponentType<Props>
,正确接受类组件和功能组件.我认为new () => ...
单独使用在这里不起作用,因为签名没有完全匹配.
要ThemedButton
在使用道具时排除道具,您必须使用一些神奇的语法:
function ThemedComponent(props: Pick<P, Exclude<keyof P, keyof ThemeAwareProps>>)
Run Code Online (Sandbox Code Playgroud)
这是这样做的:
Exclude<keyof P, keyof ThemeAwareProps>
意思是"获取钥匙P
,然后带走钥匙ThemeAwareProps
"Pick<P, ...>
然后说,"从P
,返回一个只有这些属性的对象类型"结合这些为我们提供了一个组件,它接受所有的道具ThemedButton
,减去theme
道具,这样我们就可以做到<ThemedButton />
没有错误.
这是完整的HOC:
function withTheme<P extends ThemeAwareProps>(Component: React.ComponentType<P>) {
return function ThemedComponent(props: Pick<P, Exclude<keyof P, keyof ThemeAwareProps>>) {
return (
<ThemeContext.Consumer>
{(theme) => <Component {...props} theme={theme} />}
</ThemeContext.Consumer>
)
}
}
Run Code Online (Sandbox Code Playgroud)
最后,关于这个主题的一篇好博文,我从中发现了大部分这些信息.如果您愿意,它还包括一种缩短类型的Pick<...>
东西的方法Omit
.
编辑:休息/传播的行为在3.2中已经改变,并且这个bug出现了一个不幸的副作用,导致在props
与其他道具合并时被删除的类型.目前正在使用的解决方法是转换props
为P
:
return (
<ThemeContext.Consumer>
{(theme) => <Component {...props as P} theme={theme} />}
</ThemeContext.Consumer>
)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2373 次 |
最近记录: |