我试图在React组件上使用Material UI 1.0(beta)@withStyles注释。文档提供了一个Javascript示例(https://material-ui-1dab0.firebaseapp.com/customization/css-in-js),但它在Typescript中给出了编译错误。它实际上发出正常,应用程序运行正常,所以我只是试图摆脱IDE的错误!
这是我的代码:
y
这会出错:
@withStyles(styles)
class MyComponent extends React.Component<any, any> {
manager: any;
...
}
我真的不明白这个错误。我可以使用这样的替代非注释版本:
TS1238: Unable to resolve signature of class decorator when called as an expression.
Type 'ComponentClass<StyledComponentProps<{}>>' is not assignable to type 'typeof MyComponent'.
Type 'Component<StyledComponentProps<{}>, ComponentState>' is not assignable to type 'MyComponent'.
Property 'manager' is missing in type 'Component<StyledComponentProps<{}>, ComponentState>'.
这个编译/运行没有问题。我喜欢使用注释,但我想了解错误。
任何建议表示赞赏!
答案 0 :(得分:4)
这意味着declared type of the @withStyles
decorator:
export default function withStyles<P = {}, ClassNames = {}>(
style: StyleRules | StyleRulesCallback,
options?: WithStylesOptions
): (
component: React.ComponentType<P & { classes: ClassNames; theme?: Theme }>
) => React.ComponentClass<P & StyledComponentProps<ClassNames>>;
实际上并不符合TypeScript对类装饰器的需求,这更像是:
declare function classDecorator(...args: any[]): <C> (c: C) => C;
合同非常严格:它要求函数输出为输入的子类型。这导致人们之前有problems。
如果一切都在运行时工作正常,你只想让类型检查器保持沉默,那么总是很好any
:
@(withStyles as any)(styles) // no error now
class MyComponent extends React.Component<any, any> {
manager: any;
...
}
或者,您可以继续尝试重新声明withStyles()
的类型,使其对装饰者更友好:
import { StyledComponentProps } from 'material-ui';
import { Theme } from 'material-ui/styles/createMuiTheme';
import { StyleRules, StyleRulesCallback, WithStylesOptions } from 'material-ui/styles/withStyles';
import { withStyles } from 'material-ui/styles'
declare module 'material-ui/styles' {
export function withStyles(
style: StyleRules | StyleRulesCallback,
options?: WithStylesOptions
): <C extends React.ComponentType<P & { classes: ClassNames; theme?: Theme }>, P = {}, ClassNames = {}> (
component: C
) => C & React.ComponentClass<P & StyledComponentProps<ClassNames>>;
}
@withStyles(styles) // no error now
class MyComponent extends React.Component<any, any> {
manager: any;
}
现在一切正常,因为我确保返回的值是MyComponent
构造函数的子类型。在你自己的项目中修复了很多别人的代码;我可能只是自己使用any
解决方案。
是否有人想联系Material UI folks并建议更新定义取决于他们。我认为自己对React等人的知识不足。了解我的修改声明是否合适。
无论如何,希望有所帮助;祝你好运!
答案 1 :(得分:1)
我无法使用@ jcalz的类型定义,因为它与现有的定义冲突,所以我创建了一个包装函数。
classes
上需要WithStyles
也会让使用装饰组件变得很痛苦,所以我将其设为可选项。
// withStyles.ts
import { Theme } from 'material-ui/styles';
import _withStyles, {
ClassNameMap,
StyledComponentProps,
StyleRules,
StyleRulesCallback,
WithStylesOptions,
} from 'material-ui/styles/withStyles';
export interface WithStyles<ClassKey extends string = string> {
classes?: ClassNameMap<ClassKey>;
theme?: Theme;
}
// We need to fix the withStyles definition and we want to make WithStyles.classes optional,
// so we make our own.
export const withStyles = <ClassKey extends string>(
style: StyleRules<ClassKey> | StyleRulesCallback<ClassKey>,
options?: WithStylesOptions
) => <C extends React.ComponentType<P & WithStyles<ClassKey>>, P = {}>(component: C) => {
return (_withStyles as any)(style, options)(component) as C & React.ComponentType<P & StyledComponentProps<ClassKey>>;
};
要使用它,只需导入新的withStyles.ts
而不是material-ui
。
import { withStyles, WithStyles } from './withStyles';
@withStyles(styles)
export class MyClass extends React.Component<MyClassProps> {
render() {
// classes will always exist so use `!`.
const classes = this.props.classes!;
return (
<div className={classes.root} />
);
}
}