@@ -13469,7 +13469,6 @@ namespace ts {
13469
13469
}
13470
13470
13471
13471
function getGlobalAwaitedSymbol(reportErrors: boolean): Symbol | undefined {
13472
- if (reportErrors) debugger;
13473
13472
// Only cache `unknownSymbol` if we are reporting errors so that we don't report the error more than once.
13474
13473
deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as __String, /*arity*/ 1, reportErrors) || (reportErrors ? unknownSymbol : undefined);
13475
13474
return deferredGlobalAwaitedSymbol === unknownSymbol ? undefined : deferredGlobalAwaitedSymbol;
@@ -32560,10 +32559,8 @@ namespace ts {
32560
32559
let wouldWorkWithAwait = false;
32561
32560
const errNode = errorNode || operatorToken;
32562
32561
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));
32567
32564
wouldWorkWithAwait = !(awaitedLeftType === leftType && awaitedRightType === rightType)
32568
32565
&& !!(awaitedLeftType && awaitedRightType)
32569
32566
&& isRelated(awaitedLeftType, awaitedRightType);
@@ -34643,9 +34640,14 @@ namespace ts {
34643
34640
}
34644
34641
34645
34642
/**
34646
- * Determines whether a type has a callable `then` member.
34643
+ * Determines whether a type is an object with a callable `then` member.
34647
34644
*/
34648
34645
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
+
34649
34651
const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
34650
34652
return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call).length > 0;
34651
34653
}
@@ -34667,13 +34669,24 @@ namespace ts {
34667
34669
/**
34668
34670
* For a generic `Awaited<T>`, gets `T`.
34669
34671
*/
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;
34671
34676
return type.flags & TypeFlags.Union ? mapType(type, unwrapAwaitedType) :
34672
34677
isAwaitedTypeInstantiation(type) ? type.aliasTypeArguments[0] :
34673
34678
type;
34674
34679
}
34675
34680
34676
34681
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
+
34677
34690
if (isTypeAny(type)) {
34678
34691
return type;
34679
34692
}
@@ -34684,13 +34697,18 @@ namespace ts {
34684
34697
}
34685
34698
34686
34699
// 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
+ }
34694
34712
}
34695
34713
}
34696
34714
@@ -34731,12 +34749,6 @@ namespace ts {
34731
34749
return typeAsAwaitable.awaitedTypeOfType && createAwaitedTypeIfNeeded(typeAsAwaitable.awaitedTypeOfType);
34732
34750
}
34733
34751
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
-
34740
34752
const promisedType = getPromisedTypeOfPromise(type);
34741
34753
if (promisedType) {
34742
34754
if (type.id === promisedType.id || awaitedTypeStack.lastIndexOf(promisedType.id) >= 0) {
@@ -34865,7 +34877,7 @@ namespace ts {
34865
34877
if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) {
34866
34878
// The promise type was not a valid type reference to the global promise type, so we
34867
34879
// 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));
34869
34881
return;
34870
34882
}
34871
34883
}
@@ -36865,7 +36877,7 @@ namespace ts {
36865
36877
// - `Generator<T, TReturn, TNext>` or `AsyncGenerator<T, TReturn, TNext>`
36866
36878
if (isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))) {
36867
36879
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));
36869
36881
}
36870
36882
}
36871
36883
@@ -37197,8 +37209,8 @@ namespace ts {
37197
37209
function unwrapReturnType(returnType: Type, functionFlags: FunctionFlags) {
37198
37210
const isGenerator = !!(functionFlags & FunctionFlags.Generator);
37199
37211
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 :
37202
37214
returnType;
37203
37215
}
37204
37216
0 commit comments