WHY JAVASCRIPT NEEDS TYPES
Types have a bad reputation for making code harder to read, adding unnecessary ceremony, and in general complicating things. In this blog post I’d like to show that a type system done right can help make code more readable and toolable without constraining the expressiveness of the language.
DOCUMENTATION FOR HUMANS AND MACHINES
First, I want to show how type annotations can be used as documentation for both humans and machines.
Let’s look at this function jQuery.ajax()
and pretend that we are not familiar with it. What kind of information can we get from its signature?
jQuery.ajax(url, settings)
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.The only option we have here is to check the documentation. And there is nothing wrong with that. Except that it takes time.
Now, contrast it with a typed version.
ajax(url: string, settings?: JQueryAjaxSettings): JQueryXHR;
interface JQueryAjaxSettings {
async?: boolean;
cache?: boolean;
contentType?: any;
headers?: { [key: string]: any; };
//...
}
interface JQueryXHR {
responseJSON?: any;
//...
}
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.
This bring us to my first point.
Types serve as documentation for the programmer.
In addition, this information enables advanced autocompletion, navigation, and refactoring capabilities. Having such tools is almost a requirement for large projects. Without them programmers are afraid to change the code, which makes large-scale refactorings almost impossible. As Anders Hejlsberg puts it, you can build a large application in a dynamically-typed language, but you cannot maintain it. Without advanced tools a large code base is always in a semi-read-only state.
Types enable advanced tools.
TYPES PROVIDE A CONCEPTUAL FRAMEWORK FOR THE PROGRAMMER
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.
function processPurchase(purchaser, details){
}
class User {
}
class ExternalSystem {
}
It is hard, just by looking at the code, 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.
interface Purchaser {
id: int;
bankAccount: Account;
}
class User implements Purchaser {}
class ExternalSystem implements Purchaser {}
The typed version clearly states that we have the Purchaser interface, and the User and ExternalSystem classes implement it. This brings us to my next point.
Types are useful for defining interfaces/protocols/roles. They provide a conceptual framework for the programmer.
It is important to realize that types do 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.
I’ve spent most of my career programming in Ruby and JavaScript, and I find these languages extremely powerful and flexible. But after working on sizeable apps written in these languages, I came to the conclusion that the lack of interfaces pushes developers toward building tightly coupled systems.
In a statically typed language boundaries between subsystems are defined using interfaces. Since Ruby and JavaScript lack interfaces, boundaries are not well expressed in code. Not being able to clearly see the boundaries, developers start depending on concrete types instead of abstract interfaces. And it leads to tight coupling. It is possible to build large decoupled systems in these languages, but it requires a lot of discipline.
STATICALLY TYPED LANGUAGES?
It may seem that I am advocating statically typed languages, but I am not. The arguments against a mandatory static type system are still sound.
- It complicates the language. Writing a mock library in JavaScript is an exercise that almost everyone can undertake. Doing similar stuff in Java is far more difficult.
- It constrains the expressiveness of the language.
- It requires type annotations even when they are not desirable (e.g., in a domain specific language).
What we want is something that combines the power of a dynamically typed language with the benefits of having explicit interfaces and type annotations.
OPTIONAL TYPE SYSTEMS
An optional type system does not require using type annotations. Type annotations are used to help you communicate your intent and get better tooling.
Optional type systems are forgiving. You do not have to satisfy the type checker. Quite the opposite, the type checker is there to help you find typos, search, and refactor. You do not completely rewrite your program to make the types work. If you are prototyping something, and duck typing works, just do not use types. Use them only when they add value.
It would not be completely fair to say that optional typing is only good stuff without any drawbacks. It still adds some complexity to the language (nothing compared to a mandatory static type system though).Also, to fully see the benefits of such a system you need more sophisticated tools than a plain text editor. But because of the reasons I outlined in this blog post, I think it is worth paying this price.
TYPED JAVASCRIPT
I wrote the original version of this blog post some time ago, and called it “I Wish Ruby Had Interfaces”. Back then I was a Rails developer. And I was extremely frustrated by working on a very large Rails code base, where some refactorings were taking months to finish. There was no hope Ruby would get an optional type system, so it was just a rant.
This time it is different. The JavaScript community is embracing the idea of optional types. TypeScript has become a robust tool used in production at many companies. AtScript, and Flow are new projects in this area. I am really excited to see what typed JavaScript community will look like in a few years.
WHY JAVASCRIPT NEEDS TYPES的更多相关文章
- JavaScript data types and data structures
JavaScript data types and data structures Programming languages all have built-in data structures, b ...
- JavaScript & Error Types
JavaScript & Error Types JavaScript提供了8个错误对象,这些错误对象会根据错误类型在try / catch表达式中引发: Error EvalError Ra ...
- [Javascript] Manage Application State with Immutable.js
Learn how Immutable.js data structures are different from native iterable Javascript data types and ...
- JavaScript 中的数字和日期类型
本章节介绍如何掌握Javascript里的数字和日期类型 数字EDIT 在 JavaScript 里面,数字都是双精度浮点类型的 double-precision 64-bit binary form ...
- JavaScript Transpilers: 为什么需要用它们?Babel的使用介绍。
英文原文 https://scotch.io/tutorials/javascript-transpilers-what-they-are-why-we-need-them 摘译(文章内的代码有些过期 ...
- Javascript——概述 && 继承 && 复用 && 私有成员 && 构造函数
原文链接:A re-introduction to JavaScript (JS tutorial) Why a re-introduction? Because JavaScript is noto ...
- 深入理解 JavaScript中的变量、值、传参
1. demo 如果你对下面的代码没有任何疑问就能自信的回答出输出的内容,那么本篇文章就不值得你浪费时间了. var var1 = 1 var var2 = true var var3 = [1,2, ...
- A re-introduction to JavaScript (JS Tutorial) 转载自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
A re-introduction to JavaScript (JS Tutorial) Redirected from https://developer.mozilla.org/en-US/do ...
- 实现JavaScript继承
使用TypeScript或者ES2015+标准中的extends关键字是很容易实现继承的,但这不是本文的重点.JS使用了基于原型(prototype-based)的继承方式,extends只是语法糖, ...
随机推荐
- AS3 判断双击事件
//双击事件触发的时候不触发单击事件 package { import com.greensock.TweenLite; import flash.display.DisplayObjectConta ...
- 【解决Jira】Chrome提示Java插件因过期而遭到阻止(JIRA上传截屏截图)
最近经常被这个问题所困扰:用Chrome访问JIRA上传截屏截图时,地址栏下面弹出通知,提示JAVA插件已过期.但是由于公司要求统一开发环境和设置,不能更新到最新版,就像这样: 结果网页上的Java就 ...
- web deploy 部署到远程服务器(win server 2008 r2) 遇到的问题。。。。
和他遇到的情况一样,最后也解决了 http://www.cnblogs.com/brucejia/archive/2012/07/30/2615416.html 安装的前提是先看下这里: http:/ ...
- [DP题]吃糖果
1944:吃糖果 总时间限制:1000ms内存限制:65536kB 描述 名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0).妈妈告诉 ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #13 使用Block I/O控制器设置I/O优先级
HACK #13 使用Block I/O控制器设置I/O优先级 本节介绍使用Block I/O控制器的功能设置I/O优先级的方法.Block I/O控制器可以将任意进程分组,并对该分组设置I/O的优先 ...
- Solr分组聚合查询之Facet
摘要: Solr的分组聚合是一个笼统的概念,目的就是把查询结果做分类,有多种方式可以做到很类似的结果.也正是由于它们的不同表现,可以适合于多种场景. 何为Facet Facet是一种手段,用来将搜索结 ...
- 测试工具-PICT-微软基于数据项多个取值的正交法用例生成工具
下载 http://download.microsoft.com/download/f/5/5/f55484df-8494-48fa-8dbd-8c6f76cc014b/pict33.msi 这里使用 ...
- STL string 常用函数(转)
string类的构造函数: string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 此外,string类还支持默认构造 ...
- pac (PAC(Proxy Auto Config) 是一个 Script;经由编写这个 Script,我们可以让系统判断在怎么样的情形下,要利用哪一台 Proxy 来进行联机。)
PAC自动代理文件格式,教你如何写PAC文件 PAC文件格式 PAC文件是纯文本格式的,实际上就是JavaScript文件.Chrome/Chromium的扩展Switchy!的"Auto ...
- TCP接入层的负载均衡、高可用、扩展性架构
一.web-server的负载均衡 互联网架构中,web-server接入一般使用nginx来做反向代理,实施负载均衡.整个架构分三层: 上游调用层,一般是browser或者APP 中间反向代理层,n ...