mirror of
https://github.com/zhigang1992/DefinitelyTyped.git
synced 2026-04-01 09:01:45 +08:00
AngularJS: 1) fix for $q.reject in then callbacks, 2) types for $error and $pending (#23115)
* AngularJS: 1) fix an issue with $q.reject in then callbacks, 2) types for $error and $pending Fixes #21333 * Promise typings from lib.d.ts + IPromise<never> hack
This commit is contained in:
committed by
Sheetal Nandi
parent
3c02bc73f8
commit
37c1b1dfea
@@ -548,80 +548,158 @@ namespace TestPromise {
|
||||
const promise: angular.IPromise<TResult> = null;
|
||||
const $q: angular.IQService = null;
|
||||
|
||||
const assertPromiseType = <T>(arg: angular.IPromise<T>) => arg;
|
||||
const reject = $q.reject();
|
||||
|
||||
// promise.then
|
||||
assertPromiseType<any>(promise.then((result) => any));
|
||||
assertPromiseType<any>(promise.then((result) => any, (any) => any));
|
||||
assertPromiseType<any>(promise.then((result) => any, (any) => any, (any) => any));
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => any);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => any, any => any);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => any, any => any, any => any);
|
||||
|
||||
assertPromiseType<never>(promise.then((result) => reject));
|
||||
assertPromiseType<never>(promise.then((result) => reject, (any) => reject));
|
||||
assertPromiseType<never>(promise.then((result) => reject, (any) => reject, (any) => any));
|
||||
// $ExpectType IPromise<never>
|
||||
promise.then(result => reject);
|
||||
// $ExpectType IPromise<never>
|
||||
promise.then(result => reject, any => reject);
|
||||
// $ExpectType IPromise<never>
|
||||
promise.then(result => reject, any => reject, any => any);
|
||||
|
||||
assertPromiseType<TResult>(promise.then((result) => result));
|
||||
assertPromiseType<TResult>(promise.then((result) => tresult));
|
||||
assertPromiseType<TResult>(promise.then((result) => tresultPromise));
|
||||
assertPromiseType<TResult>(promise.then((result) => result, (any) => any));
|
||||
assertPromiseType<TResult>(promise.then((result) => result, (any) => any, (any) => any));
|
||||
assertPromiseType<TResult>(promise.then((result) => result, (any) => reject, (any) => any));
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.then(result => result);
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.then(result => tresult);
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.then(result => tresultPromise);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => result, any => any);
|
||||
// $ExpectType IPromise<number | TResult>
|
||||
promise.then(result => result, any => Math.random());
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => result, any => any, any => any);
|
||||
// $ExpectType IPromise<number | TResult>
|
||||
promise.then(result => result, any => Math.random(), any => any);
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.then(result => result, any => reject, any => any);
|
||||
|
||||
assertPromiseType<angular.IPromise<never> | TResult>(promise.then((result) => anyOf2(reject, result)));
|
||||
assertPromiseType<TResult>(promise.then((result) => anyOf3(result, tresultPromise, reject)));
|
||||
assertPromiseType<TResult>(promise.then(
|
||||
(result) => anyOf3(reject, result, tresultPromise),
|
||||
(reason) => anyOf3(reject, tresult, tresultPromise)
|
||||
));
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.then(result => anyOf2(reject, result));
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.then(result => anyOf3(result, tresultPromise, reject));
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.then(
|
||||
result => anyOf3(reject, result, tresultPromise),
|
||||
reason => anyOf3(reject, tresult, tresultPromise)
|
||||
);
|
||||
|
||||
assertPromiseType<ng.IHttpResponse<TResult>>(promise.then((result) => tresultHttpPromise));
|
||||
// $ExpectType IPromise<IHttpResponse<TResult>>
|
||||
promise.then(result => tresultHttpPromise);
|
||||
|
||||
assertPromiseType<TResult | TOther>(promise.then((result) => result, (any) => tother));
|
||||
assertPromiseType<TResult | angular.IPromise<TResult> | angular.IPromise<never> | TOther | angular.IPromise<TOther>>(promise.then(
|
||||
(result) => anyOf3(reject, result, totherPromise),
|
||||
(reason) => anyOf3(reject, tother, tresultPromise)
|
||||
));
|
||||
// $ExpectType IPromise<TResult | TOther>
|
||||
promise.then(result => result, any => tother);
|
||||
|
||||
assertPromiseType<TResult | TOther>(promise.then<TResult | TOther, TResult>(
|
||||
(result) => anyOf3(tresultPromise, result, totherPromise)
|
||||
));
|
||||
// These are broken and seemingly can't be made to work
|
||||
// with the current limitations of TypeScript.
|
||||
|
||||
assertPromiseType<TResult | TOther>(promise.then((result) => result, (any) => tother, (any) => any));
|
||||
assertPromiseType<TResult | TOther>(promise.then((result) => tresultPromise, (any) => totherPromise));
|
||||
assertPromiseType<TResult | TOther>(promise.then((result) => tresultPromise, (any) => totherPromise, (any) => any));
|
||||
assertPromiseType<ng.IHttpResponse<TResult | TOther>>(promise.then((result) => tresultHttpPromise, (any) => totherHttpPromise));
|
||||
assertPromiseType<ng.IHttpResponse<TResult | TOther>>(promise.then((result) => tresultHttpPromise, (any) => totherHttpPromise, (any) => any));
|
||||
// xExpectType IPromise<TResult | TOther>
|
||||
// promise.then(result => anyOf2(result, totherPromise));
|
||||
// xExpectType IPromise<TResult | TOther>
|
||||
// promise.then(result => anyOf3(reject, result, totherPromise));
|
||||
// xExpectType IPromise<TResult | TOther>
|
||||
// const a4 = promise.then(
|
||||
// result => anyOf3(reject, result, totherPromise),
|
||||
// reason => anyOf3(reject, tother, tresultPromise)
|
||||
// );
|
||||
|
||||
assertPromiseType<TOther>(promise.then((result) => tother));
|
||||
assertPromiseType<TOther>(promise.then((result) => tother, (any) => any));
|
||||
assertPromiseType<TOther>(promise.then((result) => tother, (any) => any, (any) => any));
|
||||
assertPromiseType<TOther>(promise.then((result) => totherPromise));
|
||||
assertPromiseType<TOther>(promise.then((result) => totherPromise, (any) => any));
|
||||
assertPromiseType<TOther>(promise.then((result) => totherPromise, (any) => any, (any) => any));
|
||||
assertPromiseType<ng.IHttpResponse<TOther>>(promise.then((result) => totherHttpPromise));
|
||||
assertPromiseType<ng.IHttpResponse<TOther>>(promise.then((result) => totherHttpPromise, (any) => any));
|
||||
assertPromiseType<ng.IHttpResponse<TOther>>(promise.then((result) => totherHttpPromise, (any) => any, (any) => any));
|
||||
// $ExpectType IPromise<TResult | TOther>
|
||||
promise.then<TResult | TOther, TResult>(result =>
|
||||
anyOf3(tresultPromise, result, totherPromise)
|
||||
);
|
||||
|
||||
assertPromiseType<boolean>(promise.then((result) => tresult, (any) => tother).then(ambiguous => isTResult(ambiguous) ? ambiguous.c : ambiguous.f));
|
||||
// $ExpectType IPromise<TResult | TOther>
|
||||
promise.then(result => result, any => tother, any => any);
|
||||
// $ExpectType IPromise<TResult | TOther>
|
||||
promise.then(result => tresultPromise, any => totherPromise);
|
||||
// $ExpectType IPromise<TResult | TOther>
|
||||
promise.then(result => tresultPromise, any => totherPromise, any => any);
|
||||
// $ExpectType IPromise<IHttpResponse<TResult> | IHttpResponse<TOther>>
|
||||
promise.then(result => tresultHttpPromise, any => totherHttpPromise);
|
||||
// $ExpectType IPromise<IHttpResponse<TResult> | IHttpResponse<TOther>>
|
||||
promise.then(result => tresultHttpPromise, any => totherHttpPromise, any => any);
|
||||
|
||||
// $ExpectType IPromise<TOther>
|
||||
promise.then(result => tother);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => tother, any => any);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => tother, any => any, any => any);
|
||||
// $ExpectType IPromise<TOther>
|
||||
promise.then(result => totherPromise);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => totherPromise, any => any);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => totherPromise, any => any, any => any);
|
||||
// $ExpectType IPromise<IHttpResponse<TOther>>
|
||||
promise.then(result => totherHttpPromise);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => totherHttpPromise, any => any);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.then(result => totherHttpPromise, any => any, any => any);
|
||||
|
||||
// $ExpectType IPromise<boolean>
|
||||
promise
|
||||
.then(result => tresult, any => tother)
|
||||
.then(ambiguous => (isTResult(ambiguous) ? ambiguous.c : ambiguous.f));
|
||||
|
||||
// promise.then + $q.reject:
|
||||
|
||||
// $ExpectType IPromise<number>
|
||||
$q.resolve(true).then(result => Math.random() > 0.5 ? Math.random() : $q.reject());
|
||||
// $ExpectType IPromise<number>
|
||||
$q.resolve(true).then(result => Math.random() > 0.5 ? Math.random() : $q.reject('a'));
|
||||
// $ExpectType IPromise<never>
|
||||
$q.resolve().then(() => $q.reject('a'));
|
||||
// $ExpectType IPromise<void>
|
||||
$q.resolve().then(() => {
|
||||
if (Math.random() > 0.5) $q.reject();
|
||||
});
|
||||
|
||||
// promise.catch
|
||||
assertPromiseType<any>(promise.catch((err) => err));
|
||||
assertPromiseType<any>(promise.catch((err) => any));
|
||||
assertPromiseType<TResult>(promise.catch((err) => tresult));
|
||||
assertPromiseType<TResult | angular.IPromise<never>>(promise.catch((err) => anyOf2(tresult, reject)));
|
||||
assertPromiseType<TResult>(promise.catch((err) => anyOf3(tresult, tresultPromise, reject)));
|
||||
assertPromiseType<TResult>(promise.catch((err) => tresultPromise));
|
||||
assertPromiseType<TResult | ng.IHttpResponse<TResult>>(promise.catch((err) => tresultHttpPromise));
|
||||
assertPromiseType<TResult | TOther>(promise.catch((err) => tother));
|
||||
assertPromiseType<TResult | TOther>(promise.catch((err) => totherPromise));
|
||||
assertPromiseType<TResult | ng.IHttpResponse<TOther>>(promise.catch((err) => totherHttpPromise));
|
||||
// $ExpectType IPromise<any>
|
||||
promise.catch(err => err);
|
||||
// $ExpectType IPromise<any>
|
||||
promise.catch(err => any);
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.catch(err => tresult);
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.catch(err => anyOf2(tresult, reject));
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.catch(err => anyOf3(tresult, tresultPromise, reject));
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.catch(err => tresultPromise);
|
||||
// $ExpectType IPromise<TResult | IHttpResponse<TResult>>
|
||||
promise.catch(err => tresultHttpPromise);
|
||||
// $ExpectType IPromise<TResult | TOther>
|
||||
promise.catch(err => tother);
|
||||
// $ExpectType IPromise<TResult | TOther>
|
||||
promise.catch(err => totherPromise);
|
||||
// $ExpectType IPromise<TResult | IHttpResponse<TOther>>
|
||||
promise.catch(err => totherHttpPromise);
|
||||
|
||||
assertPromiseType<boolean>(promise.catch((err) => tother).then(ambiguous => isTResult(ambiguous) ? ambiguous.c : ambiguous.f));
|
||||
// $ExpectType IPromise<boolean>
|
||||
promise
|
||||
.catch(err => tother)
|
||||
.then(
|
||||
ambiguous => (isTResult(ambiguous) ? ambiguous.c : ambiguous.f)
|
||||
);
|
||||
|
||||
// promise.finally
|
||||
assertPromiseType<TResult>(promise.finally(() => any));
|
||||
assertPromiseType<TResult>(promise.finally(() => tresult));
|
||||
assertPromiseType<TResult>(promise.finally(() => tother));
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.finally(() => any);
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.finally(() => tresult);
|
||||
// $ExpectType IPromise<TResult>
|
||||
promise.finally(() => tother);
|
||||
}
|
||||
|
||||
function test_angular_forEach() {
|
||||
@@ -1187,6 +1265,24 @@ function NgModelControllerTyping() {
|
||||
};
|
||||
}
|
||||
|
||||
// FormController
|
||||
angular.module('app').directive('formDebugChecker', () => {
|
||||
return {
|
||||
require: '^^form',
|
||||
link: (scope, el, attrs, ctrl) => {
|
||||
const form = ctrl as angular.IFormController;
|
||||
el.on('click', () => {
|
||||
const report = [] as string[];
|
||||
angular.forEach(form.$error, (controls, validationErrorKey) => {
|
||||
const names = controls.map(control => control.$name);
|
||||
report.push(`${validationErrorKey}: ${controls.length} control(s) (${names.join(', ')})`);
|
||||
});
|
||||
console.log(`This form has ${report.length} error(s).\n${report.join('\n')}`);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
let $filter: angular.IFilterService;
|
||||
|
||||
function testFilter() {
|
||||
|
||||
49
types/angular/index.d.ts
vendored
49
types/angular/index.d.ts
vendored
@@ -357,9 +357,9 @@ declare namespace angular {
|
||||
$valid: boolean;
|
||||
$invalid: boolean;
|
||||
$submitted: boolean;
|
||||
$error: any;
|
||||
$name: string;
|
||||
$pending: any;
|
||||
$error: { [validationErrorKey: string]: Array<INgModelController | IFormController> };
|
||||
$name?: string;
|
||||
$pending?: { [validationErrorKey: string]: Array<INgModelController | IFormController> };
|
||||
$addControl(control: INgModelController | IFormController): void;
|
||||
$removeControl(control: INgModelController | IFormController): void;
|
||||
$setValidity(validationErrorKey: string, isValid: boolean, control: INgModelController | IFormController): void;
|
||||
@@ -399,8 +399,8 @@ declare namespace angular {
|
||||
$parsers: IModelParser[];
|
||||
$formatters: IModelFormatter[];
|
||||
$viewChangeListeners: IModelViewChangeListener[];
|
||||
$error: any;
|
||||
$name: string;
|
||||
$error: { [validationErrorKey: string]: boolean };
|
||||
$name?: string;
|
||||
|
||||
$touched: boolean;
|
||||
$untouched: boolean;
|
||||
@@ -408,7 +408,7 @@ declare namespace angular {
|
||||
$validators: IModelValidators;
|
||||
$asyncValidators: IAsyncModelValidators;
|
||||
|
||||
$pending: any;
|
||||
$pending?: { [validationErrorKey: string]: boolean };
|
||||
$pristine: boolean;
|
||||
$dirty: boolean;
|
||||
$valid: boolean;
|
||||
@@ -1103,28 +1103,43 @@ declare namespace angular {
|
||||
|
||||
interface IPromise<T> {
|
||||
/**
|
||||
* Regardless of when the promise was or will be resolved or rejected, then calls one of the success or error callbacks asynchronously as soon as the result is available. The callbacks are called with a single argument: the result or rejection reason. Additionally, the notify callback may be called zero or more times to provide a progress indication, before the promise is resolved or rejected.
|
||||
* The successCallBack may return IPromise<never> for when a $q.reject() needs to be returned
|
||||
* This method returns a new promise which is resolved or rejected via the return value of the successCallback, errorCallback. It also notifies via the return value of the notifyCallback method. The promise can not be resolved or rejected from the notifyCallback method.
|
||||
* Regardless of when the promise was or will be resolved or rejected, then calls one of
|
||||
* the success or error callbacks asynchronously as soon as the result is available. The
|
||||
* callbacks are called with a single argument: the result or rejection reason.
|
||||
* Additionally, the notify callback may be called zero or more times to provide a
|
||||
* progress indication, before the promise is resolved or rejected.
|
||||
* The `successCallBack` may return `IPromise<never>` for when a `$q.reject()` needs to
|
||||
* be returned.
|
||||
* This method returns a new promise which is resolved or rejected via the return value
|
||||
* of the `successCallback`, `errorCallback`. It also notifies via the return value of
|
||||
* the `notifyCallback` method. The promise can not be resolved or rejected from the
|
||||
* `notifyCallback` method.
|
||||
*/
|
||||
then<TResult>(successCallback: (promiseValue: T) => IPromise<TResult>|TResult, errorCallback?: null, notifyCallback?: (state: any) => any): IPromise<TResult>;
|
||||
then<TResult1, TResult2>(successCallback: (promiseValue: T) => IPromise<TResult1>|TResult2, errorCallback?: null, notifyCallback?: (state: any) => any): IPromise<TResult1 | TResult2>;
|
||||
|
||||
then<TResult, TCatch>(successCallback: (promiseValue: T) => IPromise<TResult>|TResult, errorCallback: (reason: any) => IPromise<TCatch>|TCatch, notifyCallback?: (state: any) => any): IPromise<TResult | TCatch>;
|
||||
then<TResult1, TResult2, TCatch1, TCatch2>(successCallback: (promiseValue: T) => IPromise<TResult1>|TResult2, errorCallback: (reason: any) => IPromise<TCatch1>|TCatch2, notifyCallback?: (state: any) => any): IPromise<TResult1 | TResult2 | TCatch1 | TCatch2>;
|
||||
then<TResult1 = T, TResult2 = never>(
|
||||
successCallback?:
|
||||
| ((value: T) => IPromise<never> | IPromise<TResult1> | TResult1)
|
||||
| null,
|
||||
errorCallback?:
|
||||
| ((reason: any) => IPromise<never> | IPromise<TResult2> | TResult2)
|
||||
| null,
|
||||
notifyCallback?: (state: any) => any
|
||||
): IPromise<TResult1 | TResult2>;
|
||||
|
||||
/**
|
||||
* Shorthand for promise.then(null, errorCallback)
|
||||
*/
|
||||
catch<TCatch>(onRejected: (reason: any) => IPromise<TCatch>|TCatch): IPromise<T | TCatch>;
|
||||
catch<TCatch1, TCatch2>(onRejected: (reason: any) => IPromise<TCatch1>|TCatch2): IPromise<T | TCatch1 | TCatch2>;
|
||||
catch<TResult = never>(
|
||||
onRejected?:
|
||||
| ((reason: any) => IPromise<never> | IPromise<TResult> | TResult)
|
||||
| null
|
||||
): IPromise<T | TResult>;
|
||||
|
||||
/**
|
||||
* Allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful to release resources or do some clean-up that needs to be done whether the promise was rejected or resolved. See the full specification for more information.
|
||||
*
|
||||
* Because finally is a reserved word in JavaScript and reserved keywords are not supported as property names by ES3, you'll need to invoke the method like promise['finally'](callback) to make your code IE8 and Android 2.x compatible.
|
||||
*/
|
||||
finally(finallyCallback: () => any): IPromise<T>;
|
||||
finally(finallyCallback: () => void): IPromise<T>;
|
||||
}
|
||||
|
||||
interface IDeferred<T> {
|
||||
|
||||
Reference in New Issue
Block a user