14

Building an Angular 2 app using Typescript, I am attempting to import the popular d3 library.

I have installed the type definitions using TSD, and I am referencing the tsd.d.ts file correctly:

/// <reference path="../../../tools/typings/tsd/tsd.d.ts" />

Now, I want to import my d3 node_module. It was installed via NPM:

/// <reference path="../../../tools/typings/tsd/tsd.d.ts" />
import * as d3 from 'd3/d3';

This works, but I don't get any benefit from my type definitions. My IDE is not providing any type-ahead info or syntax highlighting. If I change it to this:

/// <reference path="../../../tools/typings/tsd/tsd.d.ts" />
import * as d3 from 'd3/d3';

I now get all of the syntax highlighting/type-ahead definitions that I am expecting. However, my app is looking for a file at node_modules/d3.js which doesn't exist, so this obviously doesn't work.

When I change my import statement to a var declaration, my app compiles correctly and I get all the appropriate typescript definitions:

/// <reference path="../../../tools/typings/tsd/tsd.d.ts" />
declare var d3 = require('d3/d3');

So, my question is simply what is the right approach? What is the difference in import vs declare var, and is there a way to get type definitions when using import if they are not included in the npm module itself?

I've noticed things like import {Component} from 'angular2/core'; work fine, but the type definitions are included within the same directory as the javascript file I am importing.

SnareChops
  • 13,175
  • 9
  • 69
  • 91
JMac
  • 1,726
  • 3
  • 14
  • 30

1 Answers1

30

import * as d3 from 'd3/d3'; should work fine with the type system (without the ///<reference .../>) as long as the compiler options are correct, and the folder structure is correct in the typings folder.

declare var d3 is how to declare a variable that exists somewhere in the JS. Think of it like "Yeah yeah typescript, quit complaining, trust me it exists".

import {Component} from 'angular/core'; is how to pull a specific piece from a module. In node terms this translates to var Component = require('angular/core').Component;

The important compiler option to have on is "moduleResolution": "node", which should already be on for angular to function.

So if d3 was installed as a node_module then you should be able to simply use:

npm install d3
npm install --save-dev @types/d3
tsc

then

import * as d3 from 'd3';
SnareChops
  • 13,175
  • 9
  • 69
  • 91
  • 6
    for others who are first-stepping with typescript (like me), 'tsd' had been deprecated in favor of 'typings' – cesarpachon May 17 '16 at 13:40
  • Correct me if I'm wrong. This step { npm install d3, tsd install d3, tsc } equals to----> npm install @types/d3 then, the import step right?? – Rishi0405 Apr 20 '18 at 09:09
  • 1
    @Rishi It's possible that `d3` is a dependency of `@types/d3` which would cause your scenario to work. However the preferred approach is probably `npm install d3` then `npm install --save-dev @types/d3` so that you put the dependencies in the right spots in the `package.json`. `@types/d3` is not needed at runtime, only compile time, so users of your package / prod versions of your site do not need the extra files, so they can be safely ignored. – SnareChops Apr 26 '18 at 02:03