是否有任何 TypeScript 解决方案,可以帮助我拥有“无限”数量的泛型类型,当然,无需键入所有类型?
示例如下:
type Args<T extends React.ComponentType<any>> = { component: T, presetProps: React.ComponentProps<T>};
function buildComponents<T extends React.ComponentType<any>>(...args: Args<T>[] ) : any
function componentJ({name, age}: {name: string, age: number}){
return <h1>123</h1>
}
function componentI({ age}: { age: number}){
return <h1>123</h1>
}
buildComponents({component:componentJ, presetProps:{name: "Jon", age: 12}},
{component: componentI, presetProps:{age: 44}})
使用此代码,我在 {component: componentI, presetProps:{age: 44}}
上遇到错误,因为它错过了 name
,但我希望它从 componentI
而不是从 {{ 1}},就是这种情况。
答案 0 :(得分:5)
您可能希望使 buildComponents
函数泛型化,而不是在要传递给 Args
的类型的 union 中,而是在此类类型的 tuple 中。编译器不希望从异构列表(其中元素可能具有不同类型)推断联合,因为这通常是一个错误:
function foo<T>(...args: T[]) { }
foo(1, 2, "3", 4); // error!
// -----> ~~~ string is not a number
另一方面,元组类型旨在支持异构列表:
function bar<T extends any[]>(...args: T) {}
bar(1, 2, "3", 4); // okay
那么让我们用 buildComponents()
试试:
declare function buildComponents<T extends React.ComponentType<any>[]>(
...args: { [I in keyof T]: Args<Extract<T[I], React.ComponentType<any>>> }
): any;
我在那里所做的是将 map the tuple type T
转换为一个新元组,以便每个元素 T[I]
变成 Args<T[I]>
。 the Extract
utility type 有一些技巧可以解决编译器错误(请参阅 microsoft/TypeScript#27995)。但它有效:
buildComponents(
{ component: componentJ, presetProps: { name: "Jon", age: 12 } },
{ component: componentI, presetProps: { age: 44 } }
); // okay
另一种方法是使 T
成为 props 类型的元组,而不是组件类型。干净一点:
declare function buildComponents<P extends any[]>(
...args: { [I in keyof P]: { component: React.ComponentType<P[I]>, presetProps: P[I] } }
): any;
并且还在呼叫站点工作:
buildComponents(
{ component: componentJ, presetProps: { name: "Jon", age: 12 } },
{ component: componentI, presetProps: { age: 44 } }
); // okay