全局代码库

全局代码库可以通过全局作用域来访问(例如,不使用任何形式的import语句)。 许多代码库只是简单地导出一个或多个供使用的全局变量。 比如,如果你使用jQuery,那么可以使用$变量来引用它。

  1. $(() => {
  2. console.log('hello!');
  3. });

你通常能够在文档里看到如何在 HTML 的 script 标签里引用代码库:

  1. <script src="http://a.great.cdn.for/someLib.js"></script>

目前,大多数流行的全局代码库都以 UMD 代码库发布。 UMD 代码库与全局代码库很难通过文档来识别。 在编写全局代码库的声明文件之前,确保代码库不是 UMD 代码库。

从代码来识别全局代码库

通常,全局代码库的代码十分简单。 一个全局的“Hello, world”代码库可以如下:

  1. function createGreeting(s) {
  2. return 'Hello, ' + s;
  3. }

或者这样:

  1. window.createGreeting = function (s) {
  2. return 'Hello, ' + s;
  3. };

在阅读全局代码库的代码时,你会看到:

  • 顶层的var语句或function声明
  • 一个或多个window.someName赋值语句
  • 假设 DOM 相关的原始值documentwindow存在

你不会看到:

  • 检查或使用了模块加载器,如requiredefine
  • CommonJS/Node.js 风格的导入语句,如var fs = require("fs");
  • define(...)调用
  • 描述require或导入代码库的文档

全局代码库的示例

由于将全局代码库转换为 UMD 代码库十分容易,因此很少有代码库仍然使用全局代码库风格。 然而,小型的代码库以及需要使用 DOM 的代码库仍然可以是全局的。

全局代码库模版

你可以看到如下声明文件的示例:

  1. // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
  2. // Project: [~THE PROJECT NAME~]
  3. // Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
  4. /*~ If this library is callable (e.g. can be invoked as myLib(3)),
  5. *~ include those call signatures here.
  6. *~ Otherwise, delete this section.
  7. */
  8. declare function myLib(a: string): string;
  9. declare function myLib(a: number): number;
  10. /*~ If you want the name of this library to be a valid type name,
  11. *~ you can do so here.
  12. *~
  13. *~ For example, this allows us to write 'var x: myLib';
  14. *~ Be sure this actually makes sense! If it doesn't, just
  15. *~ delete this declaration and add types inside the namespace below.
  16. */
  17. interface myLib {
  18. name: string;
  19. length: number;
  20. extras?: string[];
  21. }
  22. /*~ If your library has properties exposed on a global variable,
  23. *~ place them here.
  24. *~ You should also place types (interfaces and type alias) here.
  25. */
  26. declare namespace myLib {
  27. //~ We can write 'myLib.timeout = 50;'
  28. let timeout: number;
  29. //~ We can access 'myLib.version', but not change it
  30. const version: string;
  31. //~ There's some class we can create via 'let c = new myLib.Cat(42)'
  32. //~ Or reference e.g. 'function f(c: myLib.Cat) { ... }
  33. class Cat {
  34. constructor(n: number);
  35. //~ We can read 'c.age' from a 'Cat' instance
  36. readonly age: number;
  37. //~ We can invoke 'c.purr()' from a 'Cat' instance
  38. purr(): void;
  39. }
  40. //~ We can declare a variable as
  41. //~ 'var s: myLib.CatSettings = { weight: 5, name: "Maru" };'
  42. interface CatSettings {
  43. weight: number;
  44. name: string;
  45. tailLength?: number;
  46. }
  47. //~ We can write 'const v: myLib.VetID = 42;'
  48. //~ or 'const v: myLib.VetID = "bob";'
  49. type VetID = string | number;
  50. //~ We can invoke 'myLib.checkCat(c)' or 'myLib.checkCat(c, v);'
  51. function checkCat(c: Cat, s?: VetID);
  52. }