import type { evaluate, isAny, List } from "../../../dev/utils/src/main.js" import type { MorphAst, Out } from "../tuple.js" export type inferIntersection = [l] extends [never] ? never : [r] extends [never] ? never : [l & r] extends [never] ? never : isAny extends true ? any : l extends MorphAst ? r extends MorphAst ? never : (In: evaluate) => Out : r extends MorphAst ? (In: evaluate) => Out : intersectObjects extends infer result ? result : never type intersectObjects = [l, r] extends [object, object] ? [l, r] extends [infer lList extends List, infer rList extends List] ? inferArrayIntersection : evaluate<{ [k in keyof l | keyof r]: k extends keyof l ? k extends keyof r ? inferIntersection : l[k] : r[k & keyof r] }> : l & r type inferArrayIntersection< l extends List, r extends List, result extends List = [] > = [l, r] extends [ [infer lHead, ...infer lTail], [infer rHead, ...infer rTail] ] ? inferArrayIntersection< lTail, rTail, [...result, inferIntersection] > : l extends [infer lHead, ...infer lTail] ? r extends [] ? // l is longer tuple than r, unsatisfiable never : inferArrayIntersection< lTail, r, [...result, inferIntersection] > : r extends [infer rHead, ...infer rTail] ? l extends [] ? // r is longer tuple than l, unsatisfiable never : inferArrayIntersection< l, rTail, [...result, inferIntersection] > : [number, number] extends [l["length"], r["length"]] ? [...result, ...inferIntersection[]] : result