ReactiveX/rxjs · error · TypeError
A combineLatest projection requires an array of observable v
Error message
A combineLatest projection requires an array of observable values
What it means
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.
Source
Thrown at packages/rxjs/src/combine-latest.ts:81
);
return project === undefined ? (combined as any) : combined[map]((values) => project(...values));
}
const actualSources: readonly ObservableValue<any>[] | { [key: string]: ObservableValue<any> } = Array.isArray(sources)
? [...sources]
: { ...sources };
if (isSourceArray(actualSources)) {
const combined = this[combine](
actualSources.map((source) => ({
source,
requireFirstValue: requireAllValues,
}))
);
return project === undefined ? (combined as any) : combined[map]((values) => project(...values));
} else {
if (project !== undefined) {
throw new TypeError('A combineLatest projection requires an array of observable values');
}
const keys = Object.keys(actualSources);
return this[combine](
keys.map((key) => ({
source: actualSources[key]!,
requireFirstValue: requireAllValues,
}))
)[map]((values) => Object.fromEntries(keys.map((key, i) => [key, values[i]]))) as any;
}
}
function isSourceArray(sources: any): sources is readonly ObservableValue<any>[] {
return Array.isArray(sources);
}
View on GitHub (pinned to 54796b38a5)
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
Example fix
// before
combineLatest({a: obsA, b: obsB}, (a, b) => a + b);
// after
combineLatest({a: obsA, b: obsB}).pipe(map(({a, b}) => a + b)); Defensive patterns
Strategy: validation
Validate before calling
if (typeof configOrProject === 'function' && !Array.isArray(sources)) {
// project only valid with array form — restructure the call
} Type guard
const isSourcesObject = (v: unknown): v is Record<string, Observable<any>> => typeof v === 'object' && v !== null && !Array.isArray(v);
Prevention
- 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
When it happens
Trigger: combineLatest({a: obsA, b: obsB}, (a, b) => a + b) — passing a function as the second argument alongside a sources object.
Common situations: 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.
Related errors
- Must combine observable instance with an array of observable
- RxJS Next expand does not support a scheduler argument.
- RxJS Next expand options must be an object.
- Scheduler-backed generate is not supported by this Symbol co
- Scheduler-backed publishReplay is not supported by this Symb
AI-assisted analysis of ReactiveX/rxjs@54796b38a5 (2026-08-28).
Data as JSON: /api/errors/d98c2aa0723d5415.
Report an issue: GitHub.