【问题标题】:How to type the use of Material-UI's `withStyles` decorator in the example?示例中如何键入 Material-UI 的 `withStyles` 装饰器?
【发布时间】:2018-11-04 05:57:33
【问题描述】:

我正在尝试弄清楚如何注释以下样式的类型(我从纯 JavaScript 转换为 TypeScript 并正在添加类型注释):

import * as React from 'react'
import { withStyles } from '@material-ui/core'

@withStyles(styles) // TYPE ERROR HERE
export default class App extends React.Component<{}, {}> {
    render(): JSX.Element {
        return (
            <div className="some-class"> Hello </div>
        )
    }
}

function styles() {
    return {
        // assume I need to use global styles, my actual project is more
        // complex and for some reasons I need to use global styles
        '@global': {
            '.some-class': {
                overflowX: 'hidden'
            },
        },
    }
}

我们如何输入这个?

起初,它给了我这样的错误:

        Types of property 'overflowX' are incompatible.
          Type 'string' is not assignable to type '"scroll" | "hidden" | "visible" | "auto" | "clip" | "-moz-initial" | "inherit" | "initial" | "revert" | "unset" | undefined'.

所以我将其更改为以下使用createStyles

import * as React from 'react'
import { withStyles, createStyles } from '@material-ui/core'

@withStyles(styles) // TYPE ERROR HERE
export default class App extends React.Component<{}, {}> {
    render(): JSX.Element {
        return (
            <div className="some-class"> Hello </div>
        )
    }
}

function styles() {
    return createStyles({
        // assume I need to use global styles, my actual project is more
        // complex and for some reasons I need to use global styles
        '@global': {
            '.some-class': {
                overflowX: 'hidden'
            },
        },
    })
}

现在我得到了这个错误:

tmp.tsx:5:1 - error TS1238: Unable to resolve signature of class decorator when called as an expression.
  Type 'ComponentClass<Pick<{}, never> & StyledComponentProps<"@global">, any>' is not assignable to type 'void | typeof App'.
    Type 'ComponentClass<Pick<{}, never> & StyledComponentProps<"@global">, any>' is not assignable to type 'typeof App'.
      Type 'Component<Pick<{}, never> & StyledComponentProps<"@global">, any, any>' is not assignable to type 'App'.
        Types of property 'render' are incompatible.
          Type '() => ReactNode' is not assignable to type '() => Element'.
            Type 'ReactNode' is not assignable to type 'Element'.
              Type 'undefined' is not assignable to type 'Element'.

5 @withStyles(styles) // TYPE ERROR HERE
  ~~~~~~~~~~~~~~~~~~~

在我实际的更复杂的代码中,错误类似,关于无法匹配Component 类型:

App.tsx:44:1 - error TS1238: Unable to resolve signature of class decorator when called as an expression.
  Type 'ComponentClass<Pick<AppProps, never> & StyledComponentProps<"@global">, any>' is not assignable to type 'void | typeof App'.
    Type 'ComponentClass<Pick<AppProps, never> & StyledComponentProps<"@global">, any>' is not assignable to type 'typeof App'.
      Type 'Component<Pick<AppProps, never> & StyledComponentProps<"@global">, any, any>' is not assignable to type 'App'.
        Property 'makeOnStatusWindowClick' is missing in type 'Component<Pick<AppProps, never> & StyledComponentProps<"@global">, any, any>'.

44 @withStyles(styles)
   ~~~~~~~~~~~~~~~~~~~

makeOnStatusWindowClick 是我的组件类中定义的第一个方法。

【问题讨论】:

    标签: typescript material-ui


    【解决方案1】:

    Daniel 链接到的 Material UI 文档

    很遗憾,由于当前 TypeScript 装饰器的限制,withStyles(styles) 不能用作 TypeScript 中的装饰器。

    所以我可以通过做两件事来让它工作:

    • 在我的styles函数的返回对象上使用createStyles(并且不要在函数上使用显式的返回类型定义,以便它使用createStyles生成的返回类型)
    • withStyles 用作而不是装饰器
    • 使用WithStyles 作为道具,使用自动检测到的styles 类型

    代码如下:

    import * as React from 'react'
    import { withStyles, WithStyles, createStyles } from '@material-ui/core'
    
    interface Props extends WithStyles<typeof styles> {}
    
    class App extends React.Component<Props, {}> {
        render(): JSX.Element {
            return (
                <div className="some-class"> Hello </div>
            )
        }
    }
    
    export default withStyles(styles)(App)
    
    function styles() /*: do not put a return type here */ {
        return createStyles({
            // assume I need to use global styles, my actual project is more
            // complex and for some reasons I need to use global styles
            '@global': {
                '.some-class': {
                    overflowX: 'hidden'
                },
            },
        })
    }
    

    【讨论】:

    • 谢谢,Props extends WithStyles 是缺失的部分。它甚至是工作宽度本地样式,例如: const styles = (theme: Theme) => ({ root: { minWidth: 140 }});
    【解决方案2】:

    幸运的是,他们在这里有大量关于打字稿的文档https://material-ui.com/guides/typescript/

    你也没有提到你遇到的错误,所以很难知道哪里出了问题

    可能您的道具类型缺少classes 字段

    【讨论】:

    • 您好丹尼尔,感谢您的关注。我用错误更新了问题。
    • 啊,可能是因为那个文档说“很遗憾,由于 TypeScript 装饰器的当前限制,withStyles(styles) 不能用作 TypeScript 中的装饰器。”
    • 是的,似乎就是这样。所以只要styles函数使用createStyles,并且我不使用withStyles作为装饰器,就可以了。
    猜你喜欢
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2020-06-21
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-11
    相关资源
    最近更新 更多