{"record":{"id":"d98c2aa0723d5415","repo":"ReactiveX/rxjs","slug":"a-combinelatest-projection-requires-an-array-of-ob","errorCode":null,"errorMessage":"A combineLatest projection requires an array of observable values","messagePattern":"A combineLatest projection requires an array of observable values","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/rxjs/src/combine-latest.ts","lineNumber":81,"sourceCode":"    );\n    return project === undefined ? (combined as any) : combined[map]((values) => project(...values));\n  }\n\n  const actualSources: readonly ObservableValue<any>[] | { [key: string]: ObservableValue<any> } = Array.isArray(sources)\n    ? [...sources]\n    : { ...sources };\n\n  if (isSourceArray(actualSources)) {\n    const combined = this[combine](\n      actualSources.map((source) => ({\n        source,\n        requireFirstValue: requireAllValues,\n      }))\n    );\n    return project === undefined ? (combined as any) : combined[map]((values) => project(...values));\n  } else {\n    if (project !== undefined) {\n      throw new TypeError('A combineLatest projection requires an array of observable values');\n    }\n    const keys = Object.keys(actualSources);\n\n    return this[combine](\n      keys.map((key) => ({\n        source: actualSources[key]!,\n        requireFirstValue: requireAllValues,\n      }))\n    )[map]((values) => Object.fromEntries(keys.map((key, i) => [key, values[i]]))) as any;\n  }\n}\n\nfunction isSourceArray(sources: any): sources is readonly ObservableValue<any>[] {\n  return Array.isArray(sources);\n}\n","sourceCodeStart":63,"sourceCodeEnd":97,"githubUrl":"https://github.com/ReactiveX/rxjs/blob/54796b38a57e6309f9861e174737479bb3f63f61/packages/rxjs/src/combine-latest.ts#L63-L97","documentation":"In RxJS Next's combineLatest, a projection (result selector) function is only supported with the array form of the operator. The dictionary form computes values keyed by property name, so a positional project callback has no defined meaning and throws.","triggerScenarios":"combineLatest({a: obsA, b: obsB}, (a, b) => a + b) — passing a function as the second argument alongside a sources object.","commonSituations":"Porting RxJS 6/7 code that used the deprecated resultSelector overload, or copy-pasting the array-form project callback onto the object form during migration.","solutions":["Drop the project function and map afterwards: combineLatest({a, b}).pipe(map(({a, b}) => a + b))","If you need a projection, switch to the array form: combineLatest([obsA, obsB], (a, b) => a + b)","Remove resultSelector usage left over from RxJS <=7 migrations"],"exampleFix":"// before\ncombineLatest({a: obsA, b: obsB}, (a, b) => a + b);\n// after\ncombineLatest({a: obsA, b: obsB}).pipe(map(({a, b}) => a + b));","handlingStrategy":"validation","validationCode":"if (typeof configOrProject === 'function' && !Array.isArray(sources)) {\n  // project only valid with array form — restructure the call\n}","typeGuard":"const isSourcesObject = (v: unknown): v is Record<string, Observable<any>> =>\n  typeof v === 'object' && v !== null && !Array.isArray(v);","tryCatchPattern":null,"preventionTips":["Never pass a result selector with a dictionary of sources","Map after combineLatest instead of projecting inline","Delete resultSelector usages during RxJS 6/7 migration"],"tags":["combine-latest","result-selector","rxjs-next","migration"],"backgroundTag":"invalid-argument-shape","analyzedSha":"54796b38a57e6309f9861e174737479bb3f63f61","analyzedAt":"2026-08-28T10:21:27.410Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}