When working with TypeScript, my Senior and I used a specific approach for implementing requests.
Initially, we created two interfaces for the result set of any request. One interface extended IHttpPromiseCallbackArg, while the other was for our custom output format. Additionally, I preferred creating a third interface for the actual type being returned. In this scenario, I utilized Contacts as my factory and hence required an IContact interface.
interface ICallback<T> extends ng.IHttpPromiseCallbackArg<T> {
data?: T;
}
interface IOutput<T> {
Output: T,
ErrorMsg: string
}
interface IContact {
ContactID: string;
ContactLastName: string;
ContactFirstName: string;
ContactEmail: string;
ContactPhone: string;
ContactFullName: string;
ModifiedBy?: string;
ModifiedOn?: Date;
CreatedBy: string;
CreatedOn: Date;
}
Next, we needed a Notification Factory and RequestHelper Factory.
export class NotificationFactory {
success = function (msg: string, title?: string): void {
this.toastr.success(msg, title);
}
error = function (msg: string, title?: string): void {
this.toastr.error(msg, title);
}
static $inject: Array<string> = ['toastr'];
constructor(private toastr: ng.toastr.IToastrService) {
return this;
}
}
export class RequestHelper {
toastSuccess = function (msg: string, title?: string): void {
this.NotificationFactory.success(msg, title);
}
toastError = function (msg: string, title?: string): void {
this.NotificationFactory.error(msg, title);
}
private success = (results: ICallback<IOutput<any>>, options: IOptions): any => {
if (results.data.ErrorMsg) {
this.NotificationFactory.error(results.data.ErrorMsg);
}
if (typeof options.callback === 'function') {
if (options.showSave && !results.data.ErrorMsg) {
this.NotificationFactory.success('Your changes have been saved.');
}
return options.callback(results.data);
}
if (options.showSave && !results.data.ErrorMsg) {
this.NotificationFactory.success('Your changes have been saved.');
}
return results.data;
}
private fail = (err: any, options: IOptions): ng.IPromise<any> => {
if (options.callingFn !== undefined) {
this.NotificationFactory.error('There was an error calling ' + options.callingFn + '. details:' + err.statusText);
}
return err;
}
makeRequest = (request: IRequest, o?: IOptions): ng.IPromise<any> => {
o = o || {};
var vm = this;
return this.$http(request).then((results: ICallback<IOutput<any>>) => {
return vm.success(results, o);
}).catch((err) => {
return vm.fail(err, o);
});
}
static $inject: Array<string> = ['$http', '$state', '$stateParams', 'NotificationFactory'];
constructor(private $http: ng.IHttpService, private $state: any, private $stateParams: IMyStateParams, private NotificationFactory: NotificationFactory) {
return this;
}
}
We then injected the Request Helper into any factory and called 'makeRequest'.
export class ContactsFactory {
getData = (): ng.IPromise<IOutput<Array<IContact>>> => {
let req = { method: 'GET', url: '/Contacts/GetContacts?d=' + Date.parse(new Date().toString()).toString() };
return this.RequestHelper.makeRequest(req, { callingFn: 'ContactsFactory.getData', callback: null, showSave: false });
}
getContactByID = (id: string): ng.IPromise<IOutput<Array<IContact>>> => {
let req = { method: 'POST', url: '/Contacts/GetContactByID', data: { id: id } };
return this.RequestHelper.makeRequest(req, { callingFn: 'ContactsFactory.getContactByID', callback: null, showSave: false });
}
static $inject: Array<string> = ['RequestHelper', 'UsersFactory'];
constructor(private RequestHelper: RequestHelper, private UsersFactory: UsersFactory) {
return this;
}
}
Finally, our controller would invoke the factory methods.
export class ContactsController {
loading: boolean;
contacts: Array<IContact>;
initialize = (): void => {
this.loading = true;
this.ContactsFactory.getData().then((results) => {
this.contacts = results.Output;
this.loading = false;
});
});
}
static $inject: Array<string> = ['ContactsFactory'];
constructor(private ContactsFactory: ContactsFactory) {
this.initialize();
}
}
I appreciate @Frank's suggestion on type casting the requests. Special thanks to Phxjoe and my Senior Developer for their guidance.