TypeScript學習筆記(八) - 聲明文件


本篇將介紹TypeScript的聲明文件,並簡單演示一下如何編寫和使用聲明文件。本篇也是這個系列的最后一篇。

一、聲明文件簡介

TypeScript作為JavaScript的超集,在開發過程中不可避免要引用其他第三方的JavaScript的庫。雖然通過直接引用可以調用庫的類和方法,但是卻無法使用TypeScript諸如類型檢查等特性功能。為了解決這個問題,需要將這些庫里的函數和方法體去掉后只保留導出類型聲明,而產生了一個描述JavaScript庫和模塊信息的聲明文件。通過引用這個聲明文件,就可以借用TypeScript的各種特性來使用庫文件了。

 

二、常見庫的結構

有以下幾種:全局庫、CommonJS、AMD、UMD

全局庫:

早期版本的jQuery就是使用了全局庫的使用方式:

1 (function( window, undefined ) {
2     var jQuery = function( selector, context ) {
3         return new jQuery.fn.init( selector, context, rootjQuery );
4     }
5 
6     // ......
7     
8     window.jQuery = window.$ = jQuery;
9 })(window);

通常會看到:

    • 頂級的聲明是 var 或者 function 
    • 有 window 或者 document 這些DOM對象存在
    • 對象一般會賦值到 window 上

CommonJS

NodeJs模塊化采用的規范,聲明和使用方式如下:

1 // 模塊定義文件
2 exports.module_name = {};
3 
4 // 模塊調用文件
5 var module = require('模塊定義文件名');

通常會看到:

    • 賦值給 exports 或者 module.exports 
    • 無條件調用 require 

AMD

前端框架普遍采用的模塊化的規范,聲明和使用方式如下:

1 // 定義模塊
2 define('模塊名', ['jquery', ...], function($){
3     // ......
4 });
5 
6 // 調用模塊
7 require(['模塊名'], function(module) {
8     // ......
9 });

通常會看到:

    • 無條件調用 define 或者 require 

UMD

為了能同時支持上述所有風格的庫聲明方式,就有了通用模塊規范(UMD)。一般會有下面這種聲明方式:

 1 // moment.js
 2 (function (global, factory) {
 3     typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
 4     typeof define === 'function' && define.amd ? define(factory) :
 5     global.moment = factory()
 6 }(this, function() {
 7     function hooks() {
 8         // ......
 9     }
10 
11     // ......
12     return hooks;
13 }));

通常會看到:

    • 在文件頂端會有一大串 typeof XXX 的判斷
    • 同時有 exports 、 define 這種關鍵詞

通過識別庫的結構,采用不用的聲明方式來編寫聲明文件。

 

三、如何編寫聲明文件

linq.js實現了在JavaScript里使用Linq語法,在C#有的Linq方法,在它里面幾乎都有。下面將在nodejs環境里演示如何編寫和使用linq.js的一個簡單的聲明文件。

1. 創建一個nodejs工程,並通過 npm install linq --save 下載插件包。工程結構如下所示:

 

 1 {
 2   "name": "tstest",
 3   "version": "1.0.0",
 4   "description": "",
 5   "main": "index.js",
 6   "scripts": {
 7     "test": "echo \"Error: no test specified\" && exit 1",
 8     "start": "node dist\\main.js"
 9   },
10   "author": "",
11   "license": "ISC",
12   "dependencies": {
13     "linq": "^3.0.5"
14   }
15 }
package.json
 1 {
 2     "compilerOptions": {
 3         "target": "es5",
 4         "noImplicitAny": false,
 5         "module": "commonjs",
 6         "removeComments": true,
 7         "sourceMap": false,
 8         "outDir": "dist"
 9     }
10 }
tsconfig.json

2. 在src目錄下新建文件linq.d.ts

 1 interface IEnumerator {
 2     current: () => any;
 3     moveNext: () => void;
 4     dispose: () => void;
 5 }
 6 
 7 interface Enumerable {
 8     getEnumerator: () => IEnumerator;
 9     from: (obj: any) => Enumerable;
10     where: (predicate: string | ((x: any) => boolean)) => Enumerable;
11     toArray: () => Array<any>;
12 }
13 
14 declare let linq: Enumerable;
15 
16 declare module 'linq' {
17     export = linq;
18 }

3. 還是在src目錄下新建文件main.ts

