Monday, September 7, 2015

TypeScript All Things

On following Angular controller code, the second parameter Item looks odd, it has no type.

And the only way we can get TypeScript's autocomplete goodness on that Item service is to explicitly assign the type on Item service's $promise's callback argument. We cannot get autocomplete support on customQuery method.

constructor(
    product: Domain.Product, 
    Item, 
    $stateParams, 
    appWide: SharedState.AppWide) 
{

    appWide.title = "Products";

    this.product = product;

    var tag = $stateParams.tag === undefined ? "" : $stateParams.tag;

    product.searched = tag === "" ? "" : "tag:" + tag.replaceAll("--", " ");

    product.search = () => {
        this.searched = product.searched;

        Item.customQuery({keywords: this.searched})
            .$promise.then((items : 
                Dto.SearchDto
                ) => {
                this.itemSearched = items.matches;
                product.tags = items.tags;
                product.locations = items.locations;
            });
    }; // search

    product.search();

}

Definition of Dto.SearchDto:
module Dto {
    export class SearchLocationDto {
        locationId: string;
        locationName: string;
    }

    export class SearchItemDto {
        itemId : number;
        itemTitle: string;
        itemDescription: string;
        itemTags: string;
    }

    export class SearchDto {
        matches: SearchItemDto[];
        tags: string[]  ;
        locations: SearchLocationDto[];
    }
}

Definition of Dto.IItemReturnedDto. This is the type of save's then's success callback argument. Just a primary key
module Dto {
    export interface IItemReturnedDto {
        item_id : number;
    }
}


Then on module initialization, objects are just returned typeless:
var mod:ng.IModule = angie.module('niceApp', ['ui.router', 'ngResource', 'scs.couch-potato', 'ngFileUpload']);

mod.factory('Item', ['$resource', ($resource:angular.resource.IResourceService) => {

    return $resource("/api/item-secured/:theItemId", null, {
        customQuery: {method: 'GET', isArray: false}
    });

}]);


To improve the above, provide type on a service derived from Angular's $resource. Following is the interface definition of customized angular resource method customQuery.
module InhouseLib {

    export interface ISearchParameter {
        keywords: string;
    }

    // the returned when doing save on resource is Dto.IItemReturnedDto
    export interface ISearchResource extends ng.resource.IResourceClass<ng.resource.IResource<Dto.IItemReturnedDto>> { 
        customQuery(ISearchParameter) : angular.resource.IResource<Dto.SearchDto>;
    }
}

Then on module initialization, use the type defined above.
mod.factory('Item', ['$resource', ($resource:ng.resource.IResourceService) : InhouseLib.ISearchResource => {


   var customQueryAction : ng.resource.IActionDescriptor = {
       method: 'GET',
       isArray: false
   };

   var r = <InhouseLib.ISearchResource> $resource ("/api/item/:theItemId", null, {
       customQuery: customQueryAction
   });

   return r;

}]);


Now on controller constructor, add the type for Item (line 3 on code at the bottom). Doing that, the autocomplete for customQuery on Item service shall pop-up upon typing the dot character.




And also, we can also now eliminate (on line 20) the type (Dto.SearchDto) of the callback argument items:

constructor(
     product: Domain.Product, 
     Item: InhouseLib.ISearchResource, 
     $stateParams, 
     appWide: SharedState.AppWide) 
 {

    appWide.title = "Products";

    this.product = product;

    var tag = $stateParams.tag === undefined ? "" : $stateParams.tag;

    product.searched = tag === "" ? "" : "tag:" + tag.replaceAll("--", " ");

    product.search = () => {
        this.searched = product.searched;

        Item.customQuery({keywords: this.searched})
            .$promise.then(items => {
                this.itemSearched = items.matches;
                product.tags = items.tags;
                product.locations = items.locations;
            });

    }; // search

    product.search();

}

And yet the IDE is smart to know the type and it gives an autocomplete when you type the variable name(items) and dot symbol. TypeScript and WebStorm IDE are nice.

No comments:

Post a Comment