Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

How we migrated our huge AngularJS app from CoffeeScript to TypeScript

5,807 views

Published on

How we migrated our huge AngularJS app from CoffeeScript to TypeScript

Published in: Technology
  • If you’re looking for a great essay service then you should check out ⇒ www.HelpWriting.net ⇐. A friend of mine asked them to write a whole dissertation for him and he said it turned out great! Afterwards I also ordered an essay from them and I was very happy with the work I got too.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • PumaToto | Agen Togel Terpercaya PumaToto merupakan Togel Online | Togel Terpercaya dengan Prediksi Togel Akurat | Prediksi Angka Jitu Bagi kalian yang suka bermain Togel Singapore | Togel HK bisa untuk bergabung dengan PumaToto Cara Main Togel | Cara Pasang Togel | Pasang Togel Online di PumaToto, dengan Discount dan Hadiah Menarik Tentunya Daftarkan diri Anda bersama PumaToto https://caramaintogel.com/
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❶❶❶ http://bit.ly/39sFWPG ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating direct: ❶❶❶ http://bit.ly/39sFWPG ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hi there! Get Your Professional Job-Winning Resume Here - Check our website! http://bit.ly/resumpro
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

How we migrated our huge AngularJS app from CoffeeScript to TypeScript

  1. 1. HOW WE MIGRATED OUR HUGE ANGULAR.JS APP FROM COFFEESCRIPT TO TYPESCRIPT Luka Zakrajšek CTO @ Koofr @bancek Ljubljana Spring-ish JavaScript Meetup February 10, 2015
  2. 2. ABOUT ME FRI graduate CTO and cofounder at Koofr frontend, backend, iOS, Windows Phone almost 3 years of Angular.js
  3. 3. KOOFR Koofr is white-label cloud storage solution for ISPs
  4. 4. ANGULAR.JS AT KOOFR web app desktop application (webappwrappedintobrowsertolooklikenative)
  5. 5. HUGE APP? 26 route controllers 90 directives 22 factories 14 filters 15 services 6012 LOC of Coffee (30 files) 2937 LOC of Angular HTML templates (101 files)
  6. 6. WE WERE HAPPY WITH COFFEESCRIPT Pros clean code classes Cons technical debt fear of refactoring not enough tests
  7. 7. COFFEESCRIPT Launched in 2010. Gained traction with Rails support in 2011 $(function(){ //Initializationcodegoeshere }) $-> #Initializationcodegoeshere
  8. 8. BROWSERIFY Lets you require('modules') in the browser by bundling up all of your dependencies. varunique=require('uniq'); vardata=[1,2,2,3,4,5,5,5,6]; console.log(unique(data)); $npminstalluniq $browserifymain.js-obundle.js <scriptsrc="bundle.js"></script>
  9. 9. TYPESCRIPT a typed superset of JavaScript that compiles to plain JavaScript any existing JavaScript program is also valid TypeScript program developed by Microsoft from lead architect of C# and creator of Delphi and Turbo Pascal
  10. 10. FIND A TYPO classPoint{ x:number; y:number; constructor(x:number,y:number){ this.x=x; this.y=y; } getDist(){ returnMath.sqrt(this.x*this.x+ this.y*this.y); } } varp=newPoint(3,4); vardist=p.getDst(); alert("Hypotenuseis:"+dist);
  11. 11. FEATURES
  12. 12. JAVASCRIPT functionGreeter(greeting){ this.greeting=greeting; } Greeter.prototype.greet=function(){ return"Hello,"+this.greeting; } //Oops,we'repassinganobjectwhenwewantastring. vargreeter=newGreeter({message:"world"}); alert(greeter.greet());
  13. 13. TYPES functionGreeter(greeting:string){ this.greeting=greeting; } Greeter.prototype.greet=function(){ return"Hello,"+this.greeting; } vargreeter=newGreeter("world"); alert(greeter.greet());
  14. 14. CLASSES classGreeter{ greeting:string; constructor(message:string){ this.greeting=message; } greet(){ return"Hello,"+this.greeting; } } vargreeter=newGreeter("world"); alert(greeter.greet());
  15. 15. TYPES classAnimal{ constructor(publicname:string){} move(meters:number){ alert(this.name+"moved"+meters+"m."); } } classSnakeextendsAnimal{ constructor(name:string){super(name);} move(){ alert("Slithering..."); super.move(5); } } varsam:Animal=newSnake("SammythePython"); sam.move();
  16. 16. GENERICS classGreeter<T>{ greeting:T; constructor(message:T){ this.greeting=message; } greet(){ returnthis.greeting; } } vargreeter=newGreeter<string>("Hello,world"); alert(greeter.greet());
  17. 17. MODULES moduleSayings{ exportclassGreeter{ greeting:string; constructor(message:string){ this.greeting=message; } greet(){ return"Hello,"+this.greeting; } } } vargreeter=newSayings.Greeter("world"); alert(greeter.greet());
  18. 18. USAGE npminstall-gtypescript tschelloworld.ts <scriptsrc="helloworld.js"></script> Or Grunt, Gulp ...
  19. 19. TOOLS included in Visual Studio JetBrains (IntelliJ) Vim Emacs Sublime Text CATS
  20. 20. MIGRATION coffee-script-to-typescript to the rescue npminstall-gcoffee-script-to-typescritpt coffee-to-typescript-cmayour/files/*.coffee
  21. 21. EXISTING LIBRARIES we use more than 30 libraries to be completely type-safe, you need definitions for all external libraries DefinitelyTyped - more than 700 libraries https://github.com/borisyankov/DefinitelyTyped
  22. 22. EXAMPLE jgrowl.d.ts ///<referencepath="../jquery/jquery.d.ts"/> interfaceJQueryStatic{ jGrowl:jgrowl.JGrowlStatic; } declaremodulejgrowl{ interfaceJGrowlOptions{ sticky?:boolean; position?:string; beforeOpen?:Function; //... } interfaceJGrowlStatic{ (msg:string,options?:JGrowlOptions):void; } } $.jGrowl({sticky:true,beforeOpen:()=>{ console.log("opening")}})
  23. 23. ANGULARJS - BEFORE CoffeeScript angular.module('comments.controllers',[]).directive('comments',-> restrict:'E' scope: mount:'=' replace:yes templateUrl:'comments/comments.html' controller:($scope,Api)-> $scope.comments=[] $scope.load=-> Api.callApi.api.Comments.commentsRange($scope.mount.id,0,10 success:(res)-> $scope.comments=res.comments $scope.load() )
  24. 24. ANGULARJS - AFTER TypeScript ///<referencepath="../app.ts"/> modulecomments{ interfaceCommentsScopeextendsng.IScope{ mount:k.Mount comments:Array<k.Comment> load():void }
  25. 25. exportclassCommentsCtrl{ constructor($scope:CommentsScope,Api:api.Api){ $scope.comments=[]; $scope.load=()=>{ Api.get(Api.api.Comments.commentsRange($scope.mount.id,0, .then((res)=>{ $scope.comments=res.comments; }); } }; } }
  26. 26. exportvarcommentsDirective:ng.IDirectiveFactory=()=>{ return{ restrict:"E", scope:{ mount:"=", appendComment:"=" }, replace:true, templateUrl:"comments/comments.html", controller:CommentsCtrl }; }; }
  27. 27. PROJECT STRUCTURE files/ comments/ utils/ ... app.ts main.d.ts typings.d.ts
  28. 28. PROJECT STRUCTURE app.ts ///<referencepath="main.d.ts"/> ///<referencepath="files/index.ts"/> ///<referencepath="comments/index.ts"/> ///<referencepath="utils/index.ts"/> exportvarmodule=angular.module("app",[ "gettext", files.module.name, comments.module.name, utils.module.name ]) }
  29. 29. PROJECT STRUCTURE comments/index.ts ///<referencepath="../app.ts"/> ///<referencepath="commentsDirective.ts"/> modulecomments{ exportvarmodule=angular.module("comments",[]) .directive("comments",commentsDirective); }
  30. 30. HOW TO TEST EVERYTHING? code coverage to the rescue usually used for test code coverage we can use it to see which lines were covered by manually "testing" the app
  31. 31. LIVECOVER Notpublishedyet.WillbeonGitHubandnpm. #GenerateannotatedJavaScriptcodewithBlanket.js $simple-blanket-oapp-cover.jsapp.js #RunLiveCoverserver $livecover-p3000 <scriptsrc="http://localhost:3000/coverage.js"></script> Open in your browser and start clicking like crazy. https://localhost:3000
  32. 32. QUESTIONS?

×