假设我们有一个简单的React组件,它具有静态属性如meta
:
// RectTool.tsx
class Rect extends React.PureComponent
static meta = {
icon: <AnotherComponent />,
initial: {
width: 50,
height: 50,
},
};
render() {
return (
<div>Hello World</div>
);
}
}
然后在另一个组件中,我们将该组件引用为prop:
// DesignerUI.tsx
<Designer
tools={[Rect]}
/>
我们如何在<Designer />
中定义tools
道具的类型,以便typescript将是快乐。我现在正在做的是:
// DesignerUI.tsx
interface Props {
tools: Array<
React.PureComponent & {
meta: {
icon: JSX.Element;
initial: { width: number; height: number; strokeWidth: number };
};
}
>;
}
打字给了我这个错误:
Type 'typeof Rect' is not assignable to type 'PureComponent<{}, {}, any> & { meta: { icon: Element; initial: { width: number; height: number; strokeWidth: number; }; }; }'.
Type 'typeof Rect' is missing the following properties from type 'PureComponent<{}, {}, any>': context, setState, forceUpdate, render, and 3 more.ts(2322)
没有理由工具必须是React.PureComponent
。看起来你对工具对象的要求应该是:
- 可以使用JSX作为
<Rect/>
而不使用props来调用。 - 它有一个
meta
属性与适当的值
我建议您在顶层为ToolMeta
定义类型,并在Rect
和Designer
中使用它。你已经得到了initialValues
在一个地方和initial
在另一个地方的不匹配。一个好的ToolMeta
类型可以防止这种错误。
就我个人而言,我更喜欢将大多数接口保持在一级深度,并将子属性分解为它们自己的命名类型。
interface ToolInitialValues {
width: number;
height: number;
strokeWidth?: number;
}
interface ToolMeta {
icon: JSX.Element;
initialValues: ToolInitialValues;
}
我们可以在Rect
中使用这个类型来对meta
对象进行类型检查:
class Rect extends React.PureComponent {
static meta: ToolMeta = {
您的工具组件必须具有{ meta: ToolMeta }
以满足条件#2。对于条件#1,您将希望使用React.ComponentType
类型,这是函数组件或类组件的类型。您当前的React.PureComponent
类型实际上指的是实例,而不是类本身。
interface Props {
tools: Array<
React.ComponentType & { meta: ToolMeta }
>;
}
Typescript Playground Link