TypeScript Rest Props - 允许任何 props 或告诉组件它们将成为哪些 props



我正在用TypeScript构建一个React应用程序。我有一个RequiresPermission组件,它基于谓词,应该呈现一个或另一个组件并转发所有道具。

type Props = {
NotPermittedComponent: React.ComponentType;
PermittedComponent: React.ComponentType;
isPermitted: boolean;
};
const RequiresPermisson = ({
NotPermittedComponent,
PermittedComponent,
isPermitted,
...rest
}: Props) =>
isPermitted ? (
<PermittedComponent {...rest} />
) : (
<NotPermittedComponent {...rest} />
);
export default RequiresPermisson;

当我渲染组件时,TypeScript在:中大喊RequiresPermission

const PERMITTED_TEXT = 'permitted';
const NOT_PERMITTED_TEXT = 'not-permitted';
type TestPropsProps = {
text: string;
};
const NotPermittedTestComponent: React.FunctionComponent<TestPropsProps> = ({
text,
}) => (
<div>
<span>{NOT_PERMITTED_TEXT}</span>
{text}
</div>
);
const PermittedTestComponent: React.FunctionComponent<TestPropsProps> = ({
text,
}) => (
<div>
<span>{PERMITTED_TEXT}</span>
{text}
</div>
);
const createProps = ({
NotPermittedComponent = NotPermittedTestComponent,
PermittedComponent = PermittedTestComponent,
isPermitted = false,
text = 'foo',
} = {}) => ({
NotPermittedComponent,
PermittedComponent,
isPermitted,
text,
});
const props = createProps();
render(<RequiresPermission {...props} />);

说:

Type '{ NotPermittedComponent: FunctionComponent<TestPropsProps>; PermittedComponent: FunctionComponent<TestPropsProps>; isPermitted: boolean; text: string; }' is not assignable to type '{ NotPermittedComponent: ComponentType<{}>; PermittedComponent: ComponentType<{}>; isPermitted: boolean; }'.
Types of property 'NotPermittedComponent' are incompatible.
Type 'FunctionComponent<TestPropsProps>' is not assignable to type 'ComponentType<{}>'.
Type 'FunctionComponent<TestPropsProps>' is not assignable to type 'FunctionComponent<{}>'.
Types of parameters 'props' and 'props' are incompatible.
Type '{ children?: ReactNode; }' is not assignable to type 'PropsWithChildren<TestPropsProps>'.
Property 'text' is missing in type '{ children?: ReactNode; }' but required in type 'TestPropsProps'.

我也尝试过将Record<string, unknown>作为props,但这也不起作用。

如何修复此问题以传递道具或允许任何(不是类型any(道具,从而使...rest参数正常工作?

不确定这是否是最优雅的解决方案,但我刚刚组合了所有的道具类型。这样可以检查所有道具的类型。我必须转发所有的道具,因为我无法确保子组件上不需要isPermitted之类的东西。

interface Props <A, B>{
NotPermittedComponent: React.ComponentType<A>;
PermittedComponent: React.ComponentType<B>;
isPermitted: boolean;
}
const RequiresPermisson = <A, B>(props: Props<A, B> & A & B): JSX.Element => {
const {
NotPermittedComponent,
PermittedComponent,
isPermitted,
} = props
return isPermitted ? (
<PermittedComponent {...props} />
) : (
<NotPermittedComponent {...props} />
)
}

您需要typescript中的泛型类型:https://www.typescriptlang.org/docs/handbook/generics.html

简而言之,这些是动态类型,取决于输入的内容。

在下面的代码中,我们将所有传递给类型T的道具分配给typescript,并告诉typescript这些道具是:required propsNotPermittedComponentPermittedComponentisPermitted和所有的rest,在这种情况下成为T型

type Props = {
NotPermittedComponent: React.ComponentType;
PermittedComponent: React.ComponentType;
isPermitted: boolean;
};
const RequiresPermisson = <T extends Record<string, unknown>>({
NotPermittedComponent,
PermittedComponent,
isPermitted,
...rest
}: Props & T) =>
isPermitted ? (
<PermittedComponent {...rest} />
) : (
<NotPermittedComponent {...rest} />
);
export default RequiresPermisson;

最新更新