When you create a custom hook in React that returns a tuple, like setState does, you must tell TypeScript that you are returning a tuple and not just an array of arbitrary length. For example, the following code will not work:

function usePromise<T>(fn: () => Promise<T>) {
// ...
return [value, isReady];
}

TypeScript will tell you that the return type of the hook is (T | boolean)[]. To make the return value type-safe, you can use as const:

function usePromise<T>(fn: () => Promise<T>) {
// ...
return [value, isReady] as const;
}

The return type is now readonly [T, boolean]. However, as a consumer of the hook you don't know what these values mean. What's that boolean value? Does it indicate if the promise is ready or if it failed? You can solve this by explicitly defining the return value and giving the tuple items a name:

function usePromise<T>(fn: () => Promise<T>): [value: T, isReady: boolean] {
// ...
return [value, isReady];
}

This way, the return type is [value: T, isReady: boolean] and the consumer of the hook knows what the values mean.