【问题标题】:Typescript Compile Error: Type '{}' is not assignable to type 'T'Typescript 编译错误:类型“{}”不可分配给类型“T”
【发布时间】:2019-01-30 06:40:29
【问题描述】:

我正在使用带有 Typescript 的 React 创建高阶组件 (HOC),但无法理解 Typescript 编译器返回的错误。我已经解决了我的问题,但不明白为什么会这样。

对于这里发生的事情,如果有任何指导或建议,我将不胜感激。

我的错误是:类型“{}”不可分配给类型“T”

我已经阅读了多篇关于类型解析问题的帖子,在大多数情况下,Typescript 似乎只是在做它的工作。我有一种感觉,这里就是这种情况,但是,我不明白我做错了什么。我试过弄乱类型签名,在这些情况下,它要么没有解决这个问题,要么把错误推到了引用代码上。

代码生成错误

import React, { Component, ComponentType } from 'react';

const withClass = <T extends object>(WrappedComponent: ComponentType<T>, className: string):
    React.FunctionComponent<T> =>
        (props: any) => (
            <div className={className}>
                <WrappedComponent />
            </div>
        );

export default withClass;

带有 Fix 的代码(注意 props 作为参数传播到被包装的组件)

import React, { Component, ComponentType } from 'react';

const withClass = <T extends object>(WrappedComponent: ComponentType<T>, className: string):
    React.FunctionComponent<T> =>
        (props: any) => (
            <div className={className}>
                <WrappedComponent {...props} />
            </div>
        );

export default withClass;

我希望第一段代码能够正确编译,但事实并非如此。为什么?

【问题讨论】:

    标签: reactjs typescript higher-order-components


    【解决方案1】:

    据我所知,因为这是一个函数组件,你应该为 props 操心。我认为如果您在调用构造函数方法 super(props) 的类组件中默认使用类组件,问题将会消失。我遇到了同样的错误,但是使用样式道具(CSSModules),实际上,我选择了特定的道具并且没有在我的组件中传递其余道具(...rest)。所以我认为因为你正在扩展 TypeScript 接口(我不确定)你没有传递所需的道具。在传播之后,您将传递所需的道具。备注:spread attributes

    【讨论】:

    • "因为这是一个函数组件,你应该为 props 操心。" - 这是我尝试的第一件事。如果没有 HOC 上的 props 属性,我仍然会遇到同样的错误。
    • @BrutalSimplicity 那是个问题,你有一个 T 道具,但不要通过它
    • 我想我可能误解了你的回答。当然,既然我明白了我的错误,你的答案对我来说更清楚了!
    • @BrutalSimplicity 对不起我的错误解释)
    【解决方案2】:

    也许我跳得太快了,因为我的错误突然变得非常明显!

    因此,HOC 的整个想法是能够通过组合来扩展组件的行为。如果您来自 OO 背景,这是规范的装饰器模式,但通过函数组合而不是对象进行配置。

    上面第一个示例的问题是 Typescript 抱怨我已将包装的组件标记为具有 T 道具,但我没有使用 any 道具实例化该组件!

    获胜者去...打字稿!

    Typescript 试图引导我走上正确的道路,但当然,我不想听,并试图将责任推回 Typescript。尽管如此,我必须承认,Typescript 规范目前似乎正在演变为类型杂技。 HOC 在这方面当然没有帮助。

    对于那些可能不幸也碰到这个心理障碍的人来说。这是最终的解决方案,并附有屏幕截图,以便更好地理解我上面所说的内容。

    上面的第二种解决方案有效,但在道具上使用T 会更合适。在这里,我使用控制台记录传递给包装组件的道具。

    import React, { Component, ComponentType } from 'react';
    
    const withClass = <T extends object>(WrappedComponent: ComponentType<T>, className: string):
        React.FunctionComponent<T> =>
            (props: T) => {
                console.log(props);
                return (
                    <div className={className}>
                        <WrappedComponent {...props} />
                    </div>
                );
            }
    
    export default withClass;
    

    【讨论】:

      猜你喜欢
      • 2018-09-19
      • 2020-07-04
      • 2021-11-16
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 2021-07-06
      • 1970-01-01
      • 2020-11-09
      相关资源
      最近更新 更多