I'm working with a library that models results to asynchronous operations in a way similar to the following:
type Success<TData> = { status: 'success', data: TData };
type Loading = { status: 'loading' }
type Query<TData> = Success<TData> | Loading
In the situation where one is dealing with multiple Query
objects it would be convenient to be able to check that they're all Success
objects with one function-call, eg:
const a = useFetchA() // Query<A>
const b = useFetchB() // Query<B>
if (isAllSuccess([a,b])) {
// in here:
// a is Success<A>
// b is Success<B>
}
I've been trying to write such a function, but I'm quite confused as to why TypeScript does not accept the predicate:
type Success<T> = {status: 'success', data: T}
type Loading = {status: 'loading'}
type Query<T> = Success<T> | Loading
const isAllSuccess = <T extends Array<Query<any>>>(
queries: readonly [...T]
): queries is { [I in keyof T]: Success<T[I]> } => {
// ^ A type predicate's type must be assignable to its parameter's type.
// Type '{ [I in keyof T]: Success<T[I]>; }' is not assignable to type 'readonly [...T]'.
// Target requires 1 element(s) but source may have fewer.(2677)
if (queries.length === 0) return false;
return queries.every((q) => q.status === "success");
};
Any ideas?