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