[Node.js] 使用TypeScript編寫Node項目
原文地址:http://www.moye.me/2015/04/25/using_typescript/
入 TypeScript 坑有一段時間了,由衷的看好,所以決定在自留地絮叨一番。
是什么
TypeScript (以下簡稱TS)是巨硬推出的JavaScript轉譯語言,這意味著:
- 它需要編譯
- TS代碼會被編譯成JavaScript代碼 </ol>
- TypeScript Handbook:online version
TS的特點是提供 模塊、類、接口等一系列類型概念,協助開發者在編譯時就定位出一些傳統JavaScript項目的運行時錯誤,以實現巨硬所謂的”Robust components”(值得一提的是,TS是大名鼎鼎的 Anders Hejlsberg 主導的項目。
為什么
JavaScript 一般被視為一種動態類型、弱類型的語言,它擁有巨大的靈活性。 如下所示,類型的變化并不受約束:
var x = 10; console.log(typeof x); // result -> number x = 'hello'; console.log(typeof x); // result -> string
那么TS引入的類型概念,又為哪般呢?來看一個示例:
我有一個求和的函數
function sum(x, y){ return x + y; }
但是你也可以這么用,JavaScript沒有意見,雖然結果不合理:
sum(100, 'hello'); // result -> 100hello
于是,我們用TS這樣的限定,保證以上調用是通不過編譯的(輸入都是number,返回也必須是number:
function sum(x:number, y:number):number { return x + y; }
因為我們堅信,對一個數字和一個字符串進行求和,不是一種理智的需求——且,sum這時求和的結果是可信的了。
類示例
在 Node 中,因為流和事件機制的強大,很多時候我們都會讓自己的類去繼承 events.EventEmitter,JS代碼看起來就像是這樣:
var events = require('events'); var util = require('util'); function MyClass(){ events.EventEmitter.call(this); } util.inherits(MyClass, events.EventEmitter);
如果你熟悉Node的一套理論,倒也還好,但其實用TS,能寫出更優雅的代碼:
import events = require('events'); import util = require('util'); export class MyClass extends events.EventEmitter{ constructor(){ super(); } }
具體的語法規范這里不做解釋,有興趣的可以參考官方的 Specification。
這里想說的是,TS生成的JS代碼質量很高,上述片斷生成的代碼(閉包防污染也考慮到了:
var __extends = this.__extends || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } __.prototype = b.prototype; d.prototype = new __(); }; var events = require('events'); var MyClass = (function (_super) { __extends(MyClass, _super); function MyClass() { _super.call(this); } return MyClass; })(events.EventEmitter); exports.MyClass = MyClass;
在WebStrom中使用
鄙人已退 Windows 開發保平安,也就只能說說WebStorm的使用問題了:
首先,你得有一個TS編譯器
npm install -g typescript
然后,在第一次新建.ts文件的時候,WebStorm會詢問是否為.ts文件添加watcher,這樣在文件有保存動作時,watcher會自動調用編譯器去編譯&生成——我的選項是“否”:稍微一點的項目都會使用Grunt/Gulp之類的自動化構建工具,編譯也就會納入為構建的一份子,那么以Grunt為例,編譯這事交給 grunt-ts 就再合理不過了。grunt-ts配置示例:
ts: { default: { src: ['**/*.ts', '!node_modules/**/*.ts'], target: 'es5', outDir: '/repo/releases', options: { fast: "never", module: "commonjs", sourceMap: false, suppressImplicitAnyIndexErrors: true, preserveConstEnums: true } } }
TS 在對待import require的庫時,有它自己的一套理論:它需要一個.d.ts文件來說明引用庫的Schema,比如引用underscore:
import underscore = require('underscore');
那么在項目中,需要存在一個 underscore.d.ts,其中聲明這么一句(完整示例請參考underscore.d.ts:
declare module "underscore" { export = _; //... }
然后在引用的地方聲明一個.d.ts,引入:
///<reference path="underscore.d.ts"/>
如此一來,方可正確通過編譯,亦能得到WebStorm的智能提示。當然,如果不爽這種麻煩的引用,也可以不用import,直接使用如下形式來跳過TS檢查:
var underscore = require('underscore');
一般而言,知名的第三方庫,都能在 DefinitelyTyped 項目中找到 .d.ts,而WebStorm亦提供了快捷引用方式:
Preferences -> Languages & Frameworks -> Libraries -> Downloads… -> TypeScript community stubs,選你所需 Download & Install:
參考
更多文章請移步我的blog新地址: http://www.moye.me/