score:2

Accepted answer

This question is the TypeScript equivalent of various types of JavaScript questions that pop up every now and then where the developer confuses passing a function by reference with calling said function in situ whereby just passing its return value.

You are actually calling, i.e. executing, the line generator by doing lineGenerator(data). As you can see from the API docs and the type definitions this will return either a string or null:

export interface Line<Datum> {
  (data: Datum[]): string | null;
  //...
}

This does not match the signature of the .attr() method, though, which in this case expects a function to be passed as the second argument.

export interface Selection<GElement extends BaseType, Datum, PElement extends BaseType, PDatum> {
  //...
  attr(name: string, value: ValueFn<GElement, Datum, string | number | boolean | null>): this;
  //...
}

The solution is to pass the generator to .attr() without executing it:

.attr('d', lineGenerator)

The generator will then be executed by the inner workings of .attr() being passed the data bound to the selection. That, in turn, will return the path definition string for the d attribute of the path.


Related Query

More Query from same tag