Angular 2: Why TypeScript?

https://vsavkin.com/writing-angular-2-in-typescript-1fa77c78d8e8

Angular 2 is written in TypeScript. In this article I will talk about why we made the decision. I’ll also share my experience of working with TypeScript: how it affects the way I write and refactor my code.
I like TypeScript, but you don’t have to
Even though Angular 2 is written in TypeScript, you don’t have to use it to write Angular 2 applications. The framework also works great with ES5, ES6, and Dart.
TypeScript Has Great Tools
The biggest selling point of TypeScript is tooling. It provides advanced autocompletion, navigation, and refactoring. Having such tools is almost a requirement for large projects. Without them the fear changing the code puts the code base in a semi-read-only state, and makes large-scale refactorings very risky and costly.
TypeScript is not the only typed language that compiles to JavaScript. There are other languages with stronger type systems that in theory can provide absolutely phenomenal tooling. But in practice most of them do not have anything other than a compiler. This is because building rich dev tools has to be an explicit goal from day one, which it has been for the TypeScript team. That is why they built language services that can be used by editors to provide type checking and autocompletion. If you have wondered why there are so many editors with great TypeScript supports, the answer is the language services.
The fact that intellisense and basic refactorings (e.g., rename a symbol) are reliable makes a huge impact on the process of writing and especially refactoring code. Although it is hard to measure, I feel that the refactorings that would have taken a few days before now can be done in less than a day.
While TypeScript greatly improves the code editing experience, it makes the dev setup more complex, especially comparing to dropping an ES5 script on a page. In addition, you cannot use tools analyzing JavaScript source code (e.g., JSHint), but there are usually adequate replacements.
TypeScript is a Superset of JavaScript
Since TypeScript is a superset of JavaScript, you don’t need to go through a big rewrite to migrate to it. You can do it gradually, one module at a time.
Just pick a module, rename the .js files into .ts, then incrementally add type annotations. When you are done with this module, pick the next one. Once the whole code base is typed, you can start tweaking the compiler settings to make it more strict.
This process can take some time, but it was not a big problem for Angular 2, when we were migrating to TypeScript. Doing it gradually allowed us to keep developing new functionality and fixing bugs during the transition.
TypeScript Makes Abstractions Explicit
A good design is all about well-defined interfaces. And it is much easier to express the idea of an interface in a language that supports them.
For instance, imagine a book-selling application where a purchase can be made by either a registered user through the UI or by an external system through some sort of an API.
As you can see, both classes play the role of a purchaser. Despite being extremely important for the application, the notion of a purchaser is not clearly expressed in the code. There is no file named purchaser.js. And as a result, it is possible for someone modifying the code to miss the fact that this role even exists.

It is hard, just by looking at the code to tell what objects can play the role of a purchaser, and what methods this role has. We do not know for sure, and we will not get much help from our tools. We have to infer this information manually, which is slow and error-prone.
Now, compare it with a version where we explicitly define the Purchaser interface.

The typed version clearly states that we have the Purchaser interface, and the User and ExternalSystem classes implement it. So TypeScript interfaces allow us to define abstractions/protocols/roles.
It is important to realize that TypeScript does not force us to introduce extra abstractions. The Purchaser abstraction is present in the JavaScript version of the code, but it is not explicitly defined.
In a statically-typed language, boundaries between subsystems are defined using interfaces. Since JavaScript lacks interfaces, boundaries are not well expressed in plain JavaScript. Not being able to clearly see the boundaries, developers start depending on concrete types instead of abstract interfaces, which leads to tight coupling.
My experience of working on Angular 2 before and after our transition to TypeScript reinforced this belief. Defining an interface forces me to think about the API boundaries, helps me define the public interfaces of subsystems, and exposes incidental coupling.
TypeScript Makes Code Easier to Read and Understand
Yes, I know it does not seem intuitive. Let me try to illustrate what I mean with an example. Let’s look at this function jQuery.ajax(). What kind of information can we get from its signature?

The only thing we can tell for sure is that the function takes two arguments. We can guess the types. Maybe the first one is a string and the second one is a configuration object. But it is just a guess, and we might be wrong. We have no idea what options go into the settings object (neither their names nor their types), or what this function returns.
There is no way we can call this function without checking the source code or the documentation. Checking the source code is not a good option?—?the point of having functions and classes is to be able to use them without knowing how they are implemented. In other words, we should rely on their interfaces, not on their implementation. We can check the documentation, but it is not the best developer experience?—?it takes additional time, and the docs are often out-of-date.
So although it is easy to read jQuery.ajax(url, settings), to really understand how to call this function we need to either read its implementation or its docs.
Now, contrast it with a typed version.

