@@ -13469,7 +13469,6 @@ namespace ts {
1346913469 }
1347013470
1347113471 function getGlobalAwaitedSymbol(reportErrors: boolean): Symbol | undefined {
13472- if (reportErrors) debugger;
1347313472 // Only cache `unknownSymbol` if we are reporting errors so that we don't report the error more than once.
1347413473 deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as __String, /*arity*/ 1, reportErrors) || (reportErrors ? unknownSymbol : undefined);
1347513474 return deferredGlobalAwaitedSymbol === unknownSymbol ? undefined : deferredGlobalAwaitedSymbol;
@@ -32560,10 +32559,8 @@ namespace ts {
3256032559 let wouldWorkWithAwait = false;
3256132560 const errNode = errorNode || operatorToken;
3256232561 if (isRelated) {
32563- let awaitedLeftType = getAwaitedType(leftType);
32564- let awaitedRightType = getAwaitedType(rightType);
32565- awaitedLeftType &&= unwrapAwaitedType(awaitedLeftType);
32566- awaitedRightType &&= unwrapAwaitedType(awaitedRightType);
32562+ const awaitedLeftType = unwrapAwaitedType(getAwaitedType(leftType));
32563+ const awaitedRightType = unwrapAwaitedType(getAwaitedType(rightType));
3256732564 wouldWorkWithAwait = !(awaitedLeftType === leftType && awaitedRightType === rightType)
3256832565 && !!(awaitedLeftType && awaitedRightType)
3256932566 && isRelated(awaitedLeftType, awaitedRightType);
@@ -34643,9 +34640,14 @@ namespace ts {
3464334640 }
3464434641
3464534642 /**
34646- * Determines whether a type has a callable `then` member.
34643+ * Determines whether a type is an object with a callable `then` member.
3464734644 */
3464834645 function isThenableType(type: Type): boolean {
34646+ if (allTypesAssignableToKind(type, TypeFlags.Primitive | TypeFlags.Never)) {
34647+ // primitive types cannot be considered "thenable" since they are not objects.
34648+ return false;
34649+ }
34650+
3464934651 const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
3465034652 return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call).length > 0;
3465134653 }
@@ -34667,13 +34669,24 @@ namespace ts {
3466734669 /**
3466834670 * For a generic `Awaited<T>`, gets `T`.
3466934671 */
34670- function unwrapAwaitedType(type: Type) {
34672+ function unwrapAwaitedType(type: Type): Type;
34673+ function unwrapAwaitedType(type: Type | undefined): Type | undefined;
34674+ function unwrapAwaitedType(type: Type | undefined) {
34675+ if (!type) return undefined;
3467134676 return type.flags & TypeFlags.Union ? mapType(type, unwrapAwaitedType) :
3467234677 isAwaitedTypeInstantiation(type) ? type.aliasTypeArguments[0] :
3467334678 type;
3467434679 }
3467534680
3467634681 function createAwaitedTypeIfNeeded(type: Type): Type {
34682+ // We wrap type `T` in `Awaited<T>` based on the following conditions:
34683+ // - `T` is not already an `Awaited<U>`, and
34684+ // - `T` is generic, and
34685+ // - One of the following applies:
34686+ // - `T` has no base constraint, or
34687+ // - The base constraint of `T` is `any`, `unknown`, `object`, or `{}`, or
34688+ // - The base constraint of `T` is an object type with a callable `then` method.
34689+
3467734690 if (isTypeAny(type)) {
3467834691 return type;
3467934692 }
@@ -34684,13 +34697,18 @@ namespace ts {
3468434697 }
3468534698
3468634699 // Only instantiate `Awaited<T>` if `T` contains possibly non-primitive types.
34687- if (isGenericObjectType(type) && !allTypesAssignableToKind(type, TypeFlags.Primitive | TypeFlags.Never)) {
34688- // Nothing to do if `Awaited<T>` doesn't exist
34689- const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ true);
34690- if (awaitedSymbol) {
34691- // Unwrap unions that may contain `Awaited<T>`, otherwise its possible to manufacture an `Awaited<Awaited<T> | U>` where
34692- // an `Awaited<T | U>` would suffice.
34693- return getTypeAliasInstantiation(awaitedSymbol, [unwrapAwaitedType(type)]);
34700+ if (isGenericObjectType(type)) {
34701+ const baseConstraint = getBaseConstraintOfType(type);
34702+ // Only instantiate `Awaited<T>` if `T` has no base constraint, or the base constraint of `T` is `any`, `unknown`, `{}`, `object`,
34703+ // or is promise-like.
34704+ if (!baseConstraint || (baseConstraint.flags & TypeFlags.AnyOrUnknown) || isEmptyObjectType(baseConstraint) || isThenableType(baseConstraint)) {
34705+ // Nothing to do if `Awaited<T>` doesn't exist
34706+ const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ true);
34707+ if (awaitedSymbol) {
34708+ // Unwrap unions that may contain `Awaited<T>`, otherwise its possible to manufacture an `Awaited<Awaited<T> | U>` where
34709+ // an `Awaited<T | U>` would suffice.
34710+ return getTypeAliasInstantiation(awaitedSymbol, [unwrapAwaitedType(type)]);
34711+ }
3469434712 }
3469534713 }
3469634714
@@ -34731,12 +34749,6 @@ namespace ts {
3473134749 return typeAsAwaitable.awaitedTypeOfType && createAwaitedTypeIfNeeded(typeAsAwaitable.awaitedTypeOfType);
3473234750 }
3473334751
34734- // primitives with a `{ then() }` won't be unwrapped/adopted. This prevents `Awaited<T>` when `T extends string`
34735- // (or another primitive), since the `Awaited<T>` type only unwraps `object` types.
34736- if (allTypesAssignableToKind(type, TypeFlags.Primitive | TypeFlags.Never)) {
34737- return type;
34738- }
34739-
3474034752 const promisedType = getPromisedTypeOfPromise(type);
3474134753 if (promisedType) {
3474234754 if (type.id === promisedType.id || awaitedTypeStack.lastIndexOf(promisedType.id) >= 0) {
@@ -34865,7 +34877,7 @@ namespace ts {
3486534877 if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) {
3486634878 // The promise type was not a valid type reference to the global promise type, so we
3486734879 // report an error and return the unknown type.
34868- error(returnTypeNode, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0, typeToString(unwrapAwaitedType(getAwaitedType(returnType) || voidType) ));
34880+ error(returnTypeNode, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0, typeToString(unwrapAwaitedType(getAwaitedType(returnType)) || voidType));
3486934881 return;
3487034882 }
3487134883 }
@@ -36865,7 +36877,7 @@ namespace ts {
3686536877 // - `Generator<T, TReturn, TNext>` or `AsyncGenerator<T, TReturn, TNext>`
3686636878 if (isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))) {
3686736879 const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType);
36868- return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(yieldType, returnType, nextType));
36880+ return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType( yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType));
3686936881 }
3687036882 }
3687136883
@@ -37197,8 +37209,8 @@ namespace ts {
3719737209 function unwrapReturnType(returnType: Type, functionFlags: FunctionFlags) {
3719837210 const isGenerator = !!(functionFlags & FunctionFlags.Generator);
3719937211 const isAsync = !!(functionFlags & FunctionFlags.Async);
37200- return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) ?? errorType :
37201- isAsync ? unwrapAwaitedType(getAwaitedType(returnType) ?? errorType) :
37212+ return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) || errorType :
37213+ isAsync ? unwrapAwaitedType(getAwaitedType(returnType)) || errorType :
3720237214 returnType;
3720337215 }
3720437216
0 commit comments