打字稿中的类和命名空间之间的区别

时间:2018-01-14 17:17:59

标签: javascript class typescript namespaces difference

Typescript中的类和命名空间之间究竟有什么区别?我知道如果你用静态方法创建一个类,你可以在不实例化类的情况下访问它们,而这正是我想要的命名空间之一。

我也知道你可以创建多个具有相同名称的命名空间,并且在编译为JS时它们的方法属于同一个函数。

但我无法弄清楚何时使用其中一个......对我来说,最后,类和命名空间几乎相同,所以我想我错过了一些东西......

2 个答案:

答案 0 :(得分:2)

  

但我无法弄清楚何时使用其中一个......对我来说,最后,类和命名空间几乎相同,所以我想我错过了一些东西......

如果要创建实例,请使用类,例如

class Foo {
 x = 0
}
const foo = new Foo(); // instantiate

仅在需要对类似的类/函数/变量等进行分组时才使用命名空间,例如

namespace Foo {
  export class Bar {}
  export class Bas {}
}

重叠

最终用法语法有重叠,例如类上的静态可以滥用以像命名空间一样运行。如果您按照本指南操作,则可以忽略该重叠。

答案 1 :(得分:0)

你是对的。命名空间和静态类是类似的。它们有一些共同的特征。它们都是具有相似性的ES5模式的语法糖 - cf。由TypeScript playground

提供的JavaScript编译
// TypeScript
class C {
    static readonly Name = 'C';
    static print() {
        console.log(`Name=${C.Name}`);
    }
}

namespace N {
    export const Name = 'N';
    export function print() {
        console.log(`Name=${Name}`);
    }
}

// Usage
C.print();
N.print();
const c = new C();
const n = new N(); // TS Error: Cannot use 'new' with an expression whose type lacks a call or a construct signature

// Transpiled JavaScript
var C = /** @class */ (function () {
    function C() {
    }
    C.print = function () {
        console.log("Name=" + C.Name);
    };
    C.Name = 'C';
    return C;
}());

var N;
(function (N) {
    N.Name = 'N';
    function print() {
        console.log("Name=" + N.Name);
    }
    N.print = print;
})(N || (N = {}));

然而,他们也有自己的特点:

  • 命名空间仅在TypeScript中,而不在ECAMScript中。它们可以被视为IIFE句法糖。它们可以嵌套(例如A.B.C)以重新集合C#名称空间。从ECMAScript 6 (ES6 / ES2015)开始,在大多数情况下,ES6模块比命名空间更有趣,因为在文件级别处理嵌套更简单,并保持代码结构平坦。

  • 包括静态成员也可在ES6中使用。它们也是“构造函数模式”的语法糖。静态类提供与命名空间相同的功能,但语法不太常见 - 参见前面的示例。

因此,从根本上说,每种模式都有自己的与这些用例相关的理念:

  • 对于静态(即+/-全局)成员:大多数情况下是ES6模块;有时甚至在模块内部也是TypeScript命名空间 - TS Doc ;或者只是一个恒定的对象文字,
  • 创建对象:类(顺便说一句,也可以有静态成员,比如工厂方法),工厂函数,只是普通对象文字,...

这些建议有助于使代码更“惯用”,即更易于阅读和维护。

但您/您的团队拥有您的代码,而您的决定权归您所有。您可以尝试不同的模式,根据您的经验进行比较。最后,如果它是您的选择,那么在命名空间上使用纯静态类也不错,比如使用命名空间而不是ES6模块。