cliui icon indicating copy to clipboard operation
cliui copied to clipboard

Return typings of TaskCalback require an async task to either always succeed or always fail

Open mini-bomba opened this issue 11 months ago • 0 comments

Package version

6.4.2

Describe the bug

The current typings of TaskCallback require that a promise either always returns string or always returns { isError: true; message: string; }. This basically means that any async task submitted to the task manager cannot sometimes succeed or sometimes fail without an error thrown - it must always either return a string on an error object, it cannot return an union type of both options. This unnecessarily limits the possibilities for TS users in a way that simply does not make sense.

A simple script that shows the issue (using deno for simplicity of setup, but it can also be reproduced in node with typescript)

import {cliui} from "npm:@poppinss/cliui";

const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms));

const ui = cliui();

await ui.tasks().add("test", async (task) => {
  await sleep(1000);
  return Math.random() < 0.5 ? "Done" : task.error("Failed");
}).run()

Typechecking with deno check (...or typescript LSP, or tsc) fails with the following error

Check file:///tmp/test/main.ts
TS2345 [ERROR]: Argument of type '(task: { update(logMessage: string): void; error<T extends string | Error>(error: T): T extends string ? { message: T; isError: true; } : T; }) => Promise<"Done" | { message: "Failed"; isError: true; }>' is not assignable to parameter of type 'TaskCallback'.
  Type 'Promise<"Done" | { message: "Failed"; isError: true; }>' is not assignable to type 'string | Error | Promise<Error> | { isError: true; message: string; } | Promise<{ isError: true; message: string; }> | Promise<string>'.
    Type 'Promise<"Done" | { message: "Failed"; isError: true; }>' is not assignable to type 'Promise<Error>'.
      Type '"Done" | { message: "Failed"; isError: true; }' is not assignable to type 'Error'.
        Type 'string' is not assignable to type 'Error'.
await ui.tasks().add("test", async (task) => {
                             ~~~~~~~~~~~~~~~~~
    at file:///tmp/test/main.ts:7:30

error: Type checking failed.

Reproduction repo

No response

mini-bomba avatar Feb 17 '25 22:02 mini-bomba