Skip to content

Awaited has issues with custom Promise subtype #46934

Closed
@DanielRosenwasser

Description

@DanielRosenwasser

Hello everyone,

Not sure if this is the correct place to bring this up but the Awaited<T> type as-is broke our build after upgrading from typescript 4.4.3 to 4.5.2.

For reference, here is what Awaited<T> looks like:

/**
 * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`.
 */
type Awaited<T> =
    T extends null | undefined ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode
        T extends object & { then(onfulfilled: infer F): any } ? // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped
            F extends ((value: infer V) => any) ? // if the argument to `then` is callable, extracts the argument
                Awaited<V> : // recursively unwrap the value
                never : // the argument to `then` was not callable
        T; // non-object or non-thenable

The problem is that we have a custom Promise class (AbortablePromise) and its then function accepts a onfulfilled callback that do not exactly match the condition F extends ((value: infer V) => any).

Our then is declared like this:

  public then<TResult1 = T, TResult2 = never>(
    onfulfilled?: ((value: T, abortController: AbortController) => TResult1 | PromiseLike<TResult1>) | undefined | null,
    onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
  ): AbortablePromise<TResult1 | TResult2>;

So onfulfilled in our case is (value: T, abortController: AbortController) => TResult1 | PromiseLike<TResult1>) which does not match (value: infer V) => any

Hence, Awaited<T> where T is an AbortablePromise always returns never.

Would it be possible to make the type condition more flexible in Awaited<T> to enable these promise extensions and still have the type be compatible with Promise.all, Promise.race, etc?

Originally posted by @julienavert in #45350 (comment)

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions