“任意”泛型类型

Ped*_*edo 3 typescript typescript-generics react-typescript

是否有任何 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}})
Run Code Online (Sandbox Code Playgroud)

使用此代码,我在 上出错{component: componentI, presetProps:{age: 44}},因为它错过了name,但我希望它从 中获取类型,componentI而不是从 中获取类型componentJ,就是这种情况。

jca*_*alz 5

您可能希望使您的buildComponents函数通用,而不是在要传递给的类型的联合Args,而是在此类类型的元组中。编译器不希望从异构列表(其中元素可能具有不同类型)推断联合,因为这通常是一个错误:

function foo<T>(...args: T[]) { }
foo(1, 2, "3", 4); // error!
// -----> ~~~ string is not a number
Run Code Online (Sandbox Code Playgroud)

另一方面,元组类型旨在支持异构列表:

function bar<T extends any[]>(...args: T) {}
bar(1, 2, "3", 4); // okay
Run Code Online (Sandbox Code Playgroud)

所以让我们尝试一下buildComponents()

declare function buildComponents<T extends React.ComponentType<any>[]>(
  ...args: { [I in keyof T]: Args<Extract<T[I], React.ComponentType<any>>> }
): any;
Run Code Online (Sandbox Code Playgroud)

我在那里所做的是将元组类型映射 T到一个新元组,以便每个元素都T[I]变成Args<T[I]>. 有一个繁琐位Extract实用型工作围绕编译器错误(见微软/打字稿#27995)。但它有效:

buildComponents(
  { component: componentJ, presetProps: { name: "Jon", age: 12 } },
  { component: componentI, presetProps: { age: 44 } }
); // okay
Run Code Online (Sandbox Code Playgroud)

另一种方法是创建Tprops 类型而不是组件类型的元组。它更干净一点:

declare function buildComponents<P extends any[]>(
  ...args: { [I in keyof P]: { component: React.ComponentType<P[I]>, presetProps: P[I] } }
): any;
Run Code Online (Sandbox Code Playgroud)

并在呼叫站点也工作:

buildComponents(
  { component: componentJ, presetProps: { name: "Jon", age: 12 } },
  { component: componentI, presetProps: { age: 44 } }
); // okay
Run Code Online (Sandbox Code Playgroud)

Playground 链接到代码