Typescript 键入工厂函数

Typescript 键入工厂函数,typescript,typescript-generics,Typescript,Typescript Generics,我有一个运行时构造的函数列表,这些函数使用参数初始化,并返回不同的内容: mythings: [ param => ({foo: param, bar: 2}), param => ({baz: param, qux: 4}), ] 现在我想写一个工厂函数来创建这些东西的子集,比如: const createThings = (things) => things.map(thing => thing("param")); 我正在努力输入工厂函数。我最近

我有一个运行时构造的函数列表,这些函数使用参数初始化,并返回不同的内容:

 mythings: [
   param => ({foo: param, bar: 2}),
   param => ({baz: param, qux: 4}),
 ]
现在我想写一个工厂函数来创建这些东西的子集,比如:

const createThings = (things) => things.map(thing => thing("param"));
我正在努力输入工厂函数。我最近的尝试如下所示:

// MyCreator?

const createThings = <T>(things: MyCreator<T>[]) =>
  things.map(thing => thing("param"));
//MyCreator?
const createThings=(things:MyCreator[])=>
things.map(thing=>thing(“param”);

但这一尝试并不奏效。有什么想法吗?

您可以使用映射数组/元组从数组中的每个项提取返回类型:

const mythings = [
   (param: string) => ({foo: param, bar: 2}),
   (param: string) => ({baz: param, qux: 4}),
 ]
type AllReturnTypes<T extends Array<(...a: any[])=> any>> = { 
    [P in keyof T]: T[P] extends (...a: any[])=> infer R?R:never
}

const createThings = <T extends Array<(...a: any[])=> any>>(things: T): AllReturnTypes<T> =>
  things.map(thing => thing("param") )as any; // assertion necessary unfortunately 

createThings(mythings) // ({ foo: string; bar: number; } | { baz: string; qux: number; })[]
或者在typescript 3.4中,您可以使用:


在createThings函数和客户端中都没有使用things,在上一个example@schneck,也许你是想在第二段代码中将创作者作为论据而不是神话来传递?@jo_va基本上,
mythings
是一个creators@schneck
mythings
在您的问题中是具有属性的对象
myfunction*
,但您将它们
things
用作函数。这是个错误吗?还有,当你说创建者时,这些只是常规函数或类构造函数?这对创建正确的类型很重要。@TitianCernicova Dragomir对,那是个错误,谢谢。创建者只是普通的函数,如
mythings
非常感谢您的回答!因为我必须使用TS 3.2,所以您的第一个建议是适用的。我刚刚添加了两个,还有两个工作,只剩下一件事:在开发时无法派生creator返回类型。如果我传入了一个特定的creator函数,有什么方法可以推断出来吗?@schneck映射元组是在3.1中引入的,所以除了最后一个之外,其他所有元组都可以工作。(即
作为常量
版本)
function tuple<T extends any[]>(...a: T) {
    return a;
}
const mythings = tuple(
    (param: string) => ({ foo: param, bar: 2 }),
    (param: string) => ({ baz: param, qux: 4 }),
)

let r = createThings(mythings) // [{ foo: string; bar: number; }, { baz: string; qux: number; }
const mythings = [
    (param: string) => ({ foo: param, bar: 2 }),
    (param: string) => ({ baz: param, qux: 4 }),
] as const