1 /// <reference path="linq.d.ts" />
2 
3 import * as Enumerable from 'linq';
4 
5 let result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
6 console.log(`result1 is ${result1}`);
7 
8 let result2 = Enumerable.from([1, 2, 3]).where(x => { return x > 2; }).toArray();
9 console.log(`result2 is ${result2}`);

4. 按下快捷鍵 Ctrl+Shift+B 編譯main.ts文件到dist目錄,生成main.js文件

1 "use strict";
2 var Enumerable = require('linq');
3 var result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
4 console.log("result1 is " + result1);
5 var result2 = Enumerable.from([1, 2, 3]).where(function (x) { return x > 2; }).toArray();
6 console.log("result2 is " + result2);

在控制台執行命令 npm run start ,查看輸出結果

從這個例子里可以看出,聲明文件linq.d.ts里只定義了linq的類型和方法名稱,在這里我稱之為“骨架”。在引用了聲明文件后,即可以通過智能感知和強類型檢查等特性使用linq模塊。編譯時會根據配置文件指定的模塊標准( "module": "commonjs" )生成對應的文件。因為這個例子的運行環境是nodejs,所以采用commonjs標准。

如果是在前端使用,則要采用AMD標准。下面是采用這個標准后編譯生成的文件:

1 define(["require", "exports", 'linq'], function (require, exports, Enumerable) {
2     "use strict";
3     var result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
4     console.log("result1 is " + result1);
5     var result2 = Enumerable.from([1, 2, 3]).where(function (x) { return x > 2; }).toArray();
6     console.log("result2 is " + result2);
7 });

linq模塊也支持全局庫的引用方式。通過修改linq.d.ts,支持全局庫引用

 1 interface IEnumerator {
 2     current: () => any;
 3     moveNext: () => void;
 4     dispose: () => void;
 5 }
 6 
 7 interface Enumerable {
 8     getEnumerator: () => IEnumerator;
 9     from: (obj: any) => Enumerable;
10     where: (predicate: string | ((x: any) => boolean)) => Enumerable;
11     toArray: () => Array<any>;
12 }
13 
14 declare let linq: Enumerable;
15 
16 // 全局庫引用
17 export as namespace Enumerable;
18 export = linq;

main.ts調用方式也要修改

1 /// <reference path="linq.d.ts" />
2 
3 let result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
4 console.log(`result1 is ${result1}`);
5 
6 let result2 = Enumerable.from([1, 2, 3]).where(x => { return x > 2; }).toArray();
7 console.log(`result2 is ${result2}`);

編譯生成的main.js

1 var result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
2 console.log("result1 is " + result1);
3 var result2 = Enumerable.from([1, 2, 3]).where(function (x) { return x > 2; }).toArray();
4 console.log("result2 is " + result2);

 

四、聲明文件下載

TypeScript2.0支持通過npm下載常用的模塊的聲明文件,下面借用async模塊簡單演示一下如何引用和使用常用模塊的聲明文件。

1. 通過 npm install async --save 下載async模塊

2. 使用 npm install @types/async --save-dev 下載async模塊的聲明文件。下載完成后會在工程的node_modules文件夾下生成存放聲明文件的文件夾

3. main.ts引用聲明文件

 1 /// <reference types="async" />
 2 import * as async from 'async';
 3 
 4 // 並行執行方法
 5 async.parallel([
 6     cb => { cb(null, 1); },
 7     cb => { cb(null, 2); },
 8     cb => { cb(null, 3); },
 9 ], (err, results) => {
10     console.log(`results is ${results}`);
11 });

這里的引用方式和上面的例子略有不同。上面的例子是用ref注釋將文件名引用進來,通過npm下載的聲明文件則是引用類型名稱( /// <reference types="async" /> )

4. 編譯之后生成main.js,控制台執行查看結果

1 "use strict";
2 var async = require('async');
3 async.parallel([
4     function (cb) { cb(null, 1); },
5     function (cb) { cb(null, 2); },
6     function (cb) { cb(null, 3); },
7 ], function (err, results) {
8     console.log("results is " + results);
9 });
main.js

更多聲明文件可以去 http://microsoft.github.io/TypeSearch/ 查找。也許有些模塊現在暫時沒有聲明文件,我們也可以自己編寫聲明文件后上傳到 https://github.com/DefinitelyTyped/DefinitelyTyped,一起共建TypeScript的聲明文件倉庫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM