天天看点

TypeScript 的命名空间 namespace

官方链接

关于术语的说明:需要注意的是,在 TypeScript 1.5 中,术语发生了变化。 “内部模块”现在是“命名空间”。 “外部模块”现在只是“模块”,与 ECMAScript 2015 的术语保持一致。

从哪里开始?

让我们从我们将在本页中用作示例的程序开始。 我们编写了一小组简单的字符串验证器,您可能会编写这些代码来检查用户在网页表单上的输入或检查外部提供的数据文件的格式。

Validators in a single file

测试代码:

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}'.`);
  }
}
           

引入命名空间的概念

随着我们添加更多验证器,我们将需要某种组织方案,以便我们可以跟踪我们的类型,而不必担心与其他对象的名称冲突。 与其将许多不同的名称放入全局命名空间,不如将我们的对象包装到一个命名空间中。

在这个例子中,我们将所有与验证器相关的实体移动到一个名为 Validation 的命名空间中。 因为我们希望这里的接口和类在命名空间之外是可见的,所以我们以 export 开头。 相反,变量 letterRegexp 和 numberRegexp 是实现细节,因此它们不会被导出,并且对于命名空间之外的代码是不可见的。 在文件底部的测试代码中,我们现在需要限定在命名空间之外使用时的类型名称,例如 Validation.LettersOnlyValidator。

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);
    }
  }
}
           

继续阅读