TypeScript学习(十五):模块 | 八月更文挑战

252 阅读3分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

import side effect

一些模块会有建立被其他模块使用的全局状态。这些模块没有任何的导出语法,或者使用时不关心模块中的导出内容。此时,可以使用如下语法:

import './index.ts'

import types

import types 可以导入类型,并且可以保证导入的内容在编译后完全被清除 。

通过使用 isolatedModules 选项可以提升编译工具,例如 babel 的编译行为( 太难翻译了。。。)

TS 3.8 release note: import types

re-export

export * from "./xxxx.ts”

export = & import = require()

export = 指定一个从模块中导出的对象。这个对象可以是类,接口,命名空间,函数或者枚举类型。

对于使用export = 导出的对象,必须用 import module = require("module")

module.ts

class Module {}
export = Module

index.ts

import Module = require("./module")

动态加载

直接使用 require("xxx") 即可,最好使用 typeof xxx 来保证导入对象的类型

Ambient Modules

在ts/d.ts文件中使用 declare module “xxx” 语法来定义模块。然后使用 import 语法来“延迟声明”

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 var sep: string;
}

使用 /// 引入声明文件,然后 import 导入需要的模块类型。

这里如果直接导入的话,那么 path 模块也被导入

/// <reference path="node.d.ts"/>
import * as URL from "url";
let myUrl = URL.parse("http://www.typescriptlang.org");

Shorthand ambient modules

书写新模块的时候如果不想立即定义模块内容,可以使用下面的方法

declare module "xxxx";

使用时,可以当做”存在"的模块

declare module "xxxx"

import x, {y} from "xxxx"

通配模块声明  Wildcard module declarations

一些模块加载器可以加载非 JS 文件。可以通过前缀、后缀符来表明这种特殊的加载行为。

declare module "*!text" {
    const content: string;
    export default content;
}

declare module "json!*" {
    const value: any;
    export default value;
}

导入

import fileContent from "./xyz.txt!text";
import data from "json!http://example.com/data.json";
console.log(data, fileContent);

导出内容应该接近顶层

避免过深的嵌套,比如导出命名空间,类的静态方法。

如果仅导出一个方法、变量,那么直接使用 export default。

如果要导出多个对象。那么使他们并列 top level。

export calss testC {}
export function testF {}

Re-export to extend

有时候会碰到 extend 一个模块的情况。这时候,可以在一个新的 module 中 extend 引入的类,然后再导出。以保证消费者的无感知。

cal.ts

export class cal {}

extend.ts

import { cal } from "./cal.ts"
class calEx extends cal {}

export { calEx as cal }

consume.ts

import { cal } from "extend.ts"

const c = new cal()

在模块中勿使用命名空间

命名空间是为了解决全局声明中变量名称冲突的问题。在模块中,不会存在两个对象有用同一个名称的情况。

red flag 危险信号

1. 文件中只有一个顶级声明:export namespace Foo { ... }。不要使用命名空间,把命名空间的内容全部移到顶层。

2. 多文件有一个相同的 export namespace Foo{...}。这些namespace是不会合并的