mirror of
https://github.com/zhigang1992/DefinitelyTyped.git
synced 2026-04-01 12:42:58 +08:00
AngularJS: fixed typing of the ng.IPromise.then function
The type definition for ng.IPromise.then was, in my opinion, incorrect semantically, and breaking on practical examples in my codebase. An `IPromise`' `then` function takes a callback which is called with the value of the promise once it's fulfilled. This could be a number, a string, some object, an array of strings, anything really. Yet the typing in angular.d.ts specified `then` as taking a `successCallback` of type `(response: PromiseCallbackArg) => any`. The definition of `PromiseCallbackArg` seems very permissive at first glance, as it is defined to be an object with a bunch of fields, all optional. Any object, a number, and a string all type check correctly with such a type, but an array of strings, for example, does not (`cPromise` in the provided list of test). Furthermore, it seems to me that the `PromiseCallbackArg` definition was added specifically to support the response type for promises returned by the Angular `$http` service, the `ng.IHttpPromise`. So instead of having an incorrect type on the `ng.IPromise.then` function, I propose we return it to its generic form, and instead override the type of the inherited `then` function in the `ng.IHttpPromise` interface. This would also warrant renaming `PromiseCallbackArg` to `IHttpPromiseCallbackArg`.
This commit is contained in:
@@ -58,11 +58,11 @@ angular.module('http-auth-interceptor', [])
|
||||
.config(['$httpProvider', 'authServiceProvider', <any>function ($httpProvider: ng.IHttpProvider, authServiceProvider) {
|
||||
|
||||
var interceptor = ['$rootScope', '$q', <any>function ($rootScope: ng.IScope, $q: ng.IQService) {
|
||||
function success(response: ng.PromiseCallbackArg) {
|
||||
function success(response: ng.IHttpPromiseCallbackArg) {
|
||||
return response;
|
||||
}
|
||||
|
||||
function error(response: ng.PromiseCallbackArg) {
|
||||
function error(response: ng.IHttpPromiseCallbackArg) {
|
||||
if (response.status === 401) {
|
||||
var deferred = $q.defer();
|
||||
authServiceProvider.pushToBuffer(response.config, deferred);
|
||||
@@ -79,4 +79,62 @@ angular.module('http-auth-interceptor', [])
|
||||
|
||||
}];
|
||||
$httpProvider.responseInterceptors.push(interceptor);
|
||||
}]);
|
||||
}]);
|
||||
|
||||
|
||||
module HttpAndRegularPromiseTests {
|
||||
interface Person {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
}
|
||||
|
||||
interface ExpectedResponse extends Person {}
|
||||
|
||||
interface SomeControllerScope extends ng.IScope {
|
||||
person: Person;
|
||||
theAnswer: number;
|
||||
letters: string[];
|
||||
}
|
||||
|
||||
interface OurApiPromiseCallbackArg extends ng.IHttpPromiseCallbackArg {
|
||||
data?: ExpectedResponse;
|
||||
}
|
||||
|
||||
var someController: Function = ($scope: SomeControllerScope, $http: ng.IHttpService, $q: ng.IQService) => {
|
||||
$http.get("http://somewhere/some/resource")
|
||||
.success((data: ExpectedResponse) => {
|
||||
$scope.person = data;
|
||||
});
|
||||
|
||||
$http.get("http://somewhere/some/resource")
|
||||
.then((response: ng.IHttpPromiseCallbackArg) => {
|
||||
// typing lost, so something like
|
||||
// var i: number = response.data
|
||||
// would type check
|
||||
$scope.person = response.data;
|
||||
});
|
||||
|
||||
$http.get("http://somewhere/some/resource")
|
||||
.then((response: OurApiPromiseCallbackArg) => {
|
||||
// typing lost, so something like
|
||||
// var i: number = response.data
|
||||
// would NOT type check
|
||||
$scope.person = response.data;
|
||||
});
|
||||
|
||||
var aPromise: ng.IPromise = $q.when({firstName: "Jack", lastName: "Sparrow"});
|
||||
aPromise.then((person: Person) => {
|
||||
$scope.person = person;
|
||||
});
|
||||
|
||||
var bPromise: ng.IPromise = $q.when(42);
|
||||
bPromise.then((answer: number) => {
|
||||
$scope.theAnswer = answer;
|
||||
});
|
||||
|
||||
var cPromise: ng.IPromise = $q.when(["a", "b", "c"]);
|
||||
cPromise.then((letters: string[]) => {
|
||||
$scope.letters = letters;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
19
angularjs/angular.d.ts
vendored
19
angularjs/angular.d.ts
vendored
@@ -385,15 +385,8 @@ module ng {
|
||||
when(value: any): IPromise;
|
||||
}
|
||||
|
||||
interface PromiseCallbackArg {
|
||||
data?: any;
|
||||
status?: number;
|
||||
headers?: (headerName: string) => string;
|
||||
config?: IRequestConfig;
|
||||
}
|
||||
|
||||
interface IPromise {
|
||||
then(successCallback: (response: PromiseCallbackArg) => any, errorCallback?: (response: PromiseCallbackArg) => any): IPromise;
|
||||
then(successCallback: (promiseValue: any) => any, errorCallback?: (reason: any) => any): IPromise;
|
||||
}
|
||||
|
||||
interface IDeferred {
|
||||
@@ -524,9 +517,17 @@ module ng {
|
||||
transformResponse?: any;
|
||||
}
|
||||
|
||||
interface IHttpPromiseCallbackArg {
|
||||
data?: any;
|
||||
status?: number;
|
||||
headers?: (headerName: string) => string;
|
||||
config?: IRequestConfig;
|
||||
}
|
||||
|
||||
interface IHttpPromise extends IPromise {
|
||||
success(callback: (data: any, status: number, headers: (headerName: string) => string, config: IRequestConfig) => any): IHttpPromise;
|
||||
error(callback: (data: any, status: number, headers: (headerName: string) => string, config: IRequestConfig) => any): IHttpPromise;
|
||||
then(successCallback: (response: IHttpPromiseCallbackArg) => any, errorCallback?: (response: IHttpPromiseCallbackArg) => any): IPromise;
|
||||
}
|
||||
|
||||
interface IHttpProvider extends IServiceProvider {
|
||||
@@ -658,4 +659,4 @@ module ng {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user