How does one write a type-assertion function to check whether all containers in an array are in a certain state?

58 Views Asked by At

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?

0

There are 0 best solutions below