【问题标题】:React & Typescript: Intersection type with Higher Order Control & Generic TypeReact & Typescript:具有高阶控制和通用类型的交集类型
【发布时间】:2017-06-14 03:52:56
【问题描述】:

当我使用具有此高阶的泛型类型时出现此错误 React 和 TypeScript 中的控制(使用 @types/react 15.0.27):

TS2322:Type '{}' is not assignable to type 'IntrinsicAttributes & 
IntrinsicClassAttributes<Component<ITypeComponentProps, ComponentState>> & ...'.
     Type '{}' is not assignable to type 'Readonly<ITypeComponentProps>'.
     Property 'data' is missing in type '{}'.

我希望我的 withTestData 函数返回 React.ComponentClass&lt;ITestComponentProps&gt; 类型的控件(即使用空道具),但它告诉我需要在道具中传递 data。但是,当我替换泛型类型 ITypeTestProps&lt;TData&gt; 时,它按预期工作 下面是非泛型类型ITypeTestProps,TData 是string

withTestData 看起来有点令人费解,但它做了一些相当简单的事情——它需要一个组件,该组件需要 P &amp; ITypeTestProps&lt;TData&gt; 类型的 props 和 将它包装在一个组件中,该组件需要 P 类型的 props。在这个测试用例中,PITestComponentProps

这是有错误的版本:

import * as React from "react";
import {mount} from "enzyme";

interface ITestComponentProps {}

type HOC<PWrapped, PHoc> = React.ComponentClass<PWrapped & PHoc> | 
    React.SFC<PWrapped & PHoc>;

export interface ITypeTestProps<TData> {
    data: TData;
}

export function withTestData<P, S, TData>(Component: HOC<P, 
    ITypeTestProps<TData>>, data: TData):
    React.ComponentClass<P> {

    class C extends React.Component<P & ITypeTestProps<TData>, S> {

        public render(): JSX.Element {
            return (
                <Component data={data} {...this.props as any} />
            );
        }
    }
    return C;
}

type ITypeComponentProps = ITestComponentProps & ITypeTestProps<String>;

class TestComponent extends React.Component<ITypeComponentProps, {}> {
    public render(): JSX.Element {
        return (<div>Hello, {this.props.data}</div>);
    }
}

describe("withTestData()", () => {

    it("wraps a component", () => {
        const data: string = "World";
        const WrappedTestComponent = withTestData(TestComponent, data);
        // The type mismatch occurs here:
        const wrapper = mount(<WrappedTestComponent />);
        expect(wrapper.text()).toContain(`Hello, ${data}`);
    });

});

我可以通过像这样强制转换控件来解决它,但我想消除强制转换:

const WrappedTestComponent = withTestData(TestComponent, data) as 
    React.ComponentClass<ITestComponentProps>

编辑

这是一个按我预期工作的版本——它从生成的界面中删除“数据”。唯一的区别是类型不是泛型的。

import * as React from "react";
import {mount} from "enzyme";

interface ITestComponentProps {}

type HOC<PWrapped, PHoc> = React.ComponentClass<PWrapped & PHoc> |
    React.SFC<PWrapped & PHoc>;

export interface ITypeTestProps {
    data: string;
}

export function withTestData<P, S, TData>(Component: HOC<P, ITypeTestProps>, data: TData):
    React.ComponentClass<P> {

    class C extends React.Component<P & ITypeTestProps, S> {

        public render(): JSX.Element {
            return (
                <Component data={data} {...this.props as any} />
            );
        }
    }
    return C;
}

type ITypeComponentProps = ITestComponentProps & ITypeTestProps;

class TestComponent extends React.Component<ITypeComponentProps, {}> {
    public render(): JSX.Element {
        return (<div>Hello, {this.props.data}</div>);
    }
}

describe("withTestData()", () => {

    it("wraps a component", () => {
        const data: string = "World";
        const WrappedTestComponent = withTestData(TestComponent, data);
        // The type mismatch occurs here:
        const wrapper = mount(<WrappedTestComponent />);
        expect(wrapper.text()).toContain(`Hello, ${data}`);
    });

});

从零开始运行这个例子:

$ npm install -g create-react-app
$ create-react-app my-app --scripts-version=react-scripts-ts
$ cd my-app/
$ npm install @types/react@15.0.27 enzyme --dev

将以上代码复制到文件src/demo.test.tsx

$ npm test

【问题讨论】:

    标签: reactjs typescript generics


    【解决方案1】:

    错误是正确地警告你没有为ITypeTestProps接口的强制属性提供值。

    因此,为了摆脱问题(如果您的业务逻辑没有问题也可以),您可以在ITypeTestProps 接口中将data 声明为可选属性:

    export interface ITypeTestProps<TData> {
        data?: TData;
    }
    

    【讨论】:

    • 谢谢,我理解它返回的错误,但我认为它被错误地报告了---我添加了另一个例子来澄清差异。
    • 嗯。这很奇怪。作为一种解决方法,尽管您可以让您的 withTestData 返回 React.ComponentClass&lt;P &amp; ITypeTestProps&gt; 这样您将得到预期的正确错误
    猜你喜欢
    • 2019-07-25
    • 2018-08-08
    • 2021-11-23
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-17
    相关资源
    最近更新 更多