array 是object 的子类型,因此在打字稿中将array 作为object 传递已经很好了。
关于其他道具转换:您可以使用高阶组件来完成此操作,该组件采用“扩展”道具并将它们映射到它们的预期类型。打字稿类型并不太难。这变得棘手的部分是这样编写它,以便 javascript 代码知道要转换哪些道具,因为 typescript 类型在运行时被删除。
我提出的解决方案要求您指定要转换的道具的键。这不是我写过的最优雅的东西,但它确实有效!
const withExpandedProps = <Keys extends string, Converter extends (value: any) => any>(
keys: Keys[],
convert: Converter
) => <Props extends {}>(Component: React.ComponentType<Props>) => (
props: Omit<Props, Keys> & Record<Keys, Expanded<Converter>>
) => {
const newProps = Object.fromEntries(
Object.entries(props).map(([key, value]) => {
const mappedVal = (keys as string[]).includes(key)
? convert(value as any)
: value;
return [key, mappedVal];
})
) as Props;
return <Component {...newProps} />;
};
用作:
interface MyComponentProps {
num: number;
str: string;
obj: object;
}
const MyComponent: React.FC<MyComponentProps> = ({ num, str, obj }) => {
console.log({ num, str, obj });
return (
<div>
<div>#{num}</div>
<div>{str}</div>
<ul>
{Object.keys(obj).map((key) => (
<li key={key}>{key}</li>
))}
</ul>
</div>
);
};
const NewComponent = withExpandedProps(
// all variables in javascript have a toString property
["str"],
(value: any) => value.toString()
)(
withExpandedProps(
// convert strings to numbers -- might return NaN which is type number
["num"],
(value: string | number) =>
typeof value === "string" ? parseFloat(value) : value
)(MyComponent)
);
const Test = () => (
<NewComponent
num={"5"} // string | number
str={["one", "two"]} // any
obj={["one", "two"]} // object
/>
);
(稍后将编辑更多解释)