是否可以推断第一个子元素的 props 并在 TypeScript 中强制执行它们?我可以接近它,但是泛型开始失败,而且我无法推断类型。
我正在尝试将组件道具从包装器传递到具有类型安全性的第一个子组件。当对象上不存在 prop 时,TS 应该失败,否则通过。
import React, {
Children,
isValidElement,
cloneElement,
ReactNode,
} from 'react';
interface WrapperProps<C> {
children: ReactNode;
// how can I make typeof Button generic/inferred from the code?
// firstChildProps: Partial<React.ComponentProps<typeof Button>>; // works with <C> removed
firstChildProps: Partial<React.ComponentPropsWithoutRef<C>>;
}
const Wrapper: React.FC<WrapperProps<typeof Button>> = ({
children,
firstChildProps,
}) => {
const firstChild = Children.toArray(children)[0];
if (isValidElement(firstChild)) {
// Clone the first child element and pass the firstChildProps to it
return cloneElement(firstChild, { ...firstChildProps });
} else {
return <>{children}</>;
}
};
interface ButtonProps {
disabled: boolean;
children: ReactNode;
}
const Button: React.FC<ButtonProps> = ({ disabled, children }) => {
return <button disabled={disabled}>{children}</button>;
};
const Example = () => {
return (
<>
{/* Passes type check because disabled exists on Button */}
<Wrapper firstChildProps={{ disabled: false }}>
<Button disabled={true}>Ok</Button>
</Wrapper>
{/* Fails type check because cheese does not exist on Button */}
<Wrapper firstChildProps={{ cheese: true }}>
<Button disabled={true}>Ok</Button>
</Wrapper>
</>
);
};
这是一个几乎可以使用的TS Playground。
您只需要向
WrapperProps<C>
添加通用约束 - 与 ComponentPropsWithoutRef<C>
具有的相同 - 即 ElementType
。
interface WrapperProps<C extends React.ElementType> {
children: ReactNode;
firstChildProps: Partial<React.ComponentPropsWithoutRef<C>>;
}