It gives us a lot more information.
The first argument of this function is a string.
The settings argument is optional. We can see all the options that can be passed into the function, and not only their names, but also their types.
The function returns a JQueryXHR object, and we can see its properties and functions.
The typed signature is certainly longer than the untyped one, but :string, :JQueryAjaxSettings, and JQueryXHR are not clutter. They are important documentation that improves the comprehensibility of the code. We can understand the code to a much greater degree without having to dive into the implementation or reading the docs. My personal experience is that I can read the typed code faster because types provide more context to understand the code. But if any of the readers can find a study on how types affect code readability, please leave a comment.
One thing that is different about TypeScript comparing to many other languages compiled to JavaScript is that its type annotations are optional, and jQuery.ajax(url, settings) is still valid TypeScript. So instead of an on-off switch, TypeScript’s types are more of a dial. If you find that the code is trivial to read and understand without type annotations, do not use them. Use types only when they add value.
Does TypeScript Limit Expressiveness?
Dynamically-typed languages have inferior tooling, but they are more malleable and expressive. I think using TypeScript makes your code more rigid, but to a much lesser degree than people think. Let me show you what I mean. Let’s say I use ImmutableJS to define the Person record.

How do we type the record? Let’s start with defining an interface called Person:

If we try to do the following:

the TypeScript compiler will complain. It does not know that PersonRecord is actually compatible with Person because PersonRecord is created reflectively. Some of you with the FP background are probably saying: “If only TypeScript had dependent types!” But it does not. TypeScript’s type system is not the most advanced one. But its goal is different. It is not here to prove that the program is 100% correct. It is about giving you more information and enable greater tooling. So it is OK to take shortcuts when the type system is not flexible enough. So we can just cast the created record, as follows:

The typed example:

The reason why it works is because the type system is structural. As long as the created object has the right fields?—?name and age?—?we are good.
You need to embrace the mindset that it is OK to take shortcuts when working with TypeScript. Only then you will find using the language enjoyable. For instance, don’t try to add types to some funky metaprogramming code?—?most likely you won’t be able to express it statically. Type everything around that code, and tell the typechecker to ignore the funky bit. In this case you will not lose a lot of expressiveness, and the bulk of your code will remain toolable and analyzable.
This is similar to trying to get 100% unit test code coverage. Whereas getting 95% is usually not that difficult, getting 100% can be challenging, and may negatively affect the architecture of your application.
The optional type system also preserves the JavaScript development workflow. Large parts of your application’s code base can be “broken”, but you can still run it. TypeScript will keep generating JavaScript, even when the type checker complains. This is extremely useful during development.
Why TypeScript?
There are a lot of options available to frontend devs today: ES5, ES6 (Babel), TypeScript, Dart, PureScript, Elm, etc.. So why TypeScript?
Let’s start with ES5. ES5 has one significant advantage over TypeScript: it does not require a transpiler. This allows you to keep your build setup simple. You do not need to set up file watchers, transpile code, generate source maps. It just works.
ES6 requires a transpiler, so the build setup will not be much different from TypeScript. But it is a standard, which means that every single editor and build tool either supports ES6 or will support it. This is a weaker argument that it used to be as most editors at this point have excellent TypeScript support.
Elm and PureScript are elegant languages with powerful type systems that can prove a lot more about your program than TypeScript can. The code written in Elm and PureScript can be a lot terser than similar code written in ES5.
Each of these options has pros and cons, but I think TypeScript is in a sweet spot that makes it a great choice for most projects. TypeScript takes 95% of the usefulness of a good statically-typed language and brings it to the JavaScript ecosystem. You still feel like you write ES6: you keep using the same standard library, same third-party libraries, same idioms, and many of the same tools (e.g., Chrome dev tools). It gives you a lot without forcing you out of the JavaScript ecosystem.

时间: 2024-10-16 23:19:27

Angular 2: Why TypeScript?的相关文章

Angular基础(三) TypeScript

