Namespaces vs modules vs typings in typescript?

后端 未结 1 1800
南笙
南笙 2020-12-28 11:33

Can someone please explain the difference between these concepts with an example,I\'m really confused,what\'s the use of having three of them when they all serve the same pu

相关标签:
1条回答
  • 2020-12-28 11:52

    TL;DR

    Modules and namespaces are two means of encapsulation - breaking your code into parts that make sense. New code should be written with modules, rather than namespaces.

    Declaration files ("typings") are used to describe modules, namespaces, variables, type declarations, etc. without actually containing any runnable code. Declaration files just tell TypeScript about what things exist, and how you can use those things.

    DefinitelyTyped hosts declaration files for different packages. Declaration files for a DefinitelyTyped package called foo-bar will be published as @types/foo-bar on npm.

    Namespaces

    These formalized a somewhat dated pattern in JavaScript. The pattern was basically wrapping code in an IIFE to prevent conflicts of declarations in the global scope. These things tacked "exports" onto an object and assigned them to a variable that (hopefully) had unique name in the global scope, like $ or _ or whatever.

    As an example:

    namespace foo {
        export var x = 10;
        export var y = 20;
    }
    

    This emits

    var foo;
    (function (foo) {
        foo.x = 10;
        foo.y = 20;
    })(foo || (foo = {}));
    

    Namespaces have other useful properties, like being able to merge with functions, classes, or other namespaces. But mainly, they were introduced during a transitionary period where it was necessary to serve both major ways to organize code: either providing the API surface on a well-known variable in the global scope (e.g. $, _, angular) or...

    Modules

    These all at once describe ECMAScript (standard JavaScript), CommonJS (i.e. Node.js), AMD (i.e. Require.js), and System.js modules. The crux of the idea here is that instead of just plopping variables into the global scope and hoping they don't conflict, each file gets its own unique scope and has exports.

    In practice, the original implementations of modules (CommonJS, AMD, System.js) work the same way: wrap your code in a function to get the correct scope, and tack properties onto an object.

    But TypeScript allows you to write code as if you were authoring ECMAScript modules with top-level export statements. Basically, to TypeScript, any file with top-level imports or exports is a module.

    As an example, the following

    export var x = 10;
    export var y = 20;
    

    translates to the following CommonJS module:

    "use strict";
    Object.defineProperty(module.exports, "__esModule", { value: true });
    module.exports.x = 10;
    module.exports.y = 20;
    

    While namespaces have some useful use-cases, modules have become the clear way forward for breaking your code up into different pieces.

    Typings/Types

    "Typings" was a package manager for declaration files (.d.ts files) before @types became the prescribed way to get declaration files (more on this soon)

    As a result, "typings" has also become a sort of nickname for declaration files.

    If you are starting a new project, do not use Typings. The TypeScript ecosystem has largely standardized on using npm for declaration files. Additionally, because of the confusion in terminology, you should probably not call declaration files "typings".

    With that said, we can move into the following topic:

    Declaration files

    Declaration files (.d.ts files, also called definition files) are TypeScript files that describe existing code. They can be produced from .ts files using the --declaration flag, or they can be authored manually to describe existing JavaScript code.

    Declaration files contain declarations of the code that they actually describe. To be more specific, the following TypeScript function:

    function foo(x: number, y: number) {
        return x * 100 + y;
    }
    

    would be described by the following declaration:

    declare function foo(x: number, y: number): number
    

    If the original declaration was written in JavaScript, it could still be described using a declaration with explicit types like above.

    This is important because the vast majority of JavaScript code isn't originally authored in TypeScript. So the community has come together and created a repository of declaration files called DefinitelyTyped.

    DefinitelyTyped

    This is a big git repository that describes over 3000 libraries at the time of this writing. Users can send pull requests for fixes and new packages.

    You can take a look at the repo here on GitHub.

    @types and npm

    This is how you can get declaration files from DefinitelyTyped. For example, if you wanted the .d.ts files for lodash, you could write

    npm install @types/lodash
    

    See

    • the consumption section of the TypeScript website on declaration files.
    • the announcement blog post titled The Future of Declaration Files
    • the elaboration of the above blog post

    How do these relate?

    Unfortunately the ideas here are subtle. Declaration files can describe everything in TypeScript. That means that they can describe what a module looks like, as well as what a namespace looks like.

    So declaration files don't serve the same purpose as modules and namespaces. But they do describe to TypeScript when namespaces and modules exist, and how they can be used.

    Basically, if you ever need to use something that looks like a module or a namespace and it was written in JS, you'll need a declaration file.

    Even if it was written in TypeScript, if it was already compiled to .js, then you'll need a respective .d.ts file to use it.

    I still don't understand

    Hopefully this helped explain, but if not, check out

    • The modules section on the TypeScript website.
    • TypeScript Deep Dive's section on modules
    • the above resources
    • Ryan's weird candy cup analogy that describes the differences between modules and namespaces that cartant linked to above.
    0 讨论(0)
提交回复
热议问题