命名空间

关于术语的说明:需要注意的是,在 TypeScript 1.5 中,命名法发生了变化。"Internal modules" 现在是 "namespaces"。"External modules" 现在只是 "modules",以符合 ECMAScript 2015 的术语,(即 module X { 等同于现在首选的 namespace X {)。

这篇文章概述了在 TypeScript 中使用命名空间(以前是 "internal modules")来组织代码的各种方法。正如我们在关于术语的注释中提到的那样,"internal modules" 现在称为 "namespaces"。此外,在声明内部模块时使用 module 关键字的任何地方,都可以并且应该使用 namespace 关键字。这通过使用类似名称的术语使新用户重载来避免混淆新用户。

第一步

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

单个文件中的验证器

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。相反,变量 lettersRegexpnumberRegexp 是实现细节,因此它们未导出,并且对命名空间外的代码不可见。在文件底部的测试代码中,我们现在需要在命名空间外使用时限定类型的名称,例如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}`
    );
  }
}

跨文件拆分

k06q6Zs3S0AyijcjmK6dWTgsKLAti9zbBsIamAdE6tKuod2aIF9efscxAaxqn+ubPCXXN2TxZIWqU9HW+XNRtFAALHicflT6kpNOIBHKGuCjK9B0GersYIfxm9U2grqk+6dyq8kWg6SJs72U34nfaw==

多文件命名空间

lYHOxkc8HRSRMWeRqCcuMuUMpehf948Mc8cuqc58bCXp6d/dpaC1ECaA37GOksbqWaqDU4WlTNxccaDxd5oubEJ6I+ZDbt/JBqzg7ocddm+6oDqBlrtdddB6ywv52rzME0c26JZjrO5FkQ3iirQCD/KMXfBDJW9+qZfqebFRISXKPYAMc56WZkWLNGSYZEYkyScaSL+2GhhKuoMJ9EFzfnbEqbHqnuuzcrJMpmVFTWurUOJVgrRPhcDM0iucfxeEQA14uIJ65oiV687GplUx6NUUgsiKu6oHyawJNr93+/maxqMPx3ljU72BWWtPv8XQgdaLZNvobf/RE7b3sSAZMI+bVF/i496WF9s45MOjgPfcecyEn7QR2dkfr6c5A7JLeVntztiwXRdNK0TorS79J7fztFNNQ8p4V9UstPTqcUlHSHVZ81t8GSWn7lisGwJQxhSrymFnsfmKfG04yeQDKHNRvxWYy8rhHxpXFEVIzmP1Ils7FABMiOCVa39VptyB

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

Test.ts

/// <reference path="Validation.ts" />
/// <reference path="LettersOnlyValidator.ts" />
/// <reference path="ZipCodeValidator.ts" />

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

SBAWTGrTeDMGADGsmR+npYP6jyxKXFhhnnpMunC+B55QBro1g7GvhDeoBgzxm33AR//ByTfFkAGe/STfXQopR7+dE28CegpyiOcr8bQ6iliNHA/1/1YtLOan/dmHAT8MDwLiVGiCHDZknXFVg7Atex+xbNe0c5uCznfWs3B45YQ=

s3Caok/YFX9a7+ik68l6HS0jUqi3OSiS8OjmDRO0Lgs12LSa27H80XNBeWkxHQHFmKQ7sjKSK6+vw3J4ReQkkl2b4ijRG1DypLmJ8NdiTdkbry3dI8+DUxPk5vATnAXgWQVnNv5dbM8kQdHtuCVcvxJZL2jfk46g6PRgp6HkxTSVBVsbOjyAVFqdKNa/JNc/kKpHvC4uGERe7WSPZ/twEMkKcA2bGUd7whCUtYxKS23crUnDgRlss2eQ4dI8xvHI

tsc --outFile sample.js Test.ts

3JhOe93VVcQ4ZLqa00lTpMbzBNCabyqWKL/0mWY+a083JVtRN/LkPhmztAw+3SmK0U+hEXk+7qG1SSyi+tlyJRBYPU8JNZ9/xT0LT2Le3oeeQsLwfXXsKKocq/eYegHdj3eJbHMO/HkgjLQlQ1BODPhPWj3yaGc6IF/chdr0RwY=

tsc --outFile sample.js Validation.ts LettersOnlyValidator.ts ZipCodeValidator.ts Test.ts

7xjYTyZlrZeo4aE5nrODYxkeKaM3uEahPy31iXMXYwooBjgZ4s7RaxAoumt3g9zocXZgIs/W4KCp3CZHlBe1Pr4mhCssB5dk/UARdGrPfKHGqtH+H3XA6GVybEt4U/bgynRK0A/+7oBFjX/sERo0D9PfDNUgtfhCkbdG+iP9WJ6x2AEw+7adqnSlm0TcNzn2LgzxICHM3CLgHsO/xu3i7l3j+xbA0SvKSVe+ZiHqNnn0xaiE/4VyQPqCKA2efmHud3RUz/l7nsIPdMJDOf2yGB69K/WMLpvevNL8EYRPXe/pfUyQ9tWJ1/x0C0K2gcRRecDMgCZML1hLvxn9ZybkchZz3EGoR9nsJr6h4wcIq/Y=

MyTestPage.html(摘录)

<script src="Validation.js" type="text/javascript" />
<script src="LettersOnlyValidator.js" type="text/javascript" />
<script src="ZipCodeValidator.js" type="text/javascript" />
<script src="Test.js" type="text/javascript" />

别名

femHvpz1+myWDxCv5Yu15N0ORAE5X6iduMoTspPBKfb/fd2ys0bcf4EV4yX2ksULE816fGob6gNjMIF7v60afgBui4YGtdgRqENOAwcTodrQhRsR5euqc/lMV60bE/rmJUBoylRWrhqGvDsqmZM0ktM81tpVTx7TOAItwe2TdjZzXYhi4jzS2cyxdWJxu97wOPQvdtgwpKGUFAt5OOtxvBRFmhaxtJzsXBbk7QU7gSTXMdPcpOd4Td/T3gf2N8a8JPE9mXSns57TlycCc3igsfqV13w8hMC0DT24ZkbMKZReWEEJjkRG1T/nf1d5f3uobJGN88j17rdwm8L2PApBHaNvpAcAeI4nx7YWBlhbrgrBwKcCsURiOALusrYbB6Pzo4mbK9FSBiswoZxovvUnBo9ayNesrBwghsrr+DN+vIStLMHYI1lwmy0D5gJYIVAoGOI5/ekGytm42q/qUfaQL38hJaYec0InEhuLSvbt9OrZTUfZYVGRHkjvE7HZzkV3

namespace Shapes {
  export namespace Polygons {
    export class Triangle {}
    export class Square {}
  }
}

import polygons = Shapes.Polygons;
let sq = new polygons.Square(); // Same as 'new Shapes.Polygons.Square()'

mITc2rr0/KwmmCc4JKZbyoOPSZH5plOYx5ppP/L0C/Lm+vWUuydZauJer42ojkO4eClSwxRsy8wST6yOxeN7pclsES5Ad0GtgzzDQgu9Pa52YV40C7qK7eyaMFmuyundUNYHEERRKihUGOeMHF2jb30+Q70DTMnPXt/5p/w5ICXj0IzgmbL/g6euAPN1zK9fWrY3WswxFJU/4lPK6pW1W8HhvSgBovl7f5Yf+2VNBJwqHhyFublI8FpAikeLi1tNr5aJ+9e349v/XGunhWqWeTPlA2yrAzx892C17ZBmVsI3brX7pipqBCNSIw0+1KU5f9JCdtABomnS+lPOFyW4BgjWRlOVg/0hhb9f27LmWObzvzBr9dRSvzi/8qy4D2gDf9lBpcg9xyuFwalIKLBziPczEfsts+MD4HgdG43/fdiI/leYyBdcqHg0wmH5nJAM+WjESvH3AdN69F/gLbfB+yGRPGFRmWh9Il4111SXCe20VYBcKO4qY25JMVuzDXG9mjNb/Fx0iS6RT79GEWQf2g==

使用其他 JavaScript 库

FZif6vAprDCAbf3H7cQRqHO0uvqhe29K6bh/t9N0gCZ6kx+yLXUBmf/uozCaFrAgZIw7jK/ZbWMvqjuj2L0OQlIiLJ05jO6jl9o0S0Z6Bx0iXMAH+jvF54tCF8/Pm+HP9VIuCGtrS0Y7BuOGoCebFhibs90KT0avvZ0Fdx7tri+Tz0P/WRknNgiPrnCmm7bSdScUoK10N0cR3FSPs6V3ZkrS+V5xYxnRONTYro2HK9QEo9/ZXC1St9ObN6Kez+fk5MOsi928AQpUCWRUhSBhGA==

izJ48QNeJjneF63xcERruzoVip2XqpYh1d9/V6u7B/Uhf62QFP+cKTJ4lrkagpFvrPx4+ZtZCejhSs7oSdbbCXM0jWIewPx0T21+gmQsyxuUiz6V5miQsxLsR0LyePWCCju15Zy56HK6tIZeF0wQTKoNvnBE+yEIqs/YdYqU3P4nJKqS4zBaIpaSNLw6H1RmwBXno0cogpxVT87olq1FvbM/vTgUHyU58eTPxk+cw4yKhQO1XYdODR43+xzAPnUb2Nfjv/8VX0PgTHJKGHRgCQ==

环境命名空间

rqhiebrCgQKTGCtP5B9tcqyD217McgCFTCVg2qK5x6OlyqHZWUvW4MDhopmjCSt/m/RgEn7Uh8I/GhlaphcpAg9+mKeZj0eZqXoyKnSpR8Ux/E5UJ0TQcGXTLLzZugcmvthWcYTG/ASwpnBOi9XAlHrDWFnunkSNeghH+wMmTtpzG4KbquetQWB9yA1JZHmkCTsygaDrVXGNQr8lXn5WyOaIs6OV+uds6qozItiSo0BHFHU4DWwm0dB7W1gBq12aN25C8AwB0pptWIPlnGd9M0SePjTc+fvxqh46glCOaXMniCSvkVnaog8+jdpjTdwhG1xsr74ik6ps28JEP1vk0YwtkQYw4CKzckg1JxO0XroS5mg0SmS3gKfJYEzSl8xMCS8rSn9DGxnQ8542HgNG6rB9m6XqdVeY0PFZZU+n8Y/gzhzpCwBUme56bnFzOjy3F1gKjIMmn4K74YmiStQye9DjH2FaVsPg6E3f4EegfeUeejKqDAulWMLgpj7TjSKoHirNZ5NgKi7TDQGS0Qmk4Q==

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;