我的团队已经为我们正在使用的API创建了typescript类型定义,所以我们不能碰源代码,只能碰定义。
我们有一个称为add
的函数,它本质上是向主程序添加一个或多个反应组件。对象的props
属性应取决于component
属性上列出的组件类型。
它看起来像这样:
add(arg1, arg2, {
//some other args
children: [{
id: string1,
//BackButton can be a functional or class-based component
component: BackButton,
//BackButtonProps will be defined within BackButton
props: BackButtonProps
},
{
id: string2,
//SkipButton can be a functional or class-based component
component: SkipButton,
//SkipButtonProps will be defined within SkipButton
props: SkipButtonProps
}
]
});
作为参考,有一个函数的替代(重载)版本,它只添加一个组件而不是多个组件,我已经能够找出它的typescript。它看起来像这样:
add<T>(
id: string,
component: ComponentType<T>,
props: T
): void;
我的问题是这样的——因为子组件的数量是未知的,我怎么能在add
函数上使用通用的,以便所有的子组件都是正确的类型(props
和component
属性匹配)?
add
的通用签名是这样的:
declare function add<T extends any[]>(arg1: any, arg2: any, arg3: {
children: [...{ [K in keyof T]: {
id: string,
component: T[K]
props: React.ComponentProps<T[K]>
}}]
}): void
泛型T
将存储一个元组,其中每个元素都是一个react组件。对于传入数组中索引为K
的每个元素,component
类型将用作T[K]
中的类型,props
类型必须为React.ComponentProps<T[K]>
。
让我们看看实际操作:
const BackButton = (props: {a: string}) => {
return <div></div>
}
const SkipButton = (props: {b: string}) => {
return <div></div>
}
add(0, 0, {
children: [
{
id: "1",
component: BackButton,
props: { a: "123" }
},
{
id: "2",
component: SkipButton,
props: { b: "123" }
},
{
id: "3",
component: SkipButton,
props: { a: "123" } // Error: Type '{ a: string; }' is not assignable to type '{ b: string; }'
}
]
})
游乐场