Angular Apps in TypeScript or Dart?
Jake Varness
Posted on December 5, 2017
Edit: if you are new to TypeScript syntax, you might find this article by @abelagoi helpful. If you're new to Dart, I'll try to write something about Dart since nobody else has written about it yet :)
Edit2: Dart for Beginners
In a never-ending struggle to determine which language that compiles into JS is best, Google makes everything even more confusing by offering many ways to write Angular apps. The two main ways you can write Angular apps is in either TypeScript or Dart.
That being said... What should you use? Let's compare what developing the Tour of Heroes application is like in TypeScript as well as in Dart.
The Languages
TypeScript is a typed superset of JavaScript that is built and maintained by Microsoft. You can think of it as JavaScript but with proper types. In TypeScript, you can define interfaces, create classes, all while having first-class support for accessing your favorite JavaScript libraries. You can write JavaScript in your TypeScript code and it will work as expected.
This is extremely important because if you have a favorite NPM library that you want to keep using, you can write the code in TypeScript exactly as you would in JavaScript and everything works smoothly.
Dart is a strongly typed language (required as of Dart 2.0) created and maintained by Google, with first-hand asynchronous support. It can be compiled into JavaScript, but there are some quirks that you need to be aware of, and unlike TypeScript, support for calling JavaScript libraries happens through interoperability libraries built into Dart.
If you have a favorite NPM library that you love and you want to keep using it for your Angular application, you might be tempted to just use TypeScript instead. I personally wouldn't blame you, as interop'ing between Dart and JavaScript doesn't sound particularly great.
However, the Dart Language comes packaged with pub, which allows you download reusable packages from a centralized repo, just like NPM. Packages in pub are categorized to show you that the library will work with web, Flutter, or server/command line development, so if you see a library that only works for Flutter, you probably don't want to use it, nor could you (I might make another post about Flutter later, but we'll see).
Creating a Project
Both the Dart version of Angular and the TypeScript version of Angular offer command line interfaces, and it's pretty easy to make a new project.
For Typescript, use NPM:
$ npm install -g @angular/cli
$ ng new my-angular-project
For Dart, use pub:
$ pub global activate angular_cli
$ ngdart new my_angular_project
Notice that for the Dart the project name uses underscores instead of hyphens. It is considered a convention to use underscores when naming a Dart package or project.
One other thing you might notice is that if you type ng --help
vs ngdart --help
, ng
has a laundry list of things that it can do, whereas ngdart
has three commands available: help
, generate
, and new
.
When a project first gets created, you'll notice a lot of distinct differences between the TypeScript and the Dart projects. In TypeScript, you'll notice there is a src/
folder and an e2e/
folder, where your project source and end-to-end tests exist respectively. In Dart, you'll instead have a web/
folder containing a small amount of HTML necessary for your project to run, and a lib/
folder where all of your Dart source exists. For Dart projects, having all of the Dart source in the lib/
folder is a common practice.
To start the project in TypeScript you can type:
$ ng serve
To start the project in Dart you can type:
$ pub serve
Writing Code
I've pretty much made it through a lot of the Tour of Heroes tutorials in TypeScript as well as in Dart.
If you're looking through the two codebases, one of the things you might notice is that in TypeScript, Angular has support for modules, which helps drive a lot of dependency injection/inversion within an Angular project, and Dart does not. I personally didn't find this to be too cumbersome because a lot of DI principles can be achieved in Angular Dart by using directives and providers, but the modules in TypeScript do help keep your code concise, and it helps to separate responsibilities. You might notice that in the Dart codebase, my AppComponent
pretty much acts as the AppModule
linked above. It has to handle route configuration and be aware of a couple of different providers and directives that it wouldn't otherwise need to be aware of.
Fortunately though, the Angular Dart team is working on getting dependency injection added to version 5.0 of Angular Dart. Again, a lack of DI support isn't convenient, but it doesn't stop you from writing code.
One thing you might notice as well is that the code between the two codebases has some striking similarities. Looking at just the HeroDetailComponent
in each project, you might notice only a few differences between the TypeScript version and the Dart version. It's mostly differences in syntax at this point.
For example, the constructor for this component in Dart looks like this:
HeroDetailComponent(this._heroService, this._routeParams, this._location);
Whereas in TypeScript it looks like:
constructor(
private heroService : HeroService,
private route: ActivatedRoute,
private location: Location
) {}
The main difference here is that TypeScript has keywords to tell you what is private. In Dart, if a member is prefixed with _
, it's a private field.
Another thing you might notice is that with regard to methods, the TypeScript methods look pretty simple:
ngOnInit() : void {
this.route.params
.switchMap((params : Params) => this.heroService.getHero(+params['id']))
.subscribe(hero => this.hero = hero);
}
goBack() : void {
this.location.back();
}
saveHero(): void {
this.heroService.updateHero(this.hero).then(() => this.goBack());
}
Each method returns void. In Dart, since all of the methods within the component are asynchronous, Dart requires a little more syntax:
@override
Future<Null> ngOnInit() async {
int id = int.parse(_routeParams.get('id') ?? '', onError: (_) => null);
if (id != null) hero = await _heroService.getHero(id);
}
void goBack() => _location.back();
Future<Null> save() async {
await _heroService.update(hero);
goBack();
}
In Dart, when you have an asynchronous method defined, you cannot return void
. Instead, the way that you would define a void
async method in Dart is to make it return Future<Null>
. This just tells consumers that while this method is an async method, it doesn't return anything.
Application Look and Feel
I honestly couldn't tell you the difference between the two. Both applications work the same way.
In TypeScript:
In Dart:
The differences are shocking, I know.
The tooling within the Dart application made me forget all the cool tools that I had in TypeScript, with the exception that I wasn't able to put a delay in my services to mimic a real environment. Whenever I tried, I kept getting an exception and just gave up trying to make the app feel real.
Edit 3: I actually got it to work eventually. The issue was that I wasn't using Future.delayed
properly. I was just putting my mock heroes list in as the second param rather than using a closure or function like they suggested in the tutorial.
In both instances, I was able to change code, save, and reload the apps with my changes being reflected without having to start or stop the server. I felt like I had enough resources and libraries at my disposal to accomplish what I needed to (granted, it was a tutorial where all the libraries have already been developed, but ya know...).
Overall
Honestly, I don't really see much of a difference face-up just doing the tutorials. I would say that if you have a lot of existing JS libraries that you like using and want to continue using for your Angular app, you should use TypeScript. If you want to learn something new and you don't like JavaScript, don't be afraid to write your app in Dart.
I hope that you enjoyed this overview of Angular Development using Dart and TypeScript. Have you made an app in Dart or TypeScript? What did you like about either? Let us know!
Posted on December 5, 2017
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.