Typescript 表示接受一个对象数组并返回一个包含所有键的并集的单个对象的函数

Typescript 表示接受一个对象数组并返回一个包含所有键的并集的单个对象的函数,typescript,types,Typescript,Types,我有一个javascript函数,它接受0个或多个类型为{string=>async fn*(…)=>…}的对象数组(注意*-它们是异步生成器函数) 该函数返回单个对象,该对象是每个输入对象中所有键集的并集,值是异步函数(而不是生成器),与每个输入对象的API匹配-此处的要求是,如果两个输入对象共享一个键,则它们还必须完全共享函数原型 例如: 函数makeAggregateObject(对象){…} 常数鱼={ swim:async函数*(距离){return distance>10;},//(

我有一个javascript函数,它接受0个或多个类型为
{string=>async fn*(…)=>…}
的对象数组(注意
*
-它们是异步生成器函数)

该函数返回单个对象,该对象是每个输入对象中所有键集的并集,值是异步函数(而不是生成器),与每个输入对象的API匹配-此处的要求是,如果两个输入对象共享一个键,则它们还必须完全共享函数原型

例如:

函数makeAggregateObject(对象){…}
常数鱼={
swim:async函数*(距离){return distance>10;},//(number)=>boolean
骰子:异步函数*(){}/()=>void
};
常数猫={
die:async函数*(){this.lifes-=1;}/()=>void
};
常数人={
walk:async函数*(步骤,跃点){…}/(数字,布尔)=>void
swim:async函数*(距离){return false;}//(number)=>boolean
};
const aggregate=makeAggregateObject([
人、猫、鱼
]);
控制台日志(聚合);
/*
{
swim:async函数(number)=>boolean,
walk:async函数(数字,布尔)=>void,
die:async function()=>void
}
*/
正如我前面提到的,在我将例如
die(number)=>boolean
添加到上面的
human
中的情况下,这将被视为一个错误(当然在Javascript中,没有办法实际执行这一点,但我希望在Typescript中执行),因为原型
(number)=>boolean
与之前定义的
()=>void
原型不匹配


这在Typescript中可能吗?我将如何执行此操作?

您可以在
makeAggregateObject
上使用泛型类型强制执行此操作。生成器的问题并不是一个真正的问题,这将强制所有公共属性具有兼容的类型

我们将使用类型参数
T
在元组类型中捕获所有参数类型。然后我们说参数必须是
T
(这就是我们如何将参数类型转换为
T
),但它也必须是一种类型,其中每个元素都是元组中所有类型的交集。基本上,如果typescript从参数推断出
T=[A,B]
,那么该参数也必须是
Array AsyncGenerator?(…p:p)=>承诺:永不
}
函数makeAggregateObject(对象:T&Partial[]):makeAggregateObject{
返回空值!
}

您可以在
makeAggregateObject
上使用泛型类型强制执行此操作。生成器的问题并不是一个真正的问题,这将强制所有公共属性具有兼容的类型

我们将使用类型参数
T
在元组类型中捕获所有参数类型。然后我们说参数必须是
T
(这就是我们如何将参数类型转换为
T
),但它也必须是一种类型,其中每个元素都是元组中所有类型的交集。基本上,如果typescript从参数推断出
T=[A,B]
,那么该参数也必须是
Array AsyncGenerator?(…p:p)=>承诺:永不
}
函数makeAggregateObject(对象:T&Partial[]):makeAggregateObject{
返回空值!
}

请注意,异步生成器函数不只是返回
number
、或
boolean
void
等,它们返回
AsyncGenerator
请注意,异步生成器函数不只是返回
number
、或
boolean
void
等。,他们返回了
AsyncGenerator
很好的添加
cat.lifes=9
Hi-这很有效,但几乎没有成功!我完全忘记了返回函数类型是异步函数,而不是异步生成器。输入是具有异步生成器值的对象数组,但返回值不是生成器。希望这是有意义的-我已经更新了问题以反映这一点。在本例中,类型看起来如何?对于上下文,这是我尝试应用类型的目的。关于生成器类型/用法以及
yield
的使用方式有非常具体的规则,我现在意识到这可能不像我最初的问题那样简单。不过,现在回答编辑后的问题就足够了。由你决定:)但要先发制人地奖励奖金,因为对于最初提出的问题,答案是正确的@莫尼卡被虐待了。。源对象包含异步生成器函数(例如
AsyncGenerator
),结果对象包含异步函数,并且这些函数的返回应该是(
Promise
)?如果发电机的返回类型不同怎么办?很好地添加了
cat.lifes=9
Hi-这很有效,但几乎没有成功!我完全忘记了返回函数类型是异步函数,而不是异步生成器。输入是具有异步生成器值的对象数组,但返回值不是生成器。希望这是有意义的-我已经更新了问题以反映这一点。在本例中,类型看起来如何?对于上下文,这是我尝试应用类型的目的。关于生成器类型/用法以及
yield
的使用方式有非常具体的规则,我现在意识到这可能不像我最初的问题那样简单。不过,现在回答编辑后的问题就足够了。由你决定:)但要先发制人地奖励奖金,因为对于最初提出的问题,答案是正确的@莫尼卡被虐待了。。源对象包含异步生成器函数(例如
AsyncGenerator
),结果对象包含异步函数,并且这些函数的返回应该是(
Promise
)?如果Generator的返回类型
type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

function makeAggregateObject<T extends [any] | any[]>(objects: T & Partial<UnionToIntersection<T[number]>>[]) :UnionToIntersection<T[number]> { 
    return null!
}

const fish = {
    swim: async function*(distance: number) { return distance > 10; }, // (number) => boolean
    die: async function*() { } // () => void
};

const cat = {
    lives: 9,
    die: async function*() { /* this.lives -= 1; */ } // () => void
};

const human = {
    walk: async function*(steps: number, hop: boolean) { }, // (number, boolean) => void
    swim: async function*(distance: number) { return false; }, // (number) => boolean
    // die: (n : number) =>true // uncomment this and you get an error 
};

const aggregate = makeAggregateObject([
    human,
    cat,
    fish
]);


// const aggregate: {
//     swim: (distance: number) => AsyncGenerator<never, boolean, unknown>;
//     die: () => AsyncGenerator<never, void, unknown>;
// } & {
//     lives: number;
//     die: () => AsyncGenerator<never, void, unknown>;
// } & {
//     walk: (steps: number, hop: boolean) => AsyncGenerator<never, void, unknown>;
//     swim: (distance: number) => AsyncGenerator<never, boolean, unknown>;
// }

aggregate.swim(0) // ok
aggregate.die() // also ok 
console.log(aggregate);
function makeAggregateObject<T>(objects: T[] & Partial<UnionToIntersection<T>>[]) :UnionToIntersection<T> { 
    return null!
}

type MakeAggregateObject<T> = {
    [P in keyof T]: T[P] extends (...p: infer P) => AsyncGenerator<never, infer R, any> ? (...p: P)=> Promise<R> : never
}
function makeAggregateObject<T extends [any] | any[]>(objects: T & Partial<UnionToIntersection<T[number]>>[]) :MakeAggregateObject<UnionToIntersection<T[number]>> { 
    return null!
}