Kingamere
Kingamere

Reputation: 10122

d3.js v5.9.1 - some methods in this version are not working as expected

I am using d3.js in an Angular 7.1.4 project. The version of d3 I am using is 5.9.1, which is the latest version so far.

I installed this using npm as follows:

npm install d3

which put "d3": "^5.9.1" in my package.json file.

I also installed @types/d3 through npm with the command npm install @types/d3, and that put "@types/d3": "^5.7.1" in my package.json file.

With the @types/d3 dependency, I imported d3 into my typescript files like so:

import * as d3 from "d3";, just like the d3 github guide says.

Now, I am following an example on this website that creates a bar graph using d3.

The full source code of the example is found here on jsfiddle, and if you look at their declared <script> tag, you will see that they are using d3 version 5.9.1, which is the same version I am using:

<script src="https://d3js.org/d3.v5.min.js"></script>

// https://d3js.org v5.9.1 Copyright 2019 Mike Bostock

However, when I copy the following code into my typescript file:

  const yScale = d3.scaleLinear()
  .range([height, 0])
  .domain([0, 100]);

  const makeYLines = () => d3.axisLeft()
  .scale(yScale)

I am getting an error at the d3.axisLeft() method call, and the error says:

Expected 1 arguments, but got 0.

However, the example on jsfiddle uses the same exact version that I have (5.9.1) and is not running into any problems.

Can someone explain what the problem is?

EDIT:

I just checked the minified js file and the original js file for https://d3js.org/d3.v5.js and the axisLeft method actually does take an argument:

function axisLeft(scale) { return axis(left, scale); }

So how is the jsfiddle example calling the method without passing an argument to it?

Upvotes: 1

Views: 780

Answers (1)

Mark
Mark

Reputation: 108537

Well, if you look at the d3 source code a little further, the argument it's looking for you to pass is the scale:

function axis(orient, scale) {
  var tickArguments = [],
  ...

If you don't pass it the scale will go in as undefined.

But axis is a closure that provide an alternate way to provide a scale with a .scale "method".

axis.scale = function(_) {
  return arguments.length ? (scale = _, axis) : scale;
};

Your very next bit of code is passing the scale in using that "method".

Now with TypeScript certain concessions need to be made as it's not a loosy-goosy as JavaScript. So the typings author chose to follow the axis function signature. All that said, your TypeScript should just follow that example, and be:

const makeYLines = () => d3.axisLeft(yScale);

Upvotes: 5

Related Questions