Use Awaited<T> with 'await'

This commit is contained in:
Ron Buckton
2021-09-02 18:40:02 -07:00
parent 46ce88c565
commit 5bdae61bb2
8 changed files with 192 additions and 89 deletions
+168 -67
View File
@@ -904,28 +904,29 @@ namespace ts {
// and they will not get an error from not having unrelated library files
let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined;
let deferredGlobalESSymbolConstructorTypeSymbol: Symbol | undefined;
let deferredGlobalESSymbolType: ObjectType;
let deferredGlobalESSymbolType: ObjectType | undefined;
let deferredGlobalTypedPropertyDescriptorType: GenericType;
let deferredGlobalPromiseType: GenericType;
let deferredGlobalPromiseLikeType: GenericType;
let deferredGlobalPromiseType: GenericType | undefined;
let deferredGlobalPromiseLikeType: GenericType | undefined;
let deferredGlobalPromiseConstructorSymbol: Symbol | undefined;
let deferredGlobalPromiseConstructorLikeType: ObjectType;
let deferredGlobalIterableType: GenericType;
let deferredGlobalIteratorType: GenericType;
let deferredGlobalIterableIteratorType: GenericType;
let deferredGlobalGeneratorType: GenericType;
let deferredGlobalIteratorYieldResultType: GenericType;
let deferredGlobalIteratorReturnResultType: GenericType;
let deferredGlobalAsyncIterableType: GenericType;
let deferredGlobalAsyncIteratorType: GenericType;
let deferredGlobalAsyncIterableIteratorType: GenericType;
let deferredGlobalAsyncGeneratorType: GenericType;
let deferredGlobalTemplateStringsArrayType: ObjectType;
let deferredGlobalPromiseConstructorLikeType: ObjectType | undefined;
let deferredGlobalIterableType: GenericType | undefined;
let deferredGlobalIteratorType: GenericType | undefined;
let deferredGlobalIterableIteratorType: GenericType | undefined;
let deferredGlobalGeneratorType: GenericType | undefined;
let deferredGlobalIteratorYieldResultType: GenericType | undefined;
let deferredGlobalIteratorReturnResultType: GenericType | undefined;
let deferredGlobalAsyncIterableType: GenericType | undefined;
let deferredGlobalAsyncIteratorType: GenericType | undefined;
let deferredGlobalAsyncIterableIteratorType: GenericType | undefined;
let deferredGlobalAsyncGeneratorType: GenericType | undefined;
let deferredGlobalTemplateStringsArrayType: ObjectType | undefined;
let deferredGlobalImportMetaType: ObjectType;
let deferredGlobalImportMetaExpressionType: ObjectType;
let deferredGlobalExtractSymbol: Symbol;
let deferredGlobalOmitSymbol: Symbol;
let deferredGlobalBigIntType: ObjectType;
let deferredGlobalExtractSymbol: Symbol | undefined;
let deferredGlobalOmitSymbol: Symbol | undefined;
let deferredGlobalAwaitedSymbol: Symbol | undefined;
let deferredGlobalBigIntType: ObjectType | undefined;
const allPotentiallyUnusedIdentifiers = new Map<Path, PotentiallyUnusedIdentifier[]>(); // key is file name
@@ -13320,28 +13321,48 @@ namespace ts {
return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined);
}
function getGlobalTypeAliasSymbol(name: __String, arity: number, reportErrors: boolean): Symbol | undefined {
const symbol = getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined);
if (symbol) {
// Resolve the declared type of the symbol. This resolves type parameters for the type
// alias so that we can check arity.
getDeclaredTypeOfSymbol(symbol);
if (length(getSymbolLinks(symbol).typeParameters) !== arity) {
const decl = symbol.declarations && find(symbol.declarations, isTypeAliasDeclaration);
error(decl, Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbolName(symbol), arity);
return undefined;
}
}
return symbol;
}
function getGlobalSymbol(name: __String, meaning: SymbolFlags, diagnostic: DiagnosticMessage | undefined): Symbol | undefined {
// Don't track references for global symbols anyway, so value if `isReference` is arbitrary
return resolveName(undefined, name, meaning, diagnostic, name, /*isUse*/ false);
}
function getGlobalType(name: __String, arity: 0, reportErrors: boolean): ObjectType;
function getGlobalType(name: __String, arity: number, reportErrors: boolean): GenericType;
function getGlobalType(name: __String, arity: 0, reportErrors: true): ObjectType;
function getGlobalType(name: __String, arity: 0, reportErrors: boolean): ObjectType | undefined;
function getGlobalType(name: __String, arity: number, reportErrors: true): GenericType;
function getGlobalType(name: __String, arity: number, reportErrors: boolean): GenericType | undefined;
function getGlobalType(name: __String, arity: number, reportErrors: boolean): ObjectType | undefined {
const symbol = getGlobalTypeSymbol(name, reportErrors);
return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined;
}
function getGlobalTypedPropertyDescriptorType() {
return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType;
// We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times
return deferredGlobalTypedPropertyDescriptorType ||= getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true) || emptyGenericType;
}
function getGlobalTemplateStringsArrayType() {
return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType;
// We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times
return deferredGlobalTemplateStringsArrayType ||= getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType;
}
function getGlobalImportMetaType() {
return deferredGlobalImportMetaType || (deferredGlobalImportMetaType = getGlobalType("ImportMeta" as __String, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType;
// We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times
return deferredGlobalImportMetaType ||= getGlobalType("ImportMeta" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType;
}
function getGlobalImportMetaExpressionType() {
@@ -13362,72 +13383,72 @@ namespace ts {
return deferredGlobalImportMetaExpressionType;
}
function getGlobalESSymbolConstructorSymbol(reportErrors: boolean) {
return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as __String, reportErrors));
function getGlobalESSymbolConstructorSymbol(reportErrors: boolean): Symbol | undefined {
return deferredGlobalESSymbolConstructorSymbol ||= getGlobalValueSymbol("Symbol" as __String, reportErrors);
}
function getGlobalESSymbolConstructorTypeSymbol(reportErrors: boolean) {
return deferredGlobalESSymbolConstructorTypeSymbol || (deferredGlobalESSymbolConstructorTypeSymbol = getGlobalTypeSymbol("SymbolConstructor" as __String, reportErrors));
function getGlobalESSymbolConstructorTypeSymbol(reportErrors: boolean): Symbol | undefined {
return deferredGlobalESSymbolConstructorTypeSymbol ||= getGlobalTypeSymbol("SymbolConstructor" as __String, reportErrors);
}
function getGlobalESSymbolType(reportErrors: boolean) {
return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
}
function getGlobalPromiseType(reportErrors: boolean) {
return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalPromiseType ||= getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalPromiseLikeType(reportErrors: boolean) {
return deferredGlobalPromiseLikeType || (deferredGlobalPromiseLikeType = getGlobalType("PromiseLike" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalPromiseLikeType ||= getGlobalType("PromiseLike" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined {
return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as __String, reportErrors));
return deferredGlobalPromiseConstructorSymbol ||= getGlobalValueSymbol("Promise" as __String, reportErrors);
}
function getGlobalPromiseConstructorLikeType(reportErrors: boolean) {
return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
return (deferredGlobalPromiseConstructorLikeType ||= getGlobalType("PromiseConstructorLike" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
}
function getGlobalAsyncIterableType(reportErrors: boolean) {
return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalAsyncIterableType ||= getGlobalType("AsyncIterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalAsyncIteratorType(reportErrors: boolean) {
return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
return (deferredGlobalAsyncIteratorType ||= getGlobalType("AsyncIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}
function getGlobalAsyncIterableIteratorType(reportErrors: boolean) {
return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalAsyncIterableIteratorType ||= getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalAsyncGeneratorType(reportErrors: boolean) {
return deferredGlobalAsyncGeneratorType || (deferredGlobalAsyncGeneratorType = getGlobalType("AsyncGenerator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
return (deferredGlobalAsyncGeneratorType ||= getGlobalType("AsyncGenerator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}
function getGlobalIterableType(reportErrors: boolean) {
return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalIterableType ||= getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalIteratorType(reportErrors: boolean) {
return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
return (deferredGlobalIteratorType ||= getGlobalType("Iterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}
function getGlobalIterableIteratorType(reportErrors: boolean) {
return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalIterableIteratorType ||= getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalGeneratorType(reportErrors: boolean) {
return deferredGlobalGeneratorType || (deferredGlobalGeneratorType = getGlobalType("Generator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
return (deferredGlobalGeneratorType ||= getGlobalType("Generator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType;
}
function getGlobalIteratorYieldResultType(reportErrors: boolean) {
return deferredGlobalIteratorYieldResultType || (deferredGlobalIteratorYieldResultType = getGlobalType("IteratorYieldResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalIteratorYieldResultType ||= getGlobalType("IteratorYieldResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalIteratorReturnResultType(reportErrors: boolean) {
return deferredGlobalIteratorReturnResultType || (deferredGlobalIteratorReturnResultType = getGlobalType("IteratorReturnResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
return (deferredGlobalIteratorReturnResultType ||= getGlobalType("IteratorReturnResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType;
}
function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType | undefined {
@@ -13435,16 +13456,27 @@ namespace ts {
return symbol && getTypeOfGlobalSymbol(symbol, arity) as GenericType;
}
function getGlobalExtractSymbol(): Symbol {
return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217
function getGlobalExtractSymbol(): Symbol | undefined {
// We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times
deferredGlobalExtractSymbol ||= getGlobalTypeAliasSymbol("Extract" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
return deferredGlobalExtractSymbol === unknownSymbol ? undefined : deferredGlobalExtractSymbol;
}
function getGlobalOmitSymbol(): Symbol {
return deferredGlobalOmitSymbol || (deferredGlobalOmitSymbol = getGlobalSymbol("Omit" as __String, SymbolFlags.TypeAlias, Diagnostics.Cannot_find_global_type_0)!); // TODO: GH#18217
function getGlobalOmitSymbol(): Symbol | undefined {
// We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times
deferredGlobalOmitSymbol ||= getGlobalTypeAliasSymbol("Omit" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol;
return deferredGlobalOmitSymbol === unknownSymbol ? undefined : deferredGlobalOmitSymbol;
}
function getGlobalAwaitedSymbol(reportErrors: boolean): Symbol | undefined {
if (reportErrors) debugger;
// Only cache `unknownSymbol` if we are reporting errors so that we don't report the error more than once.
deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as __String, /*arity*/ 1, reportErrors) || (reportErrors ? unknownSymbol : undefined);
return deferredGlobalAwaitedSymbol === unknownSymbol ? undefined : deferredGlobalAwaitedSymbol;
}
function getGlobalBigIntType(reportErrors: boolean) {
return deferredGlobalBigIntType || (deferredGlobalBigIntType = getGlobalType("BigInt" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType;
}
/**
@@ -25264,8 +25296,9 @@ namespace ts {
}
if (functionFlags & FunctionFlags.Async) { // Async function or AsyncGenerator function
// Get the awaited type without the `Awaited<T>` alias
const contextualAwaitedType = mapType(contextualReturnType, getAwaitedType);
return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]);
return contextualAwaitedType && getUnionType([unwrapAwaitedType(contextualAwaitedType), createPromiseLikeType(contextualAwaitedType)]);
}
return contextualReturnType; // Regular function or Generator function
@@ -25278,7 +25311,7 @@ namespace ts {
const contextualType = getContextualType(node, contextFlags);
if (contextualType) {
const contextualAwaitedType = getAwaitedType(contextualType);
return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]);
return contextualAwaitedType && getUnionType([unwrapAwaitedType(contextualAwaitedType), createPromiseLikeType(contextualAwaitedType)]);
}
return undefined;
}
@@ -32527,8 +32560,10 @@ namespace ts {
let wouldWorkWithAwait = false;
const errNode = errorNode || operatorToken;
if (isRelated) {
const awaitedLeftType = getAwaitedType(leftType);
const awaitedRightType = getAwaitedType(rightType);
let awaitedLeftType = getAwaitedType(leftType);
let awaitedRightType = getAwaitedType(rightType);
awaitedLeftType &&= unwrapAwaitedType(awaitedLeftType);
awaitedRightType &&= unwrapAwaitedType(awaitedRightType);
wouldWorkWithAwait = !(awaitedLeftType === leftType && awaitedRightType === rightType)
&& !!(awaitedLeftType && awaitedRightType)
&& isRelated(awaitedLeftType, awaitedRightType);
@@ -34561,6 +34596,11 @@ namespace ts {
return typeAsPromise.promisedTypeOfPromise = getTypeArguments(type as GenericType)[0];
}
// primitives with a `{ then() }` won't be unwrapped/adopted.
if (allTypesAssignableToKind(type, TypeFlags.Primitive | TypeFlags.Never)) {
return undefined;
}
const thenFunction = getTypeOfPropertyOfType(type, "then" as __String)!; // TODO: GH#18217
if (isTypeAny(thenFunction)) {
return undefined;
@@ -34610,6 +34650,54 @@ namespace ts {
return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call).length > 0;
}
interface AwaitedTypeInstantiation extends Type {
_awaitedTypeBrand: never;
aliasSymbol: Symbol;
aliasTypeArguments: readonly Type[];
}
function isAwaitedTypeInstantiation(type: Type): type is AwaitedTypeInstantiation {
if (type.flags & TypeFlags.Conditional) {
const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ false);
return !!awaitedSymbol && type.aliasSymbol === awaitedSymbol && type.aliasTypeArguments?.length === 1;
}
return false;
}
/**
* For a generic `Awaited<T>`, gets `T`.
*/
function unwrapAwaitedType(type: Type) {
return type.flags & TypeFlags.Union ? mapType(type, unwrapAwaitedType) :
isAwaitedTypeInstantiation(type) ? type.aliasTypeArguments[0] :
type;
}
function createAwaitedTypeIfNeeded(type: Type): Type {
if (isTypeAny(type)) {
return type;
}
// If this is already an `Awaited<T>`, just return it. This helps to avoid `Awaited<Awaited<T>>` in higher-order.
if (isAwaitedTypeInstantiation(type)) {
return type;
}
// Only instantiate `Awaited<T>` if `T` contains possibly non-primitive types.
if (isGenericObjectType(type) && !allTypesAssignableToKind(type, TypeFlags.Primitive | TypeFlags.Never)) {
// Nothing to do if `Awaited<T>` doesn't exist
const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ true);
if (awaitedSymbol) {
// Unwrap unions that may contain `Awaited<T>`, otherwise its possible to manufacture an `Awaited<Awaited<T> | U>` where
// an `Awaited<T | U>` would suffice.
return getTypeAliasInstantiation(awaitedSymbol, [unwrapAwaitedType(type)]);
}
}
Debug.assert(getPromisedTypeOfPromise(type) === undefined, "type provided should not be a non-generic 'promise'-like.");
return type;
}
/**
* Gets the "awaited type" of a type.
*
@@ -34625,21 +34713,28 @@ namespace ts {
return type;
}
// If this is already an `Awaited<T>`, just return it. This avoids `Awaited<Awaited<T>>` in higher-order
if (isAwaitedTypeInstantiation(type)) {
return type;
}
// If we've already cached an awaited type, return a possible `Awaited<T>` for it.
const typeAsAwaitable = type as PromiseOrAwaitableType;
if (typeAsAwaitable.awaitedTypeOfType) {
return typeAsAwaitable.awaitedTypeOfType;
return createAwaitedTypeIfNeeded(typeAsAwaitable.awaitedTypeOfType);
}
// For a union, get a union of the awaited types of each constituent.
//
return typeAsAwaitable.awaitedTypeOfType =
mapType(type, errorNode ? constituentType => getAwaitedTypeWorker(constituentType, errorNode, diagnosticMessage, arg0) : getAwaitedTypeWorker);
}
if (type.flags & TypeFlags.Union) {
const mapper = errorNode ? (constituentType: Type) => getAwaitedType(constituentType, errorNode, diagnosticMessage, arg0) : getAwaitedType;
typeAsAwaitable.awaitedTypeOfType = mapType(type, mapper);
return typeAsAwaitable.awaitedTypeOfType && createAwaitedTypeIfNeeded(typeAsAwaitable.awaitedTypeOfType);
}
function getAwaitedTypeWorker(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined {
const typeAsAwaitable = type as PromiseOrAwaitableType;
if (typeAsAwaitable.awaitedTypeOfType) {
return typeAsAwaitable.awaitedTypeOfType;
// primitives with a `{ then() }` won't be unwrapped/adopted. This prevents `Awaited<T>` when `T extends string`
// (or another primitive), since the `Awaited<T>` type only unwraps `object` types.
if (allTypesAssignableToKind(type, TypeFlags.Primitive | TypeFlags.Never)) {
return type;
}
const promisedType = getPromisedTypeOfPromise(type);
@@ -34694,7 +34789,7 @@ namespace ts {
return undefined;
}
return typeAsAwaitable.awaitedTypeOfType = awaitedType;
return createAwaitedTypeIfNeeded(typeAsAwaitable.awaitedTypeOfType = awaitedType);
}
// The type was not a promise, so it could not be unwrapped any further.
@@ -34714,13 +34809,13 @@ namespace ts {
// be treated as a promise, they can cast to <any>.
if (isThenableType(type)) {
if (errorNode) {
if (!diagnosticMessage) return Debug.fail();
Debug.assertIsDefined(diagnosticMessage);
error(errorNode, diagnosticMessage, arg0);
}
return undefined;
}
return typeAsAwaitable.awaitedTypeOfType = type;
return createAwaitedTypeIfNeeded(typeAsAwaitable.awaitedTypeOfType = type);
}
/**
@@ -34770,7 +34865,7 @@ namespace ts {
if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) {
// The promise type was not a valid type reference to the global promise type, so we
// report an error and return the unknown type.
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(getAwaitedType(returnType) || voidType));
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)));
return;
}
}
@@ -36641,6 +36736,10 @@ namespace ts {
if (iterationTypes === noIterationTypes) return noIterationTypes;
if (iterationTypes === anyIterationTypes) return anyIterationTypes;
const { yieldType, returnType, nextType } = iterationTypes;
// if we're requesting diagnostics, report errors for a missing `Awaited<T>`.
if (errorNode) {
getGlobalAwaitedSymbol(/*reportErrors*/ true);
}
return createIterationTypes(
getAwaitedType(yieldType, errorNode) || anyType,
getAwaitedType(returnType, errorNode) || anyType,
@@ -36667,7 +36766,9 @@ namespace ts {
getIterationTypesOfIterableCached(type, asyncIterationTypesResolver) ||
getIterationTypesOfIterableFast(type, asyncIterationTypesResolver);
if (iterationTypes) {
return iterationTypes;
return use & IterationUse.ForOfFlag ?
getAsyncFromSyncIterationTypes(iterationTypes, errorNode) :
iterationTypes;
}
}
@@ -36756,7 +36857,7 @@ namespace ts {
// While we define these as `any` and `undefined` in our libs by default, a custom lib *could* use
// different definitions.
const { returnType, nextType } = getIterationTypesOfGlobalIterableType(globalType, resolver);
return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(yieldType, returnType, nextType));
return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType));
}
// As an optimization, if the type is an instantiation of the following global type, then
@@ -37097,7 +37198,7 @@ namespace ts {
const isGenerator = !!(functionFlags & FunctionFlags.Generator);
const isAsync = !!(functionFlags & FunctionFlags.Async);
return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) ?? errorType :
isAsync ? getAwaitedType(returnType) ?? errorType :
isAsync ? unwrapAwaitedType(getAwaitedType(returnType) ?? errorType) :
returnType;
}
+7 -5
View File
@@ -1445,11 +1445,13 @@ interface Promise<T> {
*/
type Awaited<T> =
T extends null | undefined ? T : // special case for `null | undefined` when not in `--noImplicitAny` mode
T extends { then(onfulfilled: infer F): any } ? // thenable, extracts the first argument to `then()`
F extends ((value: infer V) => any) ? // if the argument to `then` is callable, extracts the argument
Awaited<V> : // recursively unwrap the value
never : // the argument to `then` was not callable.
T; // non-thenable
T extends object ? // `await` only unwraps object types with a callable then. Non-object types are not unwrapped.
T extends { then(onfulfilled: infer F): any } ? // thenable, extracts the first argument to `then()`
F extends ((value: infer V) => any) ? // if the argument to `then` is callable, extracts the argument
Awaited<V> : // recursively unwrap the value
never : // the argument to `then` was not callable.
T : // argument was not an object
T; // non-thenable
interface ArrayLike<T> {
readonly length: number;
@@ -6,9 +6,9 @@ class C {
>method : () => void
var fn = async () => await this;
>fn : () => Promise<this>
>async () => await this : () => Promise<this>
>await this : this
>fn : () => Promise<Awaited<this>>
>async () => await this : () => Promise<Awaited<this>>
>await this : Awaited<this>
>this : this
}
}
@@ -6,9 +6,9 @@ class C {
>method : () => void
var fn = async () => await this;
>fn : () => Promise<this>
>async () => await this : () => Promise<this>
>await this : this
>fn : () => Promise<Awaited<this>>
>async () => await this : () => Promise<Awaited<this>>
>await this : Awaited<this>
>this : this
}
}
@@ -6,9 +6,9 @@ class C {
>method : () => void
var fn = async () => await this;
>fn : () => Promise<this>
>async () => await this : () => Promise<this>
>await this : this
>fn : () => Promise<Awaited<this>>
>async () => await this : () => Promise<Awaited<this>>
>await this : Awaited<this>
>this : this
}
}
@@ -1,5 +1,5 @@
tests/cases/compiler/doNotElaborateAssignabilityToTypeParameters.ts(3,3): error TS2322: Type 'T | Yadda' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'T | Yadda'.
tests/cases/compiler/doNotElaborateAssignabilityToTypeParameters.ts(3,3): error TS2322: Type 'Yadda | Awaited<T>' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'Yadda | Awaited<T>'.
==== tests/cases/compiler/doNotElaborateAssignabilityToTypeParameters.ts (1 errors) ====
@@ -7,8 +7,8 @@ tests/cases/compiler/doNotElaborateAssignabilityToTypeParameters.ts(3,3): error
let yaddable = await getXOrYadda(x);
return yaddable;
~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'T | Yadda' is not assignable to type 'T'.
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'T | Yadda'.
!!! error TS2322: Type 'Yadda | Awaited<T>' is not assignable to type 'T'.
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'Yadda | Awaited<T>'.
}
interface Yadda {
@@ -4,14 +4,14 @@ async function foo<T>(x: T): Promise<T> {
>x : T
let yaddable = await getXOrYadda(x);
>yaddable : T | Yadda
>await getXOrYadda(x) : T | Yadda
>yaddable : Yadda | Awaited<T>
>await getXOrYadda(x) : Yadda | Awaited<T>
>getXOrYadda(x) : T | Yadda
>getXOrYadda : <T>(x: T) => T | Yadda
>x : T
return yaddable;
>yaddable : T | Yadda
>yaddable : Yadda | Awaited<T>
}
interface Yadda {
@@ -4,7 +4,7 @@ async function f<T>(source: Iterable<T> | AsyncIterable<T>) {
>source : Iterable<T> | AsyncIterable<T>
for await (const x of source) {
>x : T
>x : Awaited<T>
>source : Iterable<T> | AsyncIterable<T>
}
}