一.模仿Reddit a) 运行ng new –ng4angular-reddit创建应用,从随书代码中复制样式文件,新建组件app-root,代码为: 界面可以看到了: b) 对于界面输入的数据,获取的方式有点特别,使用了#newlink这样的语法,newlink是一个对象,现在代表就是所在的input这个DOM元素. 将对象作为参数传递给addArticle方法,在对应的ts代码中,可以获取newlink.value.newlink是HTMLInputElement类型. c)关于参数的绑定

码农视角 - Angular 框架起步

开发环境 1.npm 安装最新的Nodejs,便包含此工具.类似Nuget一样的东西,不过与Nuget不同的是,这玩意完全是命令行的.然后用npm来安装开发环境,也就是下边的angular cli. 2.Angular Cli 通过命令行创建项目,“编译”代码,启动调度环境等功能.angular本身使用typescript编写,需要通过ng命令,将相关的ts代码转换成js代码,以便在浏览器中运行. 安装angular cli npm install -g @angular/cli 3.IDE 复

如何选择前端框架:ANGULAR VS EMBER VS REACT

最近一段时间是令前端工程师们非常兴奋的时期,因为三大Web框架陆续发布新版本,让我们见识到了更强大的Web框架.Ember2.0在2个月之前已经发布,从1.0升级到2.0非常简单.几周之前React发布了0.14版本.还有很多流行的前端框架,像Backbone .Knockout及Aurelia.如果你想开发一个Web app,建议采用Angular,Ember或React三种框架中的一个.这三个框架可以说是安全级别最高,技术非常成熟的框架,而且有很多技术社区支持.所以你又开始纠结了,开发Web

VS Code Angular Snippets

Visual Studio Code Beta is available and it supports extensions! I published my first 2 extensions for creating Angular 1 and 2 snippets. You can grab these from the marketplace or right from VS Code. You can browse the VS Code Extension Gallery both

vue、react、angular三大框架对比

前端当前最火的三大框架当属vue.react以及angular了. 但是在做项目的时候,我们怎么去选择呢?  这里做一个比较,希望大家可以有一个比较清晰的认识. vue与react vue和react是当前最火的两个前端框架,vue的发展很快,但是目前来说,react的生态系统会更强大,世界上使用这个框架的人也很多. 另外,react是facebook官方维护的, 而vue是尤雨溪本人维护的. 并且在其他周边库,如react的react-rouer和redux,是react社区在维护的. 而vu

最新 angular 5 入门与提高

一.概述 尽管被称为Angular5,实际上它只是这个诞生于2012年的前端框架的的第四个版本: 看起来差不多半年就发布一个新版本,不过实际上从重写的版本2开始,开发 接口与核心思想就稳定下来了,并基本保持着与前序版本的兼容性. 在5这个新的版本中,Angular团队将改进重点放在以下特性方面: 更易于构建渐进式Web应用 -- Progressive Web App 使用构建优化器剔除无用代码,以获得更小的应用.更快的网络加载时间 使物化设计组件兼容服务端渲染 PWA是Google提出的一个标

Angular 开发环境搭建

Angular 开发环境搭建 1 安装node.js 可以直接去官网https://nodejs.org/en/ 下载: 目的:使用npm 管理项目依赖的软件包: 在cmd 中敲入 npm –version 查看版本号看是否安装成功 2 由于 npm 会自动访问海外的服务器,由于网络的原因,可以使用cnpm yarn 作为替代的包管理工具: cnpm 是淘宝发布的一款工具,会自动把 npm 上面的所有包定时同步到国内的服务器上来,cnpm 本身也是一款 NodeJS 模块. http://npm

angular编译机制

转载https://segmentfault.com/a/1190000011562077 Angular编译机制 前言 这是我用来进行实验的代码,它是基于quickstart项目,并根据aot文档修改得到的.各位可以用它来进行探索,也可以自己基于quickstart进行修改(个人建议后者). 2018年2月17日更新:最近又做了2个小Demo用来研究Angular的编译和打包,基于Angular5,一个使用rollup,一个使用webpack,(rollup目前无法做到Angular的lazy

【Angular专题】——(2)【译】Angular中的ForwardRef

原文地址:https://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html 作者:Christoph Burgdorf 译者注:文章内容比较老,控制台信息等与新框架不完全一致,理解思路即可. 一. 问题点在哪里 先做一个小声明,我们现在拥有一个AppComponent,并使用DI系统向其中注入了一个NameService,因为我们使用的是Typescript,所以需要做的工作就是在构造函数的参数中