Merge pull request #11430 from Microsoft/fixAsyncReturnTypeCheck

Fix async return type check
This commit is contained in:
Ron Buckton
2016-10-31 15:18:11 -07:00
committed by GitHub
8 changed files with 179 additions and 121 deletions

View File

@@ -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<U>(...): Promise<U>;
// }
//
// 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 <T>(...): Promise<T> }`.
// 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((<TypeReferenceNode>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((<PropertyDeclaration>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(<ClassDeclaration>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(<FunctionLikeDeclaration>node);
checkReturnTypeAnnotationAsExpression(<FunctionLikeDeclaration>node);
for (const parameter of (<FunctionLikeDeclaration>node).parameters) {
markTypeNodeAsReferenced(parameter.type);
}
markTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
break;
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.Parameter:
checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
markTypeNodeAsReferenced((<PropertyDeclaration | ParameterDeclaration>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();
}

View File

@@ -446,8 +446,8 @@ namespace ts {
}
export function concatenate<T>(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<T>(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<T>(array: T[], value: T, comparer?: (v1: T, v2: T) => number): number {
export function binarySearch<T>(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

View File

@@ -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
},

View File

@@ -262,7 +262,8 @@ namespace ts {
}
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
const nodeType = node.original ? (<FunctionLikeDeclaration>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;
}

View File

@@ -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((<Identifier>name).text) : getTextOfNode(name);
case SyntaxKind.QualifiedName:
return entityNameToString((<QualifiedName>name).left) + "." + entityNameToString((<QualifiedName>name).right);
case SyntaxKind.PropertyAccessExpression:
return entityNameToString((<PropertyAccessEntityNameExpression>name).expression) + "." + entityNameToString((<PropertyAccessEntityNameExpression>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 (<TypeReferenceNode>node).typeName;
case SyntaxKind.ExpressionWithTypeArguments:
Debug.assert(isEntityNameExpression((<ExpressionWithTypeArguments>node).expression));
return <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression;
case SyntaxKind.Identifier:
case SyntaxKind.QualifiedName:
return (<EntityName><Node>node);
}
switch (node.kind) {
case SyntaxKind.TypeReference:
case SyntaxKind.JSDocTypeReference:
return (<TypeReferenceNode>node).typeName;
case SyntaxKind.ExpressionWithTypeArguments:
return isEntityNameExpression((<ExpressionWithTypeArguments>node).expression)
? <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression
: undefined;
case SyntaxKind.Identifier:
case SyntaxKind.QualifiedName:
return (<EntityName><Node>node);
}
return undefined;

View File

@@ -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<T> = Promise<T>;
async function f(): PromiseAlias<void> {
~~~~~~~~~~~~~~~~~~
!!! 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.
}

View File

@@ -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*/];

View File

@@ -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<any>'.
Types of property 'then' are incompatible.
Type '() => void' is not assignable to type '{ (onfulfilled?: (value: any) => any, onrejected?: (reason: any) => any): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; }'.
@@ -20,21 +20,21 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1
async function fn1() { } // valid: Promise<void>
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<void> { } // 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<any>'.
!!! 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<any>; <TResult>(onfulfilled: (value: any) => any, onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<any>; <TResult>(onfulfilled: (value: any) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>; <TResult1, TResult2>(onfulfilled: (value: any) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>; }'.