命名空间

Ts1.5里术语名已经发生了变化。
“内部模块”现在称做“命名空间”。
“外部模块”现在则简称为“模块”。
这是为了与 ECMAScript 2015里的术语保持一致。

基础知识

默认情况下,我们代码或所定义的验证器(类型等)都在全局命名空间下,这就会导致出现重名现象,而命名空间一个最明确的目的就是解决重名问题。

随着更多验证器的加入,我们需要一种手段来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。
因此,我们把验证器包裹到一个命名空间内,而不是把它们放在全局命名空间下。

命名空间定义了标识符的可见范围,一个标识符可在多个名字空间中定义,它在不同名字空间中的含义是互不相干的。
这样,在一个新的名字空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他名字空间中。

// 定义命名空间
namespace TeacherAPI {
    // 命名空间内部元素 必须通过export向外暴漏
    export const name = "教师API";
    export interface GetList {
        (schoolId: string): Array<any>;
    }
}

// 使用命名空间
const getTeachers: TeacherAPI.GetList = (schoolId)=>{
    return []
}
console.log(TeacherAPI.name);

别名

通过命名空间来使用标识,可能会比较长。这个时候我们可以用使用ts提供的别名来进行简化

namespace People {
    export namespace Teacher {
        export class HeadMaster { }
    }
}

import HeadMaster = People.Teacher.HeadMaster; // 别名
const wangMaster = new HeadMaster(); 

分离到多文件

当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护。

type-part1.ts
/// <reference path="type-part2.ts" />

namespace TeacherAPI {
    export const name = "教师API";
    export interface GetList {
        (schoolId: string): Array<any>;
    }
}
type-part2.ts
namespace TeacherAPI {
    export interface GetOne {
        (tid: string): any;
    }
}
index.ts
/// <reference path="type-part1.ts" />

console.log(TeacherAPI.name);
const getTeachers: TeacherAPI.GetList = (schoolId)=>{
    return []
}
const getTeacher: TeacherAPI.GetOne = (schoolId)=>{
    return {}
}

结合类型声明文件

在上一章的模块中,我们学到了类型定义文件。 其中已经有相关的例子了
D3.d.ts 部分摘录

D3.d.ts
declare namespace D3 {
    export interface Selectors {
        select: {
            (selector: string): Selection;
            (element: EventTarget): Selection;
        };
    }

    export interface Event {
        x: number;
        y: number;
    }

    export interface Base extends Selectors {
        event: Event;
    }
}

declare var d3: D3.Base;