d3 V4.2.1 TypeScript 2.0 error importing d3-selection-multi - d3.js

I am trying to import d3 v4 into a typescript project using jspm and systemjs. I can get d3 imported correctly using this
import * as d3 from 'd3';
This works and it allows me to make selections etc. I tried using the attr function and passing it an object which did not work. I found that d3 v4 includes that as a separate module.
After downloading that module d3-selection-multi with jspm. I try to import it into my project like so.
import * as d3 from 'd3';
import 'jspm_packages/npm/d3-selection-multi#1.0.0';
I then try and use the attrs function but the console logs the following error
(index):40 Error: (SystemJS)
d3.selectAll(...).data(...).style(...).attrs is not a function(…)
I am also getting some compile error which i get all the time but yet they always still compile and the code runs
error TS2307: Cannot find module 'd3'
error TS1110: Type expected
Can any one explain what I am doing wrong and offer a solution?

The following should work
import * as d3 from 'd3';
import 'd3-selection-multi';

I ended up having to create a 'bundle' file and import that instead of importing individual d3 packages. This is probably not ideal, but it works (I've commented out packages which I do not need, in order to save on space):
// export * from 'd3-array';
// export * from 'd3-axis';
// export * from 'd3-brush';
// export * from 'd3-chord';
// export * from 'd3-collection';
// export * from 'd3-color';
// export * from 'd3-dispatch';
// export * from 'd3-drag';
// export * from 'd3-dsv';
// export * from 'd3-ease';
// export * from 'd3-force';
// export * from 'd3-format';
// export * from 'd3-geo';
// export * from 'd3-hierarchy';
// export * from 'd3-interpolate';
// export * from 'd3-path';
// export * from 'd3-polygon';
// export * from 'd3-quadtree';
// export * from 'd3-queue';
// export * from 'd3-random';
// export * from 'd3-request';
// export * from 'd3-scale';
export * from 'd3-selection';
export * from 'd3-selection-multi';
export * from 'd3-shape';
// export * from 'd3-time';
// export * from 'd3-time-format';
// export * from 'd3-timer';
// export * from 'd3-transition';
// export * from 'd3-voronoi';
// export * from 'd3-zoom';
To use this, I just have to:
import * as D3 from './d3.bunde.ts';
P.S. Probably doesn't matter, but I'm building my project using angular-cli.

Working "jspm + d3-selection-multi" example: https://github.com/jakeNiemiec/jspm_d3
If you need to import all of D3, use jspm install npm:d3. This will add quite a bit of bloat. Remember that jspm comes with rollup, take a look at the build script in package.json.

Related

Cannot find module even though the cypress test runner is able to mount the component

I am trying to set up component tests with cypress, vue3 and vite. With the Getting Started guide, I was able to successfully mount my component, however in my editor (vscode), it tells me that I cannot find the module or corresponding type declarations ts(2307).
I have added the global styles file in support/component.ts and nothing else.
// Import commands.js using ES2015 syntax:
import "./commands";
// Import global styles
import "../../src/styles/style.scss";
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from "cypress/vue";
// Augment the Cypress namespace to include type definitions for
// your custom command.
// Alternatively, can be defined in cypress/support/component.d.ts
// with a <reference path="./component" /> at the top of your spec.
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount;
}
}
}
Cypress.Commands.add("mount", mount);
How do I get rid of the linter warning?

Client-only Nuxt 3 D3 plugin

I'm trying to use the D3 extension in a Nuxt 3 project and for that I created a d3.client.js file in the plugins/ directory.
import * as d3 from "d3";
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(d3)
})
However, when I try to use it gives me a 500 Internal Server Error document is not defined.
<script>
import * as d3 from "d3";
export default {
name: "globe",
created() {
d3.select("#globe");
}
}
</script>
How can I solve this?
d3.select() uses document.querySelector() under the hood. Since you're working server side, you don't have access to document yet. So you'll need to mock it or to avoid using it.
You can avoid using it all together by passing an element instead of a string to d3.select(), as it will then create a functioning d3 selection without running document.querySelector(). And since every other chained .select() or .selectAll() uses previousSelection.querySelector(), you can just continue from there.
If you do not have access to the DOM element directly, you might want to mock document. This article suggests using JSDOM:
import { JSDOM } from 'jsdom';
// create a new JSDOM instance for d3-selection to use
const document = new JSDOM().window.document;
d3.select(document.body)
.append('div');
I managed to solve it by using the d3.select with a Vue reference.
const globe = d3.select(this.$refs.globe)

Re-export all imports with changed type definition

We have a git submodule of React components written in poorly typed TS. It has a single index file, which re-exports everything like this:
export * from './blocks'
Then, in the main app, we use import * as allBlocks from '../packages/blocks' or import {SomeBlock} ....
But now, I have added some type declarations to the mentioned index file, which, however, need to be imported separately to use.
Is there a way to tell TS to re-export as the new type?
for example something like this:
export * from './blocks' as TheNewType
This is how the index file looks currently.
export * from './blocks' // I want to export all as different type
// all this is just for the types
import * as allBlocks from './blocks'
type AllBlocks = typeof allBlocks
type BlockNames = keyof AllBlocks
export type BlockComponents = {
[key in BlockNames]: BlockComponent<ExtractComponentGenerics<AllBlocks[key]>>
}
type BlockComponent<P = {}> = React.ComponentType<P> & BlockComponentStatics<P>
/** This interface types some static properties used by our library, that are not normally present on React.ComponentType */
interface BlockComponentStatics<P = {}> {
getInitialProps?(): P | Promise<P>;
// ...
}
function assertIsBlocks(val: any): asserts val is BlockComponents {/*...*/}
assertIsBlocks(allBlocks)
export allBlocks // This unfortunatelly produces named export, which I don't want.
export default allBlocks // I don't want this neither. I want the * export.
Since this package doesn't come as a module, I am not sure if and how I can use Ambient module declaration or Module augmentation.

VSCode - Reference a type of a module from JS

Using Visual Studio Code for JS programming I can access some features from typescript; since the editor will parse all .d.ts files around, it'll help me with variable types. For example it does recognize the following:
any.js
/**
* #param {string} s
* #return {Promise<Person>}
*/
function foo(s){ ... }
foo('Jhon').then((p) => p.name )
index.d.ts
interface Person {
name: string
surname: string
}
Now, I want to access types (interfaces, classes... whatever) declared in node.d.ts declaration file; for example it declares the module stream which declares the Readable interface.
I'm looking for something like this:
const stream = require('stream')
/**
* #param {stream.Readable} stream
*/
function goo(stream) { ... }
But that does not work.I've tried with:
{internal.Readable}
{stream.Readable}
{Node.stream.Readable}
{Node.Readable}
{Node.internal.Readable}
As of VS Code 1.18, this is a limitation when using require with JSDoc types. I've opened this issue to track this specifically
Some possible workarounds:
Use import:
import * as stream from 'stream'
/**
* #param {stream.Readable} stream
*/
function goo(stream) { ... }
or import Readable explicitly:
const stream = require('stream')
const {Readable} = require('stream')
/**
* #param {Readable} stream
*/
function goo(stream) { ... }
https://github.com/Microsoft/TypeScript/issues/14377 also tracks allowing you to specify module imports in jsdocs directly.

How to add a simple SVG using D3 and ES2015

I have a ES2015 project using Webpack. I am trying to add D3v4 so I add the following...
// Typescript
import { select } from 'd3';
...
select(".application").append("svg"); // line 22
I have also tried...
import { select } from 'd3-selection';
But this throws an exception...
ERROR in ./src/main/angular/app/app.component.ts
(22,12): error TS1138: Parameter declaration expected.
What is the correct way to do this? Is there any D3 documentation for ES2015?

Resources