@@ -841,6 +841,7 @@ namespace ts {
841
841
let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined;
842
842
let deferredGlobalESSymbolType: ObjectType;
843
843
let deferredGlobalTypedPropertyDescriptorType: GenericType;
844
+ let deferredGlobalAwaitedSymbol: Symbol | undefined;
844
845
let deferredGlobalPromiseType: GenericType;
845
846
let deferredGlobalPromiseLikeType: GenericType;
846
847
let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
@@ -895,7 +896,6 @@ namespace ts {
895
896
const potentialThisCollisions: Node[] = [];
896
897
const potentialNewTargetCollisions: Node[] = [];
897
898
const potentialWeakMapCollisions: Node[] = [];
898
- const awaitedTypeStack: number[] = [];
899
899
900
900
const diagnostics = createDiagnosticCollection();
901
901
const suggestionDiagnostics = createDiagnosticCollection();
@@ -11449,6 +11449,10 @@ namespace ts {
11449
11449
return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
11450
11450
}
11451
11451
11452
+ function getGlobalAwaitedSymbol(reportErrors: boolean) {
11453
+ return deferredGlobalAwaitedSymbol || (deferredGlobalAwaitedSymbol = getGlobalTypeSymbol("Awaited" as __String, reportErrors));
11454
+ }
11455
+
11452
11456
function getGlobalPromiseType(reportErrors: boolean) {
11453
11457
return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
11454
11458
}
@@ -26192,8 +26196,6 @@ namespace ts {
26192
26196
// creates a `Promise<T>` type where `T` is the promisedType argument
26193
26197
const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
26194
26198
if (globalPromiseType !== emptyGenericType) {
26195
- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26196
- promisedType = getAwaitedType(promisedType) || unknownType;
26197
26199
return createTypeReference(globalPromiseType, [promisedType]);
26198
26200
}
26199
26201
@@ -26204,8 +26206,6 @@ namespace ts {
26204
26206
// creates a `PromiseLike<T>` type where `T` is the promisedType argument
26205
26207
const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true);
26206
26208
if (globalPromiseLikeType !== emptyGenericType) {
26207
- // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
26208
- promisedType = getAwaitedType(promisedType) || unknownType;
26209
26209
return createTypeReference(globalPromiseLikeType, [promisedType]);
26210
26210
}
26211
26211
@@ -29665,98 +29665,26 @@ namespace ts {
29665
29665
return typeAsAwaitable.awaitedTypeOfType = type;
29666
29666
}
29667
29667
29668
- if (type.flags & TypeFlags.Union) {
29669
- let types: Type[] | undefined;
29670
- for (const constituentType of (<UnionType>type).types) {
29671
- types = append<Type>(types, getAwaitedType(constituentType, errorNode, diagnosticMessage, arg0));
29672
- }
29673
-
29674
- if (!types) {
29675
- return undefined;
29676
- }
29677
-
29678
- return typeAsAwaitable.awaitedTypeOfType = getUnionType(types);
29668
+ const symbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
29669
+ if (!symbol) {
29670
+ return typeAsAwaitable.awaitedTypeOfType = type;
29679
29671
}
29680
29672
29681
- const promisedType = getPromisedTypeOfPromise(type);
29682
- if (promisedType) {
29683
- if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
29684
- // Verify that we don't have a bad actor in the form of a promise whose
29685
- // promised type is the same as the promise type, or a mutually recursive
29686
- // promise. If so, we return undefined as we cannot guess the shape. If this
29687
- // were the actual case in the JavaScript, this Promise would never resolve.
29688
- //
29689
- // An example of a bad actor with a singly-recursive promise type might
29690
- // be:
29691
- //
29692
- // interface BadPromise {
29693
- // then(
29694
- // onfulfilled: (value: BadPromise) => any,
29695
- // onrejected: (error: any) => any): BadPromise;
29696
- // }
29697
- // The above interface will pass the PromiseLike check, and return a
29698
- // promised type of `BadPromise`. Since this is a self reference, we
29699
- // don't want to keep recursing ad infinitum.
29700
- //
29701
- // An example of a bad actor in the form of a mutually-recursive
29702
- // promise type might be:
29703
- //
29704
- // interface BadPromiseA {
29705
- // then(
29706
- // onfulfilled: (value: BadPromiseB) => any,
29707
- // onrejected: (error: any) => any): BadPromiseB;
29708
- // }
29709
- //
29710
- // interface BadPromiseB {
29711
- // then(
29712
- // onfulfilled: (value: BadPromiseA) => any,
29713
- // onrejected: (error: any) => any): BadPromiseA;
29714
- // }
29715
- //
29716
- if (errorNode) {
29717
- error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method);
29718
- }
29719
- return undefined;
29720
- }
29721
-
29722
- // Keep track of the type we're about to unwrap to avoid bad recursive promise types.
29723
- // See the comments above for more information.
29724
- awaitedTypeStack.push(type.id);
29725
- const awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0);
29726
- awaitedTypeStack.pop();
29727
-
29728
- if (!awaitedType) {
29729
- return undefined;
29730
- }
29673
+ if (type.aliasSymbol === symbol) {
29674
+ return typeAsAwaitable.awaitedTypeOfType = type;
29675
+ }
29731
29676
29732
- return typeAsAwaitable.awaitedTypeOfType = awaitedType;
29677
+ const result = getTypeAliasInstantiation(symbol, [type]);
29678
+ if (result !== unknownType || type === unknownType || getPromisedTypeOfPromise(type) === unknownType) {
29679
+ return typeAsAwaitable.awaitedTypeOfType = result;
29733
29680
}
29734
29681
29735
- // The type was not a promise, so it could not be unwrapped any further.
29736
- // As long as the type does not have a callable "then" property, it is
29737
- // safe to return the type; otherwise, an error will be reported in
29738
- // the call to getNonThenableType and we will return undefined.
29739
- //
29740
- // An example of a non-promise "thenable" might be:
29741
- //
29742
- // await { then(): void {} }
29743
- //
29744
- // The "thenable" does not match the minimal definition for a promise. When
29745
- // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
29746
- // will never settle. We treat this as an error to help flag an early indicator
29747
- // of a runtime problem. If the user wants to return this value from an async
29748
- // function, they would need to wrap it in some other value. If they want it to
29749
- // be treated as a promise, they can cast to <any>.
29750
- const thenFunction = getTypeOfPropertyOfType(type, "then" as __String);
29751
- if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) {
29752
- if (errorNode) {
29753
- if (!diagnosticMessage) return Debug.fail();
29754
- error(errorNode, diagnosticMessage, arg0);
29755
- }
29756
- return undefined;
29682
+ if (errorNode) {
29683
+ if (!diagnosticMessage) return Debug.fail();
29684
+ error(errorNode, diagnosticMessage, arg0);
29757
29685
}
29758
29686
29759
- return typeAsAwaitable.awaitedTypeOfType = type ;
29687
+ return undefined ;
29760
29688
}
29761
29689
29762
29690
/**
0 commit comments