簡體   English   中英

React&Typescript:具有高級控制和通用類型的交叉點類型

[英]React & Typescript: Intersection type with Higher Order Control & Generic Type

當我在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<ITestComponentProps>的控件(即帶有空道具),但這告訴我我需要在道具中傳遞data 但是,當我將以下通用類型ITypeTestProps<TData>替換為非通用類型ITypeTestProps並將TData替換為string類型時,它可以按預期工作。

withTestData看起來有點withTestData費解,但是它做起來相當簡單-它需要一個期望類型為P & ITypeTestProps<TData>道具的組件,並將其包裝在一個期望類型為P道具的組件中。 在此測試用例中, 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

錯誤已正確警告您錯過了為ITypeTestProps接口的必需屬性提供值的ITypeTestProps

因此,為了解決該問題(如果您的業務邏輯可以沒有問題),可以在ITypeTestProps接口ITypeTestProps data聲明為可選屬性:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM