2

The Namespaces chapter give an example related to D3.d.ts which I don't understand.
This is the full example:

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;

What I really don't understand is how would I use D3.d.ts in my modules or my typescript scripts? Please give me some short examples.

EDIT
Please ignore the fact that here it is used D3; could be B3 or G3 or X7 ... whatever; I'm not interested on a specifically library. I'm only interested in how would I use the example given both in my typescript modules and my typescript scripts.

EDIT2 What mostly confuse me is the fact that the above example uses declare namespace ... instead of namespace D3 (as used e.g. for namespace Validation). Also what's the use (and how to use?) of declare var d3: D3.Base;?

Adrian
  • 3,321
  • 2
  • 29
  • 46
  • As you can see this is not a module so I guess (only) I can't use it in one of my modules. Or I might be completely wrong because of my complete confusion after reading the Modules and Namespaces chapters. – Adrian Mar 22 '18 at 20:06
  • edited my response. – jrv Mar 22 '18 at 23:06

3 Answers3

6

Such declarations define global variables that do not come from imports but might be defined on the window by some <script>. To be able to simply use these variables directly (without imports!) you could always use a reference, e.g.:

/// <reference path="../types/D3.d.ts" />
d3.select("div"); // No import!

If the declaration file is placed in an @types directory it should be included without explicit reference.


The namespace uses declare because this is a declaration file: It has to either export the namespace (which only is valid for modules) or declare it, to make these types available.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Thanks but you miss my intent. I edited my post in order to avoid this. Specifically I don't care it's about d3 or g3 or whatever. – Adrian Mar 22 '18 at 20:00
  • My answer does not care about that either. The point is: If placed in a `@types` directory or referenced you then can use the globally defined variables. In the example `d3`. Without any import. – H.B. Mar 22 '18 at 20:19
  • Sorry again for me badly explaining my intent. I guess your suggestion is related to [Declaration Files](https://www.typescriptlang.org/docs/handbook/declaration-files) but the example is from the [Namespaces](https://www.typescriptlang.org/docs/handbook/namespaces.html) chapter and I guess the notions learned there should apply to the example given too but not to a later chapter (meaning Declaration Files). – Adrian Mar 22 '18 at 20:30
  • @adrhc: What are you talking about? This clearly *is a declaration file* (`.d.ts`), all of this is specific to declaration files. – H.B. Mar 22 '18 at 20:32
  • edited comment: You are right, it's a declaration file. Now please see the EDIT2. – Adrian Mar 22 '18 at 20:33
  • I have seen that, it's what you copied. It's a **declaration file**. – H.B. Mar 22 '18 at 20:34
  • `/// ` confuses me. The file specified in the example is named _D3.d.ts_ and I'm a linux guy (case sensitive FS). Are you talking about _D3.d.ts_ file or something else? – Adrian Mar 22 '18 at 20:54
  • @adrhc: It's just an example, it does not matter what the declaration file is named. Just assume that this file has the same contents as the ones in your code snippet. – H.B. Mar 22 '18 at 20:55
1

As I understand typescript the "code" in the example does not generate nor change any output javascript. It is all declarations that will help intellisense and the typescript compiler find errors, but does nothing to alter the code. The declarations that the example gives are intended for an "ambient" declaration file, i.e. a declaration file that provides typescript definitions for ordinary javascript library so that typescript and intellisense can work with them as if they were typescript files instead of plain javascript. I believe that at a first approximation typescript treats anything it finds of which it has no declaration knowledges as an "any" type.

For the library mentioned you would be better off to use the existing type library (npm install --save-dev @types/d3). I have found that after installing the library (npm install --save d3) and the @types/d3, using import * as d3 from 'd3' in a .ts file (in angular 5; other situations may other steps) will bring the object and type information in, and everything works satisfactorily. If you open up the types file you will see a completely different set of declarations from the ones given in the typescript documentation example, but I believe they are still all declarations, i.e. no code.

In reply to edits

The file in the example is not a primary typescript file. It is a declarations file describing the "typescript shape" of an ordinary javascript library, i.e. how the typescript compiler and intellisense should pretend the ordinary javascript would look like if it were written in typescript. While you may think the choice of the name D3 was arbitrary, it was not exactly. The .d.ts file is trying to provide typescript meta information for a library (the d3 library: https://www.npmjs.com/package/d3) which does not itself provide that information (although, as mentioned, the typescript meta information for that particular library is available as an @types package).

If you were writing your own library code and wanted to work inside a namespace as per the validation example, you would use namespace D3 rather than declare namespace D3, but you would also be writing a .ts file, not a .d.ts file. As the section title of the documentation says, that example is working on ambient namespaces, i.e. namespaces for ordinary javascript code the writer of the file does not (typically) provide.

In summary, the goals of the two halves of the documentation are different. In the first half the "validation" code is showing you how to use namespaces within your own typescript code. In the second half, the "d3" code is showing you how you can provide typescript metadata for code that is plain javascript, not typescript.

jrv
  • 443
  • 4
  • 14
  • Sorry, I badly explained my intent; please see the EDITs. – Adrian Mar 22 '18 at 20:31
  • The "In summary ..." part is helpful for me. The "... name D3 was arbitrary ..." part is confusing because I'm a linux guy (case sensitive FS) and when thinking about a relation between _D3_ and _d3_ in fact there's none (considering the case sensitivity). Besides I read the entire typescript [Documentation](https://www.typescriptlang.org/docs/home.html) and I don't remember existing such a relation; maybe you could point that to me? – Adrian Mar 23 '18 at 18:05
  • When I said the name was not arbitrary, I did not mean it was computationally significant. There is no code that will not work if the namespace were called "DeeThree" instead of "D3." I don't know, but there may be some name collision if it were called "d3", because the d3 library declares a global variable with that name. Even if there is no collision, I personally would name the namespace differently just to make it clear that sometimes I am referring to the namespace (D3) and sometimes to the variable (d3). There is no program relation between the upper-case symbol and the lower-case one. – jrv Mar 26 '18 at 02:07
0

The declare namespace keyword is mainly used to extend or modify existing namespaces, typically in the context of external libraries or type declaration files. In this case, all members inside the declare namespace block are automatically made accessible to other files for referencing.

On the other hand, the namespace keyword is used to define a new namespace. In this case, the members defined inside the namespace are not exposed to the outside by default. You need to explicitly use the export keyword to make the desired members accessible for referencing in other files.

In summary, declare namespace is used to modify or extend existing namespaces, and all members are automatically exposed to the outside. namespace is used to define a new namespace, and you need to manually export the members to make them accessible externally.

I hope this clarifies the difference between declare namespace and namespace!

Jeong_94
  • 11
  • 4
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 12 '23 at 18:53