只允许特定元素作为 prop 由 Typescript 检查
Only allow a specific element as a prop checked by Typescript
如何定义只允许将特定元素类型作为 prop 传递给组件?
假设我有一个组件,它有一个属性 divider
,它应该以某种方式输入,以便只有 <svg>
个元素可以传递给这个属性。
import { ElementType, ReactElement } from 'react';
type Props = {
divider: ReactElement<'svg'>;
};
export function SVGClipPathSection({ divider: Divider }: Props) {
return (
<div>
<Divider />
Blub
</div>
);
}
这导致
JSX element type 'Divider' does not have any construct or call signatures.ts(2604)
什么类型合适?
更新#1
type Props = {
divider: SVGElement;
};
export function SVGClipPathSection({ divider }: Props) {
return <div>{divider}</div>;
}
这导致:
error TS2322: Type 'SVGElement' is not assignable to type 'ReactNode'.
Type 'SVGElement' is missing the following properties from type 'ReactPortal': key, type, props
6 return <div>{divider}</div>;
~~~~~~~~~
node_modules/@types/react/index.d.ts:1375:9
1375 children?: ReactNode | undefined;
~~~~~~~~
The expected type comes from property 'children' which is declared here on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'
您可以使用HTML 元素接口来定义元素类型。
因此,对于您的示例,您可以将分隔符类型定义为 SVGElement
。
请参考这个,https://developer.mozilla.org/en-US/docs/Web/API#interfaces
type Props = {
divider: SVGElement;
}
我不认为你想做的是可能的。
但是,您可以遍历您的组件数组并过滤那些您想要的类型,如果有不需要类型的子项,可能会发出警告。
const filtered = divider.filter(e => React.isValidElement(e) && e.type === 'svg');
if (filtered.length !== divider.length) {
console.warn('divider elements must be of type <svg/>');
}
const typed = filtered as ReactElement<React.ComponentProps<'svg'>>[];
编辑: 您很好地解释了为什么您想要的东西在 中可能无法实现:
Any react functional component is just a function that has a specific
props type and returns JSX.Element
. This means that if you render the
component before you pass it a child, then react has no idea what
generated that JSX at all, and just passes it along.
And problem is that you render the component with the <MyComponent>
syntax. So after that point, it's just a generic tree of JSX nodes.
如何定义只允许将特定元素类型作为 prop 传递给组件?
假设我有一个组件,它有一个属性 divider
,它应该以某种方式输入,以便只有 <svg>
个元素可以传递给这个属性。
import { ElementType, ReactElement } from 'react';
type Props = {
divider: ReactElement<'svg'>;
};
export function SVGClipPathSection({ divider: Divider }: Props) {
return (
<div>
<Divider />
Blub
</div>
);
}
这导致
JSX element type 'Divider' does not have any construct or call signatures.ts(2604)
什么类型合适?
更新#1
type Props = {
divider: SVGElement;
};
export function SVGClipPathSection({ divider }: Props) {
return <div>{divider}</div>;
}
这导致:
error TS2322: Type 'SVGElement' is not assignable to type 'ReactNode'.
Type 'SVGElement' is missing the following properties from type 'ReactPortal': key, type, props
6 return <div>{divider}</div>;
~~~~~~~~~
node_modules/@types/react/index.d.ts:1375:9
1375 children?: ReactNode | undefined;
~~~~~~~~
The expected type comes from property 'children' which is declared here on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'
您可以使用HTML 元素接口来定义元素类型。
因此,对于您的示例,您可以将分隔符类型定义为 SVGElement
。
请参考这个,https://developer.mozilla.org/en-US/docs/Web/API#interfaces
type Props = {
divider: SVGElement;
}
我不认为你想做的是可能的。
但是,您可以遍历您的组件数组并过滤那些您想要的类型,如果有不需要类型的子项,可能会发出警告。
const filtered = divider.filter(e => React.isValidElement(e) && e.type === 'svg');
if (filtered.length !== divider.length) {
console.warn('divider elements must be of type <svg/>');
}
const typed = filtered as ReactElement<React.ComponentProps<'svg'>>[];
编辑: 您很好地解释了为什么您想要的东西在
Any react functional component is just a function that has a specific props type and returns
JSX.Element
. This means that if you render the component before you pass it a child, then react has no idea what generated that JSX at all, and just passes it along.And problem is that you render the component with the
<MyComponent>
syntax. So after that point, it's just a generic tree of JSX nodes.