@@ -842,6 +842,7 @@ namespace ts {
842842        let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined;
843843        let deferredGlobalESSymbolType: ObjectType;
844844        let deferredGlobalTypedPropertyDescriptorType: GenericType;
845+         let deferredGlobalAwaitedSymbol: Symbol | undefined;
845846        let deferredGlobalPromiseType: GenericType;
846847        let deferredGlobalPromiseLikeType: GenericType;
847848        let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
@@ -896,7 +897,6 @@ namespace ts {
896897        const potentialThisCollisions: Node[] = [];
897898        const potentialNewTargetCollisions: Node[] = [];
898899        const potentialWeakMapCollisions: Node[] = [];
899-         const awaitedTypeStack: number[] = [];
900900
901901        const diagnostics = createDiagnosticCollection();
902902        const suggestionDiagnostics = createDiagnosticCollection();
@@ -11455,6 +11455,10 @@ namespace ts {
1145511455            return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
1145611456        }
1145711457
11458+         function getGlobalAwaitedSymbol(reportErrors: boolean) {
11459+             return deferredGlobalAwaitedSymbol || (deferredGlobalAwaitedSymbol = getGlobalTypeSymbol("Awaited" as __String, reportErrors));
11460+         }
11461+ 
1145811462        function getGlobalPromiseType(reportErrors: boolean) {
1145911463            return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
1146011464        }
@@ -26270,8 +26274,6 @@ namespace ts {
2627026274            // creates a `Promise<T>` type where `T` is the promisedType argument
2627126275            const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
2627226276            if (globalPromiseType !== emptyGenericType) {
26273-                 // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26274-                 promisedType = getAwaitedType(promisedType) || unknownType;
2627526277                return createTypeReference(globalPromiseType, [promisedType]);
2627626278            }
2627726279
@@ -26282,8 +26284,6 @@ namespace ts {
2628226284            // creates a `PromiseLike<T>` type where `T` is the promisedType argument
2628326285            const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
2628426286            if (globalPromiseLikeType !== emptyGenericType) {
26285-                 // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26286-                 promisedType = getAwaitedType(promisedType) || unknownType;
2628726287                return createTypeReference(globalPromiseLikeType, [promisedType]);
2628826288            }
2628926289
@@ -29743,98 +29743,26 @@ namespace ts {
2974329743                return typeAsAwaitable.awaitedTypeOfType = type;
2974429744            }
2974529745
29746-             if (type.flags & TypeFlags.Union) {
29747-                 let types: Type[] | undefined;
29748-                 for (const constituentType of (<UnionType>type).types) {
29749-                     types = append<Type>(types, getAwaitedType(constituentType, errorNode, diagnosticMessage, arg0));
29750-                 }
29751- 
29752-                 if (!types) {
29753-                     return undefined;
29754-                 }
29755- 
29756-                 return typeAsAwaitable.awaitedTypeOfType = getUnionType(types);
29746+             const symbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
29747+             if (!symbol) {
29748+                 return typeAsAwaitable.awaitedTypeOfType = type;
2975729749            }
2975829750
29759-             const promisedType = getPromisedTypeOfPromise(type);
29760-             if (promisedType) {
29761-                 if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
29762-                     // Verify that we don't have a bad actor in the form of a promise whose
29763-                     // promised type is the same as the promise type, or a mutually recursive
29764-                     // promise. If so, we return undefined as we cannot guess the shape. If this
29765-                     // were the actual case in the JavaScript, this Promise would never resolve.
29766-                     //
29767-                     // An example of a bad actor with a singly-recursive promise type might
29768-                     // be:
29769-                     //
29770-                     //  interface BadPromise {
29771-                     //      then(
29772-                     //          onfulfilled: (value: BadPromise) => any,
29773-                     //          onrejected: (error: any) => any): BadPromise;
29774-                     //  }
29775-                     // The above interface will pass the PromiseLike check, and return a
29776-                     // promised type of `BadPromise`. Since this is a self reference, we
29777-                     // don't want to keep recursing ad infinitum.
29778-                     //
29779-                     // An example of a bad actor in the form of a mutually-recursive
29780-                     // promise type might be:
29781-                     //
29782-                     //  interface BadPromiseA {
29783-                     //      then(
29784-                     //          onfulfilled: (value: BadPromiseB) => any,
29785-                     //          onrejected: (error: any) => any): BadPromiseB;
29786-                     //  }
29787-                     //
29788-                     //  interface BadPromiseB {
29789-                     //      then(
29790-                     //          onfulfilled: (value: BadPromiseA) => any,
29791-                     //          onrejected: (error: any) => any): BadPromiseA;
29792-                     //  }
29793-                     //
29794-                     if (errorNode) {
29795-                         error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
29796-                     }
29797-                     return undefined;
29798-                 }
29799- 
29800-                 // Keep track of the type we're about to unwrap to avoid bad recursive promise types.
29801-                 // See the comments above for more information.
29802-                 awaitedTypeStack.push(type.id);
29803-                 const awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0);
29804-                 awaitedTypeStack.pop();
29805- 
29806-                 if (!awaitedType) {
29807-                     return undefined;
29808-                 }
29751+             if (type.aliasSymbol === symbol) {
29752+                 return typeAsAwaitable.awaitedTypeOfType = type;
29753+             }
2980929754
29810-                 return typeAsAwaitable.awaitedTypeOfType = awaitedType;
29755+             const result = getTypeAliasInstantiation(symbol, [type]);
29756+             if (result !== unknownType || type === unknownType || getPromisedTypeOfPromise(type) === unknownType) {
29757+                 return typeAsAwaitable.awaitedTypeOfType = result;
2981129758            }
2981229759
29813-             // The type was not a promise, so it could not be unwrapped any further.
29814-             // As long as the type does not have a callable "then" property, it is
29815-             // safe to return the type; otherwise, an error will be reported in
29816-             // the call to getNonThenableType and we will return undefined.
29817-             //
29818-             // An example of a non-promise "thenable" might be:
29819-             //
29820-             //  await { then(): void {} }
29821-             //
29822-             // The "thenable" does not match the minimal definition for a promise. When
29823-             // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
29824-             // will never settle. We treat this as an error to help flag an early indicator
29825-             // of a runtime problem. If the user wants to return this value from an async
29826-             // function, they would need to wrap it in some other value. If they want it to
29827-             // be treated as a promise, they can cast to <any>.
29828-             const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
29829-             if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) {
29830-                 if (errorNode) {
29831-                     if (!diagnosticMessage) return Debug.fail();
29832-                     error(errorNode, diagnosticMessage, arg0);
29833-                 }
29834-                 return undefined;
29760+             if (errorNode) {
29761+                 if (!diagnosticMessage) return Debug.fail();
29762+                 error(errorNode, diagnosticMessage, arg0);
2983529763            }
2983629764
29837-             return typeAsAwaitable.awaitedTypeOfType = type ;
29765+             return undefined ;
2983829766        }
2983929767
2984029768        /**
0 commit comments