TypeScript学习笔记(八) - 声明文件
本篇将介绍TypeScript的声明文件,并简单演示一下如何编写和使用声明文件。本篇也是这个系列的最后一篇。
一、声明文件简介
TypeScript作为JavaScript的超集,在开发过程中不可避免要引用其他第三方的JavaScript的库。虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript诸如类型检查等特性功能。为了解决这个问题,需要将这些库里的函数和方法体去掉后只保留导出类型声明,而产生了一个描述JavaScript库和模块信息的声明文件。通过引用这个声明文件,就可以借用TypeScript的各种特性来使用库文件了。
二、常见库的结构
有以下几种:全局库、CommonJS、AMD、UMD
全局库:
早期版本的jQuery就是使用了全局库的使用方式:
(function( window, undefined ) {
var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
} // ...... window.jQuery = window.$ = jQuery;
})(window);
通常会看到:
- 顶级的声明是 var 或者 function
- 有 window 或者 document 这些DOM对象存在
- 对象一般会赋值到 window 上
CommonJS
NodeJs模块化采用的规范,声明和使用方式如下:
// 模块定义文件
exports.module_name = {}; // 模块调用文件
var module = require('模块定义文件名');
通常会看到:
- 赋值给 exports 或者 module.exports
- 无条件调用 require
AMD
前端框架普遍采用的模块化的规范,声明和使用方式如下:
// 定义模块
define('模块名', ['jquery', ...], function($){
// ......
}); // 调用模块
require(['模块名'], function(module) {
// ......
});
通常会看到:
- 无条件调用 define 或者 require
UMD
为了能同时支持上述所有风格的库声明方式,就有了通用模块规范(UMD)。一般会有下面这种声明方式:
// moment.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
global.moment = factory()
}(this, function() {
function hooks() {
// ......
} // ......
return hooks;
}));
通常会看到:
- 在文件顶端会有一大串 typeof XXX 的判断
- 同时有 exports 、 define 这种关键词
通过识别库的结构,采用不用的声明方式来编写声明文件。
三、如何编写声明文件
linq.js实现了在JavaScript里使用Linq语法,在C#有的Linq方法,在它里面几乎都有。下面将在nodejs环境里演示如何编写和使用linq.js的一个简单的声明文件。
1. 创建一个nodejs工程,并通过 npm install linq --save 下载插件包。工程结构如下所示:
{
"name": "tstest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node dist\\main.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"linq": "^3.0.5"
}
}
package.json
{
"compilerOptions": {
"target": "es5",
"noImplicitAny": false,
"module": "commonjs",
"removeComments": true,
"sourceMap": false,
"outDir": "dist"
}
}
tsconfig.json
2. 在src目录下新建文件linq.d.ts
interface IEnumerator {
current: () => any;
moveNext: () => void;
dispose: () => void;
} interface Enumerable {
getEnumerator: () => IEnumerator;
from: (obj: any) => Enumerable;
where: (predicate: string | ((x: any) => boolean)) => Enumerable;
toArray: () => Array<any>;
} declare let linq: Enumerable; declare module 'linq' {
export = linq;
}
3. 还是在src目录下新建文件main.ts
/// <reference path="linq.d.ts" /> import * as Enumerable from 'linq'; let result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
console.log(`result1 is ${result1}`); let result2 = Enumerable.from([1, 2, 3]).where(x => { return x > 2; }).toArray();
console.log(`result2 is ${result2}`);
4. 按下快捷键 Ctrl+Shift+B 编译main.ts文件到dist目录,生成main.js文件
"use strict";
var Enumerable = require('linq');
var result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
console.log("result1 is " + result1);
var result2 = Enumerable.from([1, 2, 3]).where(function (x) { return x > 2; }).toArray();
console.log("result2 is " + result2);
在控制台执行命令 npm run start ,查看输出结果
从这个例子里可以看出,声明文件linq.d.ts里只定义了linq的类型和方法名称,在这里我称之为“骨架”。在引用了声明文件后,即可以通过智能感知和强类型检查等特性使用linq模块。编译时会根据配置文件指定的模块标准( "module": "commonjs" )生成对应的文件。因为这个例子的运行环境是nodejs,所以采用commonjs标准。
如果是在前端使用,则要采用AMD标准。下面是采用这个标准后编译生成的文件:
define(["require", "exports", 'linq'], function (require, exports, Enumerable) {
"use strict";
var result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
console.log("result1 is " + result1);
var result2 = Enumerable.from([1, 2, 3]).where(function (x) { return x > 2; }).toArray();
console.log("result2 is " + result2);
});
linq模块也支持全局库的引用方式。通过修改linq.d.ts,支持全局库引用
interface IEnumerator {
current: () => any;
moveNext: () => void;
dispose: () => void;
} interface Enumerable {
getEnumerator: () => IEnumerator;
from: (obj: any) => Enumerable;
where: (predicate: string | ((x: any) => boolean)) => Enumerable;
toArray: () => Array<any>;
} declare let linq: Enumerable; // 全局库引用
export as namespace Enumerable;
export = linq;
main.ts调用方式也要修改
/// <reference path="linq.d.ts" /> let result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
console.log(`result1 is ${result1}`); let result2 = Enumerable.from([1, 2, 3]).where(x => { return x > 2; }).toArray();
console.log(`result2 is ${result2}`);
编译生成的main.js
var result1 = Enumerable.from([1, 2, 3]).where('$>1').toArray();
console.log("result1 is " + result1);
var result2 = Enumerable.from([1, 2, 3]).where(function (x) { return x > 2; }).toArray();
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引用声明文件
/// <reference types="async" />
import * as async from 'async'; // 并行执行方法
async.parallel([
cb => { cb(null, 1); },
cb => { cb(null, 2); },
cb => { cb(null, 3); },
], (err, results) => {
console.log(`results is ${results}`);
});
这里的引用方式和上面的例子略有不同。上面的例子是用ref注释将文件名引用进来,通过npm下载的声明文件则是引用类型名称( /// <reference types="async" /> )
4. 编译之后生成main.js,控制台执行查看结果
"use strict";
var async = require('async');
async.parallel([
function (cb) { cb(null, 1); },
function (cb) { cb(null, 2); },
function (cb) { cb(null, 3); },
], function (err, results) {
console.log("results is " + results);
});
main.js
更多声明文件可以去 http://microsoft.github.io/TypeSearch/ 查找。也许有些模块现在暂时没有声明文件,我们也可以自己编写声明文件后上传到 https://github.com/DefinitelyTyped/DefinitelyTyped,一起共建TypeScript的声明文件仓库。
TypeScript学习笔记(八) - 声明文件的更多相关文章
- Python学习笔记八:文件操作(续),文件编码与解码,函数,递归,函数式编程介绍,高阶函数
文件操作(续) 获得文件句柄位置,f.tell(),从0开始,按字符数计数 f.read(5),读取5个字符 返回文件句柄到某位置,f.seek(0) 文件在编辑过程中改变编码,f.detech() ...
- SpringMVC学习笔记八:文件上传下载(转)
转自:http://www.cnblogs.com/WJ-163/p/6269409.html 一.关键步骤 ①引入核心JAR文件 SpringMVC实现文件上传,需要再添加两个jar包.一个是文件上 ...
- python学习笔记八:文件与目录
一.文件的打开和创建 1.打开 open(file,mode): >>>fo = open('test.txt', 'r') >>>fo.read() 'hello ...
- TypeScript学习笔记(八):1.5版本之后的模块和命名空间
我之前有写过TS1.5版本之前的“模块”的笔记:TypeScript学习笔记(七):模块 但是TS这里的模块和在ECMAScript 2015里的模块(即JS原生支持了模块的概念)概率出现了混淆,所以 ...
- go微服务框架kratos学习笔记八 (kratos的依赖注入)
目录 go微服务框架kratos学习笔记八(kratos的依赖注入) 什么是依赖注入 google wire kratos中的wire Providers injector(注入器) Binding ...
- Windows phone 8 学习笔记(2) 数据文件操作
原文:Windows phone 8 学习笔记(2) 数据文件操作 Windows phone 8 应用用于数据文件存储访问的位置仅仅限于安装文件夹.本地文件夹(独立存储空间).媒体库和SD卡四个地方 ...
- Typescript 学习笔记二:数据类型
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记三:函数
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记一:介绍、安装、编译
前言 整理了一下 Typescript 的学习笔记,方便后期遗忘某个知识点的时候,快速回忆. 为了避免凌乱,用 gitbook 结合 marketdown 整理的. github地址是:ts-gitb ...
- python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...
随机推荐
- Bootstrap fileinput v1.0(ssm版)
前言bootstrap fileinput是一个很好的文件上传插件.但是官方不出api,这就尴尬了.百度一下,每个人写法都不相同,好多代码本身都是错的.我修改后才能跑起来.综上所述:所以今天我摸索了一 ...
- 2016-2017 ACM-ICPC CHINA-Final Solution
Problem A. Number Theory Problem Solved. 水. #include<bits/stdc++.h> using namespace std; ; typ ...
- poj3421 X-factor Chains(重复元素的全排列)
poj3421 X-factor Chains 题意:给定正整数$x(x<=2^{20})$,求$x$的因子组成的满足任意前一项都能整除后一项的序列的最大长度,以及满足最大长度的子序列的个数. ...
- php+mysql事务处理例子详细分析实例
一.数据引擎innodb用begin,rollback,commit来实现提交事务处理,begin开始事务后出现错误就rollback事务回滚或者没有错误就commit提事务提交确认完成. start ...
- 20145315 《Java程序设计》第五周学习总结
20145315 <Java程序设计>第五周学习总结 教材学习内容总结 第八章 8.1语法与继承架构 8.1.1使用try,catch 所有的错误都会被打包为对象,使用try,catch可 ...
- JS实现弹出层效果
很多时候我们想去某某网站干点什么的时候,就会让我们先注册登录后才可以访问内容,而现在很多网站注册登录的时候都会有一种遮罩层的效果,就是背景是带有透明度的黑色遮罩,盖满整个网站,然后登录框弹出固定在屏幕 ...
- CentOS日常维护及常用脚本
[root@-.x.x xiewenming]# curl myip.ipip.net 当前 IP:42.62.x.x 来自于:中国 北京 北京 联通/电信 www.17ce.com cdn解析网站 ...
- ZOJ 2587 Unique Attack(最小割唯一性判断)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2587 题意:判断最小割是否唯一. 思路: 最小割唯一性的判断是先跑一遍最大 ...
- mysql之innodb的锁分类介绍
一.innodb行锁分类 record lock:记录锁,也就是仅仅锁着单独的一行 gap lock:区间锁,仅仅锁住一个区间(注意这里的区间都是开区间,也就是不包括边界值. next-key loc ...
- Android之shape与selector实现圆角
shape和selector是Android UI设计中经常用到的,比如我们要自定义一个圆角Button,点击Button有些效果的变化,就要用到shape和selector.可以这样说,shape和 ...