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
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.
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...
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 import
s or export
s 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" 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 (.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.
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 npmThis 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
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.
Hopefully this helped explain, but if not, check out