diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 37ace5741a1..627bf3bb2e2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15546,31 +15546,24 @@ namespace ts { } /** - * Checks the return type of an async function to ensure it is a compatible - * Promise implementation. - * @param node The signature to check - * @param returnType The return type for the function - * @remarks - * This checks that an async function has a valid Promise-compatible return type, - * and returns the *awaited type* of the promise. An async function has a valid - * Promise-compatible return type if the resolved value of the return type has a - * construct signature that takes in an `initializer` function that in turn supplies - * a `resolve` function as one of its arguments and results in an object with a - * callable `then` signature. - */ + * Checks the return type of an async function to ensure it is a compatible + * Promise implementation. + * + * This checks that an async function has a valid Promise-compatible return type, + * and returns the *awaited type* of the promise. An async function has a valid + * Promise-compatible return type if the resolved value of the return type has a + * construct signature that takes in an `initializer` function that in turn supplies + * a `resolve` function as one of its arguments and results in an object with a + * callable `then` signature. + * + * @param node The signature to check + */ function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type { if (languageVersion >= ScriptTarget.ES2015) { const returnType = getTypeFromTypeNode(node.type); return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); } - const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(); - if (globalPromiseConstructorLikeType === emptyObjectType) { - // If we couldn't resolve the global PromiseConstructorLike type we cannot verify - // compatibility with __awaiter. - return unknownType; - } - // As part of our emit for an async function, we will need to emit the entity name of // the return type annotation as an expression. To meet the necessary runtime semantics // for __awaiter, we must also check that the type of the declaration (e.g. the static @@ -15595,42 +15588,56 @@ namespace ts { // then(...): Promise; // } // - // When we get the type of the `Promise` symbol here, we get the type of the static - // side of the `Promise` class, which would be `{ new (...): Promise }`. + // Always mark the type node as referenced if it points to a value + markTypeNodeAsReferenced(node.type); + + const promiseConstructorName = getEntityNameFromTypeNode(node.type); const promiseType = getTypeFromTypeNode(node.type); - if (promiseType === unknownType && compilerOptions.isolatedModules) { - // If we are compiling with isolatedModules, we may not be able to resolve the - // type as a value. As such, we will just return unknownType; + if (promiseType === unknownType) { + if (!compilerOptions.isolatedModules) { + if (promiseConstructorName) { + error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); + } + else { + error(node.type, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type); + } + } return unknownType; } - const promiseConstructor = getNodeLinks(node.type).resolvedSymbol; - if (!promiseConstructor || !symbolIsValue(promiseConstructor)) { - // try to fall back to global promise type. - const typeName = promiseConstructor - ? symbolToString(promiseConstructor) - : typeToString(promiseType); - return checkCorrectPromiseType(promiseType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeName); + if (promiseConstructorName === undefined) { + error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(promiseType)); + return unknownType; } - // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced. - checkReturnTypeAnnotationAsExpression(node); + const promiseConstructorSymbol = resolveEntityName(promiseConstructorName, SymbolFlags.Value, /*ignoreErrors*/ true); + const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : unknownType; + if (promiseConstructorType === unknownType) { + error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); + return unknownType; + } - // Validate the promise constructor type. - const promiseConstructorType = getTypeOfSymbol(promiseConstructor); - if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { + const globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(); + if (globalPromiseConstructorLikeType === emptyObjectType) { + // If we couldn't resolve the global PromiseConstructorLike type we cannot verify + // compatibility with __awaiter. + error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); + return unknownType; + } + + if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type, + Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) { return unknownType; } // Verify there is no local declaration that could collide with the promise constructor. - const promiseName = getEntityNameFromTypeNode(node.type); - const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName); - const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value); - if (rootSymbol) { - error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, - promiseNameOrNamespaceRoot.text, - getFullyQualifiedName(promiseConstructor)); + const rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName); + const collidingSymbol = getSymbol(node.locals, rootName.text, SymbolFlags.Value); + if (collidingSymbol) { + error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, + rootName.text, + entityNameToString(promiseConstructorName)); return unknownType; } @@ -15688,44 +15695,19 @@ namespace ts { errorInfo); } - /** Checks a type reference node as an expression. */ - function checkTypeNodeAsExpression(node: TypeNode) { - // When we are emitting type metadata for decorators, we need to try to check the type - // as if it were an expression so that we can emit the type in a value position when we - // serialize the type metadata. - if (node && node.kind === SyntaxKind.TypeReference) { - const root = getFirstIdentifier((node).typeName); - const meaning = root.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace; - // Resolve type so we know which symbol is referenced - const rootSymbol = resolveName(root, root.text, meaning | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); - // Resolved symbol is alias - if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias) { - const aliasTarget = resolveAlias(rootSymbol); - // If alias has value symbol - mark alias as referenced - if (aliasTarget.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) { - markAliasSymbolAsReferenced(rootSymbol); - } - } - } - } - /** - * Checks the type annotation of an accessor declaration or property declaration as - * an expression if it is a type reference to a type with a value declaration. - */ - function checkTypeAnnotationAsExpression(node: VariableLikeDeclaration) { - checkTypeNodeAsExpression((node).type); - } - - function checkReturnTypeAnnotationAsExpression(node: FunctionLikeDeclaration) { - checkTypeNodeAsExpression(node.type); - } - - /** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */ - function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) { - // ensure all type annotations with a value declaration are checked as an expression - for (const parameter of node.parameters) { - checkTypeAnnotationAsExpression(parameter); + * If a TypeNode can be resolved to a value symbol imported from an external module, it is + * marked as referenced to prevent import elision. + */ + function markTypeNodeAsReferenced(node: TypeNode) { + const typeName = node && getEntityNameFromTypeNode(node); + const rootName = typeName && getFirstIdentifier(typeName); + const rootSymbol = rootName && resolveName(rootName, rootName.text, (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); + if (rootSymbol + && rootSymbol.flags & SymbolFlags.Alias + && symbolIsValue(rootSymbol) + && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) { + markAliasSymbolAsReferenced(rootSymbol); } } @@ -15751,20 +15733,25 @@ namespace ts { case SyntaxKind.ClassDeclaration: const constructor = getFirstConstructorWithBody(node); if (constructor) { - checkParameterTypeAnnotationsAsExpressions(constructor); + for (const parameter of constructor.parameters) { + markTypeNodeAsReferenced(parameter.type); + } } break; case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - checkParameterTypeAnnotationsAsExpressions(node); - checkReturnTypeAnnotationAsExpression(node); + for (const parameter of (node).parameters) { + markTypeNodeAsReferenced(parameter.type); + } + + markTypeNodeAsReferenced((node).type); break; case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: - checkTypeAnnotationAsExpression(node); + markTypeNodeAsReferenced((node).type); break; } } @@ -18476,9 +18463,33 @@ namespace ts { function getDiagnosticsWorker(sourceFile: SourceFile): Diagnostic[] { throwIfNonDiagnosticsProducing(); if (sourceFile) { + // Some global diagnostics are deferred until they are needed and + // may not be reported in the firt call to getGlobalDiagnostics. + // We should catch these changes and report them. + const previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); + const previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length; + checkSourceFile(sourceFile); - return diagnostics.getDiagnostics(sourceFile.fileName); + + const semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName); + const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); + if (currentGlobalDiagnostics !== previousGlobalDiagnostics) { + // If the arrays are not the same reference, new diagnostics were added. + const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics); + return concatenate(deferredGlobalDiagnostics, semanticDiagnostics); + } + else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) { + // If the arrays are the same reference, but the length has changed, a single + // new diagnostic was added as DiagnosticCollection attempts to reuse the + // same array. + return concatenate(currentGlobalDiagnostics, semanticDiagnostics); + } + + return semanticDiagnostics; } + + // Global diagnostics are always added when a file is not provided to + // getDiagnostics forEach(host.getSourceFiles(), checkSourceFile); return diagnostics.getDiagnostics(); } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 2893576f688..dd71877930a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -446,8 +446,8 @@ namespace ts { } export function concatenate(array1: T[], array2: T[]): T[] { - if (!array2 || !array2.length) return array1; - if (!array1 || !array1.length) return array2; + if (!some(array2)) return array1; + if (!some(array1)) return array2; return [...array1, ...array2]; } @@ -527,6 +527,27 @@ namespace ts { return result || array; } + /** + * Gets the relative complement of `arrayA` with respect to `b`, returning the elements that + * are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted + * based on the provided comparer. + */ + export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: (x: T, y: T) => Comparison = compareValues, offsetA = 0, offsetB = 0): T[] | undefined { + if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; + const result: T[] = []; + outer: for (; offsetB < arrayB.length; offsetB++) { + inner: for (; offsetA < arrayA.length; offsetA++) { + switch (comparer(arrayB[offsetB], arrayA[offsetA])) { + case Comparison.LessThan: break inner; + case Comparison.EqualTo: continue outer; + case Comparison.GreaterThan: continue inner; + } + } + result.push(arrayB[offsetB]); + } + return result; + } + export function sum(array: any[], prop: string): number { let result = 0; for (const v of array) { @@ -626,12 +647,12 @@ namespace ts { * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - export function binarySearch(array: T[], value: T, comparer?: (v1: T, v2: T) => number): number { + export function binarySearch(array: T[], value: T, comparer?: (v1: T, v2: T) => number, offset?: number): number { if (!array || array.length === 0) { return -1; } - let low = 0; + let low = offset || 0; let high = array.length - 1; comparer = comparer !== undefined ? comparer diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ef3de5b353c..7d5a1418843 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -163,7 +163,7 @@ "category": "Error", "code": 1054 }, - "Type '{0}' is not a valid async function return type.": { + "Type '{0}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.": { "category": "Error", "code": 1055 }, diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 7800a41e147..548609d676c 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -262,7 +262,8 @@ namespace ts { } function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody { - const nodeType = node.original ? (node.original).type : node.type; + const original = getOriginalNode(node, isFunctionLike); + const nodeType = original.type; const promiseConstructor = languageVersion < ScriptTarget.ES2015 ? getPromiseConstructor(nodeType) : undefined; const isArrowFunction = node.kind === SyntaxKind.ArrowFunction; const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0; @@ -336,15 +337,16 @@ namespace ts { } function getPromiseConstructor(type: TypeNode) { - const typeName = getEntityNameFromTypeNode(type); - if (typeName && isEntityName(typeName)) { - const serializationKind = resolver.getTypeReferenceSerializationKind(typeName); - if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue - || serializationKind === TypeReferenceSerializationKind.Unknown) { - return typeName; + if (type) { + const typeName = getEntityNameFromTypeNode(type); + if (typeName && isEntityName(typeName)) { + const serializationKind = resolver.getTypeReferenceSerializationKind(typeName); + if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue + || serializationKind === TypeReferenceSerializationKind.Unknown) { + return typeName; + } } } - return undefined; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9274d20f76e..d78418e1976 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -485,6 +485,17 @@ namespace ts { return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name); } + export function entityNameToString(name: EntityNameOrEntityNameExpression): string { + switch (name.kind) { + case SyntaxKind.Identifier: + return getFullWidth(name) === 0 ? unescapeIdentifier((name).text) : getTextOfNode(name); + case SyntaxKind.QualifiedName: + return entityNameToString((name).left) + "." + entityNameToString((name).right); + case SyntaxKind.PropertyAccessExpression: + return entityNameToString((name).expression) + "." + entityNameToString((name).name); + } + } + export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic { const sourceFile = getSourceFileOfNode(node); const span = getErrorSpanForNode(sourceFile, node); @@ -1042,17 +1053,19 @@ namespace ts { } export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression { - if (node) { - switch (node.kind) { - case SyntaxKind.TypeReference: - return (node).typeName; - case SyntaxKind.ExpressionWithTypeArguments: - Debug.assert(isEntityNameExpression((node).expression)); - return (node).expression; - case SyntaxKind.Identifier: - case SyntaxKind.QualifiedName: - return (node); - } + switch (node.kind) { + case SyntaxKind.TypeReference: + case SyntaxKind.JSDocTypeReference: + return (node).typeName; + + case SyntaxKind.ExpressionWithTypeArguments: + return isEntityNameExpression((node).expression) + ? (node).expression + : undefined; + + case SyntaxKind.Identifier: + case SyntaxKind.QualifiedName: + return (node); } return undefined; diff --git a/tests/baselines/reference/asyncAliasReturnType_es5.errors.txt b/tests/baselines/reference/asyncAliasReturnType_es5.errors.txt new file mode 100644 index 00000000000..5e524e265e2 --- /dev/null +++ b/tests/baselines/reference/asyncAliasReturnType_es5.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts(3,21): error TS1055: Type 'PromiseAlias' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. + + +==== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts (1 errors) ==== + type PromiseAlias = Promise; + + async function f(): PromiseAlias { + ~~~~~~~~~~~~~~~~~~ +!!! error TS1055: Type 'PromiseAlias' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. + } \ No newline at end of file diff --git a/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js index fe99be204fc..2f11dddf7de 100644 --- a/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js +++ b/tests/baselines/reference/asyncAwaitIsolatedModules_es5.js @@ -77,6 +77,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { } }; var _this = this; +var missing_1 = require("missing"); function f0() { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/]; diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt index 3ea03927aa9..5fa33233912 100644 --- a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt +++ b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS1055: Type '{}' is not a valid async function return type. -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,23): error TS1055: Type 'any' is not a valid async function return type. -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS1055: Type 'number' is not a valid async function return type. -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,23): error TS1055: Type 'PromiseLike' is not a valid async function return type. -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type. -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS1055: Type '{}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,23): error TS1055: Type 'any' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS1055: Type 'number' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,23): error TS1055: Type 'PromiseLike' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. Type 'Thenable' is not assignable to type 'PromiseLike'. Types of property 'then' are incompatible. Type '() => void' is not assignable to type '{ (onfulfilled?: (value: any) => any, onrejected?: (reason: any) => any): PromiseLike; (onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike): PromiseLike; (onfulfilled: (value: any) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; (onfulfilled: (value: any) => TResult1 | PromiseLike, onrejected: (reason: any) => TResult2 | PromiseLike): PromiseLike; }'. @@ -20,21 +20,21 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1 async function fn1() { } // valid: Promise async function fn2(): { } { } // error ~~~ -!!! error TS1055: Type '{}' is not a valid async function return type. +!!! error TS1055: Type '{}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. async function fn3(): any { } // error ~~~ -!!! error TS1055: Type 'any' is not a valid async function return type. +!!! error TS1055: Type 'any' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. async function fn4(): number { } // error ~~~~~~ -!!! error TS1055: Type 'number' is not a valid async function return type. +!!! error TS1055: Type 'number' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. async function fn5(): PromiseLike { } // error ~~~~~~~~~~~~~~~~~ -!!! error TS1055: Type 'PromiseLike' is not a valid async function return type. +!!! error TS1055: Type 'PromiseLike' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. async function fn6(): Thenable { } // error ~~~~~~~~ -!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type. +!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. ~~~~~~~~ -!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type. +!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. !!! error TS1055: Type 'Thenable' is not assignable to type 'PromiseLike'. !!! error TS1055: Types of property 'then' are incompatible. !!! error TS1055: Type '() => void' is not assignable to type '{ (onfulfilled?: (value: any) => any, onrejected?: (reason: any) => any): PromiseLike; (onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike): PromiseLike; (onfulfilled: (value: any) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; (onfulfilled: (value: any) => TResult1 | PromiseLike, onrejected: (reason: any) => TResult2 | PromiseLike): PromiseLike; }'.