【译】TypeScript 类型声明文件(.d.ts)编写之库结构(Library Structures)

【译】TypeScript 类型声明文件(.d.ts)编写之库结构(Library Structures)_第1张图片
【译】TypeScript 类型声明文件(.d.ts)编写之库结构(Library Structures)_第2张图片

一、概述(Overview)

总体上说,声明文件的结构,取决于所使用库的类型。JavaScript 中,可以有有很多种提供形式(结构),写声明文件的时候,需要与库的提供形式匹配。本文主旨在于如何识别库的提供形式,以及为对应形式编写声明文件的方法。
  本身中后续提及提供形式、库结构、库类型指的是一回事,基本上可以认为是库的模块化形式以及使用方式,如:全局、模块等。

二、识别库类型(Identifying Kinds of Libraries)

首先,看下一 TypeScript 提供的库声明文件类型,简单展示一下每种类型如何使用、如何编写,以及从实际场景中,列举出一些样例。
  为库编写声明文件的第一步,是识别库的结构。我们给出的识别库结构的方法,都是取决于使用方式和库的代码。这两种方法中,使用方式要看库文档中的说明,而代码就看其中具体的代码组织形式了。推荐使用自己觉得舒适的方式。

1、全局库(Global Libraries)

全局库指的是可以在全局作用域使用的库,比如:不需要任何形式的 import。很多库简单暴露出几个全局变量使用。比如:jQuery 中的 $ 变量。

$(() => { console.log('hello!'); } );

经常会看到这种全局库的文档中,给出的如何在 HTML 标签中的使用方法:


如今大多数提供“全局操作形式”的库,实际上都使用的是 UMD 形式。全局库UMD 通过文档还是难以区分的,在为全局库编写声明文件之前,先确保其不是 UMD 的。

(1)通过代码识别全局库

全局库代码使用非常简单,一个 “Hello, world” 的全局库,看起来是这样的:

function createGreeting(s) {
    return "Hello, " + s;
}

或者这样:

window.createGreeting = function(s) {
    return "Hello, " + s;
}

观察全局库代码,通常可以看到:

  • 顶层的 var 声明,或者 function 声明
  • 一个或多个给 window 下属性的赋值,如:window.someName
  • 假设 windowdocument 这样的 DOM 基本类型存在

不会看到:

  • 模块加载器侦测使用,如:requiredefine
  • CommonJS/Node.js 风格的引入形式,如:var fs = require("fs");
  • 调用 define(...)
  • 文档描述怎样 requireimpot
(2)全局库样例

由于将全局库转换为 UMD 非常容易,所以流行库很少再以全局库的形式提供。但是一些小型库并且需要 DOM 操作的,或者不需要其他依赖的库,可能仍然以“全局”形式提供。

(3)全局库模板

global.d.ts 模板定义了一个 myLib 库。请确保阅读 避免命名冲突 的说明。

2、模块库(Modular Libraries)

一些库只在具备模块加载器的环境下才能使用。例如:由于 express 库只在 Node.js 环境下工作,并且使用 CommonJS 的 require 功能。
  
  ECMAScript 2015(也称为 ES2015、ECMAScript 6 和 ES6)、CommonJS 和 RequireJS 对于引入模块具备相似的概念。
  以下列举一些书写方式:

  • CommonJS(Node.js)
var fs = require("fs");
  • TypeScript、ES6 中,import 关键字提供相同的功能
import fs = require("fs");

模块库的文档中,可以看到一些代表性的字样,如:

var someLib = require('someLib');

define(..., ['someLib'], function(someLib) {

});

对于 UMD 库中,虽然也是提供全局功能,但是一样会在其中看到上述的样例,所以要确保查看代码或文档

(1)通过代码识别模块库

模块库至少具备以下特点中的一些:

  • 非条件地调用 requiredefine,这一点区别于 UMD
  • 类似 import * as a from 'b';export c; 这样的声明
  • exportsmodule.exports 赋值

很少具备:

  • 对于 windowglobal 的属性的赋值
(2)模块库样例

很多流行的 Node.js 库是模块库,如:expressgulprequest

3、UMD

UMD 模块,既可以作为模块使用(通过引入),也可以全局(在没有模块加载器的环境)使用。很多流行库,如:Moment.js,就是以 UMD 的形式编写的。
  在 Node.js 或者 RequireJS 中,可以这样写:

import moment = require("moment");
console.log(moment.format());

而在普通浏览器中,可以这样写:

console.log(moment.format());
(1)识别 UMD

UMD 模块检查模块加载器环境是否存在。

(function (root, factory) {
    if (typeof define === "function" && define.amd) {
        define(["libName"], factory);
    } else if (typeof module === "object" && module.exports) {
        module.exports = factory(require("libName"));
    } else {
        root.returnExports = factory(root.libName);
    }
}(this, function (b) {

如果在库的代码中看到 typeof definetypeof windowtypeof module 的测试,尤其是在文件顶部,基本上就是 UMD 库了。
  UMD 库的文档也经常会演示 “Using in Node.js” 样例,展示如何使用 require,以及 “Using in the browser” 样例展示如何使用

你可能感兴趣的:(【译】TypeScript 类型声明文件(.d.ts)编写之库结构(Library Structures))