【发布时间】: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<ITestComponentProps> 类型的控件(即使用空道具),但它告诉我需要在道具中传递 data。但是,当我替换泛型类型 ITypeTestProps<TData> 时,它按预期工作
下面是非泛型类型ITypeTestProps,TData 是string。
withTestData 看起来有点令人费解,但它做了一些相当简单的事情——它需要一个组件,该组件需要 P & ITypeTestProps<TData> 类型的 props 和
将它包装在一个组件中,该组件需要 P 类型的 props。在这个测试用例中,P 是 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<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