我正在制作一个React组件,它接受一系列其他React组件及其props .
type Components = [ComponentType, Props][]
我怎样才能写这个,以便类型脚本能够理解Props对象应该匹配给定的组件props ?
谢谢.
UPD,基本上,一个函数接受一个[fn,args]数组,并用相应的args调用每个fn.如何编写该函数的签名,以便二元组是类型安全的正确fn/arg对?
我正在制作一个React组件,它接受一系列其他React组件及其props .
type Components = [ComponentType, Props][]
我怎样才能写这个,以便类型脚本能够理解Props对象应该匹配给定的组件props ?
谢谢.
UPD,基本上,一个函数接受一个[fn,args]数组,并用相应的args调用每个fn.如何编写该函数的签名,以便二元组是类型安全的正确fn/arg对?
您可以做到这一点,尽管它有点复杂,并且在当前的实现中比我希望的更脆弱.我已经将类型逻辑抽象为助手类型:
// This part is reusable for any pair of [unaryFunction, argument]
type IsFnArgPair<T extends any> = T extends [infer F, infer A] ? F extends (x: A) => any ? T : [never, never] : [never, never]
function RenderChildPropPairs<T extends any[]>(props: { pairs: Array<IsFnArgPair<T>> }): JSX.Element {
return (
<>
{props.pairs.map(([Comp, props]) => <Comp {...props} />)}
</>
);
}
我们可以定义几个组件/props 对来测试这一点:
type MyComponentProps = { children: React.ReactNode, foo: number }
function MyComponent(props:MyComponentProps): JSX.Element {
return (
<div>
{String(props.foo)}
{props.children}
</div>
);
}
type MyOtherComponentProps = {
foo: boolean
}
function MyOtherComponent({ foo }: MyOtherComponentProps): JSX.Element {
return <div>{String(foo)}</div>;
}
然后测试它:
function RenderPass() {
// OK
return <RenderChildPropPairs pairs={[[MyComponent, { foo: 1, children: null }], [MyOtherComponent, { foo: true }]]} />
}
function RenderFail() {
// Fails as expected
return <RenderChildPropPairs pairs={[[MyComponent, { foo:'hi', children: null }], [MyOtherComponent, { foo: 1 }]]} />
}
这并不完美.特别是,有两个方面您可以改进:更好的智能感知(传递无效对的人只会得到"类型blah不能分配给类型‘never’"",这不是一个很好的错误消息.第二个是,如果您试图将这些对提取到变量中,您会看到推断存在问题,尽管使用satisfies
可以稍微减轻这个问题:
function LessOops() {
const pairs = [[MyComponent, { foo: 1, children: null }], [MyOtherComponent, { foo: true }]] satisfies Array<[any, any]>;
return <RenderChildPropPairs pairs={pairs} />
}
请注意,尽管是any
s,但这仍然是类型安全的:如果您传递无效的对,您将收到错误.
此解决方案的另一个问题是,如果您try 使用as const
将对数组输入为二元组,您会看到与as const
的readonly
度相关的错误.我会继续努力解决这个问题,尽管也许更聪明的人可以给出更好的解决方案.