# 模块声明
# export = 和 import = require()
CommonJS和AMD的环境里都有一个exports变量,这个变量包含了一个模块的所有导出内容。
CommonJS和AMD的exports都可以被赋值为一个对象, 这种情况下其作用就类似于 es6 语法里的默认导出,即 export default语法了。虽然作用相似,但是 export default 语法并不能兼容CommonJS和AMD的exports。
为了支持CommonJS和AMD的exports, TypeScript提供了export =语法。
export =语法定义一个模块的导出对象。 这里的对象一词指的是类,接口,命名空间,函数或枚举。
若使用export =导出一个模块,则必须使用TypeScript的特定语法import module = require("module")来导入此模块。
ZipCodeValidator.ts
let numberRegexp = /^[0-9]+$/;
class ZipCodeValidator {
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
export = ZipCodeValidator;
2
3
4
5
6
7
8
9
10
11
Test.ts
import zip = require("./ZipCodeValidator");
// Some samples to try
let strings = ["Hello", "98052", "101"];
// Validators to use
let validator = new zip();
// Show whether each string passed each validator
strings.forEach(s => {
console.log(`"${ s }" - ${ validator.isAcceptable(s) ? "matches" : "does not match" }`);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 外部模块
在Node.js里大部分工作是通过加载一个或多个模块实现的。 我们可以使用顶级的 export声明来为每个模块都定义一个.d.ts文件,但最好还是写在一个大的.d.ts文件里。 我们使用与构造一个外部命名空间相似的方法,但是这里使用 module关键字并且把名字用引号括起来,方便之后import。 例如:
node.d.ts (simplified excerpt)
declare module "url" {
export interface Url {
protocol?: string;
hostname?: string;
pathname?: string;
}
export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
}
declare module "path" {
export function normalize(p: string): string;
export function join(...paths: any[]): string;
export let sep: string;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
现在我们可以/// <reference>
node.d.ts并且使用import url = require("url");或import * as URL from "url"加载模块。
/// <reference path="node.d.ts"/>
import * as URL from "url";
let myUrl = URL.parse("http://www.typescriptlang.org");
2
3
# 外部模块简写
假如你不想在使用一个新模块之前花时间去编写声明,你可以采用声明的简写形式以便能够快速使用它。
declarations.d.ts
declare module "hot-new-module";
2
3
简写模块里所有导出的类型将是any。
import x, {y} from "hot-new-module";
x(y);
2
3
4
# 模块声明通配符
某些模块加载器如SystemJS 和 AMD支持导入非JavaScript内容。 它们通常会使用一个前缀或后缀来表示特殊的加载语法。 模块声明通配符可以用来表示这些情况。
declare module "*!text" {
const content: string;
export default content;
}
// Some do it the other way around.
declare module "json!*" {
const value: any;
export default value;
}
2
3
4
5
6
7
8
9
现在你可以就导入匹配"!text"或"json!"的内容了。
import fileContent from "./xyz.txt!text";
import data from "json!http://example.com/data.json";
console.log(data, fileContent);
2
3
# UMD模块
有些模块被设计成兼容多个模块加载器,或者不使用模块加载器(全局变量)。 它们以 UMD模块为代表。 这些库可以通过导入的形式或全局变量的形式访问。
math-lib.d.ts
export function isPrime(x: number): boolean;
export as namespace mathLib;// 注意这句的含义
2
3
4
5
6
之后,这个库可以在某个模块里通过导入来使用:
import { isPrime } from "math-lib";
isPrime(2);
mathLib.isPrime(2); // 错误: 不能在模块内使用全局定义。
理解下这句 错误: 不能在模块内使用全局定义。。。
因为该文件有 import,所以它是模块,模块内不能用全局变量
2
3
4
5
6
7
它同样可以通过全局变量的形式使用,但只能在某个脚本(指不带有模块导入import或导出 export的脚本文件)里。
mathLib.isPrime(2);
2
# 文件声明
# 模块类的库
模块化库通常至少具有以下一些内容:
- 无条件调用require或define
- import * as a from 'b';类似or 的声明export c;
- 分配给exports或module.exports
模块库的模版共有4个
- 如果您的模块可以像函数一样调用,则使用模板module-function.d.ts (opens new window)
const x = require("foo");
// Note: calling 'x' as a function
const y = x(42);
2
3
- 如果您的模块可以使用new的方式构建,则使用module-class.d.ts (opens new window)
const x = require("bar");
// Note: using 'new' operator on the imported variable
const y = new x("hello");
2
3
- 如果您有一个模块,在导入时使用 template 对其他模块进行更改 则可以使用 module-plugin.d.ts (opens new window)
import { greeter } from "super-greeter";
// Normal Greeter API
greeter(2);
greeter("Hello world");
// Now we extend the object with a new function at runtime
import "hyper-super-greeter"; // 对原有模块进行了扩展
greeter.hyperGreet();
2
3
4
5
6
7
// js
const maxInterval = 12;
function getArrayLength(arr) {
return arr.length;
}
module.exports = {
getArrayLength,
maxInterval,
};
// 类型文件
export function getArrayLength(arr: any[]): number;
export const maxInterval: 12;
2
3
4
5
6
7
8
9
10
11
12
13
# 全局类型的库 比如jQuery
在html代码里这样引入 <script src="http://a.great.cdn.for/jQuery.js"></script>
再js中这样使用
$(() => {
console.log("hello!");
});
2
3
实现这种库的类型文件可以使用模版Global.d.ts (opens new window)
# UMD类的 库示例
UMD类的库可以使用module-plugin.d.ts模板。
# 使用依赖项
如何将别的库的类型导入到自己的库的类型声明文件中
- 如果自己的库依赖全局库请使用
/// <reference types="..." />
指令
/// <reference types="someLib" />
function getThing(): someLib.thing;
2
3
4
- 如果自己库依赖依赖于别的模块库,请使用以下import
import * as moment from "moment";
function getThing(): moment;
2
- 如果自己的全局库依赖别的 UMD 模块 ,请使用
/// <reference types指令:
/// <reference types="moment" />
function getThing(): moment;
2
3
- 如果自己的的模块或 UMD 库依赖于 UMD 库 ,请使用以下import语句:,不要使用指令
/// <reference来声明对 UMD 库的依赖!
/// <reference types="moment" />
function getThing(): moment;
import * as someLib from "someLib";
2
3
# 知识小记❗️❗️❗️❗️
export default请注意,在 .d.ts 文件中使用需要esModuleInterop: true工作。如果您的项目中没有esModuleInterop: true,例如当您向Definitely Typed 提交 PR 时,则必须使用该export=语法。这种较旧的语法更难使用,但在任何地方都适用。下面是如何使用以下方式编写上面的示例export=:
使用 export default
export default function getArrayLength(arr: any[]): number;
export const maxInterval: 12;
2
使用 export=
declare function getArrayLength(arr: any[]): number;
declare namespace getArrayLength {
declare const maxInterval: 12;
}
export = getArrayLength;
2
3
4
5
# export as namespace 可选的全局使用
您可以使用export as namespace
声明您的模块将在 UMD 上下文中的全局范围内可用:
export as namespace moduleName;
参考如下声明文件示例
如果此模块是一个UMD模块,当在模块加载程序环境外部加载时,它会公开全局变量“myLib”,请在此处声明该全局变量。
否则删除下面声明
export as namespace myLib;
如果这个模块导出一个函数,则像下面这样声明
export function myFunction(a: string): string;
export function myOtherFunction(a: number): number;
您可以声明类型,这个类型可通过导入的方式使用
export interface SomeType {
name: string;
length: number;
extras?: string[];
}
您可以使用let cont var 来声明模块的属性
export const myField: number;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 全局修改模块
全局修改模块在导入时会更改全局范围内的现有值,比如在原型上加新方法String.prototype.xx = x
如果全局修改模块是可调用或可构造的,则需要将此处的模式与模块类或模块函数模板文件中的模式相结合
比如扩展 String的原型上的方法
declare global {
/*~ Here, declare things that go in the global namespace, or augment
*~ existing declarations in the global namespace
*/
interface String {
fancyFormat(opts: StringFormatOptions): string;
}
}
如果你的模块导出了类型或者值,则可以这么写
export interface StringFormatOptions {
fancinessLevel: number;
}
如果你的模块什么也没导出则需要下面这样,如果导出的话,则需要删除他
export {};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22