Typescript学习之模块和命名空间总结

Typescript学习之模块和命名空间总结

官网介绍

关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变化。
“内部模块”现在称做“命名空间”。 “外部模块”现在则简称为“模块”,
这是为了与 ECMAScript 2015里的术语保持一致,
(也就是说 module X { 相当于现在推荐的写法 namespace X {)

模块

从ECMAScript 2015开始,JavaScript引入了模块的概念。TypeScript也沿用这个概念。
模块在其自身的作用域里执行,而不是在全局作用域里;
这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,
除非你明确地使用export形式之一导出它们。 
相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,
你必须要导入它们,可以使用 import形式之一。
模块是自声明的;两个模块之间的关系是通过在文件级别上使用imports和exports建立的。
模块使用模块加载器去导入其它的模块。
在运行时,模块加载器的作用是在执行此模块代码前去查找并执行这个模块的所有依赖。
大家最熟知的JavaScript模块加载器是服务于Node.js的 CommonJS和服务于Web应用的Require.js。
TypeScript与ECMAScript 2015一样,任何包含顶级import或者export的文件都被当成一个模块。
相反地,如果一个文件不带有顶级的import或者export声明,
那么它的内容被视为全局可见的(因此对模块也是可见的)。

导出

  // 定义一个请求接口,并导出
export interface paramsData {
  name : string,
  list : {
    time :Date,
    suppilerName :string,
    count :number,
    flag:boolean
  }[]
 }

导出语句

  // 导出一个接口
 export type {paramsData as params}
 // 导出一个函数
 export {getData as handleGetData}
 // 导出一个类
 export {Drag as MyDrag}
 // 导出一个枚举类型
 export {List as enumList}
 // 导出所有
 export * 

导入

import { params } from 文件路径
import { handleGetData } from 文件路径
import { MyDrag } from 文件路径
import { enumList } from 文件路径
let date = new Date()
let params: params = {
  name: 'AAA',
  list: [
    {
      time: date,
      suppilerName: 'xxx有限公司',
      count: 2,
      flag: false,
    },
  ],
}
console.log('params:', params)
console.log(handleGetData(222))
let drag = new MyDrag()
console.log('drag:', drag)
let list: enumList = enumList.approve
console.log('list:', list)
//导入所有,并用modules 变量接收
import * as modules from 文件路径
// 默认导出
export default 模块
笔记
CommonJS(node.js)和AMD(Require.js)的环境里都有一个exports变量,
这个变量包含了一个模块的所有导出内容。
CommonJS和AMD的exports都可以被赋值为一个对象, 
这种情况下其作用就类似于 es6 语法里的默认导出,即 export default语法了。虽然作用相似,
但是 export default 语法并不能兼容CommonJS和AMD的exports。
为了支持CommonJS和AMD的exports, TypeScript提供了export =语法。
export =语法定义一个模块的导出对象。 
这里的对象一词指的是类,接口,命名空间,函数或枚举。
若使用export =导出一个模块,
则必须使用TypeScript的特定语法import module = require("module")来导入此模块。
模块里不要使用命名空间
当初次进入基于模块的开发模式时,可能总会控制不住要将导出包裹在一个命名空间里。
模块具有其自己的作用域,并且只有导出的声明才会在模块外部可见。 
记住这点,命名空间在使用模块时几乎没什么价值。
在组织方面,命名空间对于在全局作用域内对逻辑上相关的对象和类型进行分组是很便利的。
例如,在C#里,你会从 System.Collections里找到所有集合的类型。 
通过将类型有层次地组织在命名空间里,可以方便用户找到与使用那些类型。 
然而,模块本身已经存在于文件系统之中,这是必须的。
我们必须通过路径和文件名找到它们,这已经提供了一种逻辑上的组织形式。 
我们可以创建 /collections/generic/文件夹,把相应模块放在这里面。
命名空间对解决全局作用域里命名冲突来说是很重要的。 
比如,你可以有一个 My.Application.Customer.AddForm
和My.Application.Order.AddForm -- 两个类型的名字相同,
但命名空间不同。 然而,这对于模块来说却不是一个问题。 
在一个模块里,没有理由两个对象拥有同一个名字。 
从模块的使用角度来说,使用者会挑出他们用来引用模块的名字,所以也没有理由发生重名的情况。

命名空间

我们先来写一段程序并将在整篇文章中都使用这个例子。 我们定义几个简单的字符串验证器,假设你会使用它们来验证表单里的用户输入或验证外部数据。

interface StringValidator {
    isAcceptable(s: string): boolean;
}

let lettersRegexp = /^[A-Za-z]+$/;
let numberRegexp = /^[0-9]+$/;

class LettersOnlyValidator implements StringValidator {
    isAcceptable(s: string) {
        return lettersRegexp.test(s);
    }
}

class ZipCodeValidator implements StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }
}

// Some samples to try
let strings = ["Hello", "98052", "101"];

// Validators to use
let validators: { [s: string]: StringValidator; } = {};
validators["ZIP code"] = new ZipCodeValidator();
validators["Letters only"] = new LettersOnlyValidator();

// Show whether each string passed each validator
for (let s of strings) {
    for (let name in validators) {
        let isMatch = validators[name].isAcceptable(s);
        console.log(`'${ s }' ${ isMatch ? "matches" : "does not match" } '${ name }'.`);
    }
}

使用命名空间的验证器

namespace Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }

    const lettersRegexp = /^[A-Za-z]+$/;
    const numberRegexp = /^[0-9]+$/;

    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }

    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}

// Some samples to try
let strings = ["Hello", "98052", "101"];

// Validators to use
let validators: { [s: string]: Validation.StringValidator; } = {};
validators["ZIP code"] = new Validation.ZipCodeValidator();
validators["Letters only"] = new Validation.LettersOnlyValidator();

// Show whether each string passed each validator
for (let s of strings) {
    for (let name in validators) {
        console.log(`"${ s }" - ${ validators[name].isAcceptable(s) ? "matches" : "does not match" } ${ name }`);
    }
}

分离文件

不同文件之间存在依赖关系,所以我们加入了引用标签来告诉编译器文件之间的关联
Validation.ts
namespace Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }
}
LettersOnlyValidator.ts
/// <reference path="Validation.ts" />
namespace Validation {
    const lettersRegexp = /^[A-Za-z]+$/;
    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }
}
ZipCodeValidator.ts
/// <reference path="Validation.ts" />
namespace Validation {
    const numberRegexp = /^[0-9]+$/;
    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
}

结尾

以上就是本文的主要学习内容,有不正确的地方欢迎指正,谢谢!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值