GithubHelp home page GithubHelp logo

[geoPath()] Default Values Not Set about d3-geo HOT 10 CLOSED

d3 avatar d3 commented on April 27, 2024
[geoPath()] Default Values Not Set

from d3-geo.

Comments (10)

tomwanzek avatar tomwanzek commented on April 27, 2024 1

Thanks, I will update the definitions for d3-geo to reflect the changes with 1.4.0. Once you update the D3 Standard Bundle to use d3-geo 1.4, I will bump that as well.

from d3-geo.

mbostock avatar mbostock commented on April 27, 2024

That seems like the expected behavior, as the defaults are null. Or are you saying it should return null instead of undefined? I suppose I am being lazy and treating them as equivalent. I’m not sure whether to fix the documentation to say the defaults are undefined, or to coerce the undefined to null… FWIW, it’s also the case that path.projection(undefined) will set the projection to undefined, and not null, and likewise with path.context.

from d3-geo.

tomwanzek avatar tomwanzek commented on April 27, 2024

I think there are a couple of things coming together here. One is pertinent to the API doc in and of itself:

The geoPath(...) API states:

Creates a new geographic path generator with the default settings.

Which when looking at the corresponding API for the .projection(...) method of the path generator leads one to:

If projection is not specified, returns the current projection, which defaults to null. The null projection represents the identity transformation: the input geometry is not projected and is instead rendered directly in raw coordinates.

and correspondingly for the `.context(...) method:

If a context is not specified, returns the current render context which defaults to null.

The second aspect relates to the expected usage of folks wanting to use all the goodness of D3 with TypeScript. There have been several asks to tie the definitions down to what is referred to as strictNullChecks when compiling.

As of TypeScript 2, there is support for non-nullable types. I.e. before or without the said compiler option set, e.g, number is implicitly widened to number | null | undefined. By implication, developers are left to perform all the usual tests to ensure that variable/objects are not undefined or null before using them in operations or accessing members.

The drive behind validating the definitions is obvious, if the definitions reflect the underlying code, and the "contract" is for e.g. number, then no additional testing code will need to be written to rule out null or undefined.

Obviously, libraries may in some cases make a semantic distinction between undefined and null, which may be critical in distinguishing "failure" modes of methods/functions.

So it's down to as tight as reasonable contracts that avoid unnecessary validation code, while instead relying on the type-safety of the compiler.

Apologies for the digression, as I said the validation for strictNullChecks has been raised for the D3 definitions across the board. I have put it off to address other things in the interim.

IMHO, I would lean towards implementing the defaults as null in line with the already published API, unless that creates some issues I might have overlooked?

from d3-geo.

mbostock avatar mbostock commented on April 27, 2024

Hmm. This issue applies quite a bit more generally than just to d3.geoPath.

There are quite a few places in D3 where an accessor expects a function, null or undefined, and will not coerce an undefined value to null. There are also some places that do coerce undefined to null, such as line.context. Generally, I make a minimum effort to validate the input arguments, so the places that replace undefined with null are doing so because they had some reason to check whether the input value was nully. For example, if you pass a nully value to line.context, it means you want to generate an SVG path string rather than render to a CanvasRenderingContext2D, so the line generator checks the specified context and branches the logic as appropriate.

It’s tempting to add some logic to D3 to coerce nully input values to null. But it’s more tempting to verify that non nully input values that should be functions are indeed typeof "function", so that an error can be thrown immediately on set rather than on subsequent use with TypeError: value is not a function. There are a few places where I do perform such type checks, such as d3.dispatch, but it does feel like a rabbit hole in the sense that you can never validate the input types perfectly and I don’t feel like I have a good sense in JavaScript of what degree of input validation is appropriate.

And yet, the nice thing about TypeScript is that this can be done statically rather than burdening the runtime implementation, right? And so all we really need to do is fix the places where D3 internally violates the type constraint (such as in d3.geoPath where it initializes to undefined rather than null)?

from d3-geo.

tomwanzek avatar tomwanzek commented on April 27, 2024

Apologies for the slight delay in getting back to this.

You are right on both counts, for one, the point I raised above regarding strictNullChecks-validation is a bit broader than just geoPath(...). And secondly, it can be a bit of a rabbit hole 😟 .

That is the primary reason, why I initially deferred it when writing the definitions for the D3 Modules. I went after the low hanging, high value-add fruit first.

Nevertheless, yes, the benefit of "validate-once-compile-time-check-many" can be tremendous, where static type-checking is feasible. In particular, since it is possible to use interfaces, generics and function-signatures to set up fairly specific API contracts, where possible without being unnecessarily restrictive.

So it's the initial bump we are really talking about (e.g. DefinitelyTyped PR 12566 which is a starting point to refine the d3-selection and the modules most tightly coupled to it).

In a large number of cases the D3 API documentation is explicit enough (e.g. the rendering context related references you made above), in others I found I had to go to the code to see what is being coerced, defaulted or returned in certain well-defined failure modes, like, loosely speaking, "could not be found" or "not applicable".

The new geoPath(...) factory is an example, where there seems to be a very specific opportunity to narrow down to null without loss of generality.

As for the broader validation, IMHO the best approach would be to prioritize the modules (in batches as necessary where they are coupled) and set up a mini project:

  • to scrub through the API documentation vis-a-vis the corresponding TypeScript definition file,
  • flag any line items (method signatures, return values) where it seems non-obvious, and
  • decide on the appropriate action (definition refinement, API Doc update, minor code revisions to internally set defaults, whatever seems most appropriate).

Such a coordinated effort (spaced out to not overload anyone with cycles they need for other priorities would be great. Given your natural familiarity with the code and, more importantly, understanding of intent and context, it would be great to structure it with your input.

Open to suggestions.

from d3-geo.

mbostock avatar mbostock commented on April 27, 2024

Thanks—this is great feedback. I’m excited that your (and others’) work to support TypeScript will improve D3 even for non-TypeScript users.

from d3-geo.

tomwanzek avatar tomwanzek commented on April 27, 2024

So how about this: we limit this issue specifically to geoPath(...) and open a new discussion/strategy issue for the broader topic of integrating/moving forward D3/JS/TS.

You could open up a thread on d3, I can pour in a basic "level-setting" where the TS2 support is currently at and we can take it from there. You could frame it as widely or narrowly as you see fit.

At the narrow end of the spectrum is the scrub/validation listed above.

At the wider end is the strategic question of bringing the TS definitions into the respective D3 repos, while addressing the narrower needs along the way.

For what it's worth, it's about getting the most symbiotic arrangement for the user community and managing the scope/phasing along the way.

If you opened a thread up in d3, it could also be set up as a github project in follow-up. One thing a middle of the road contributor to DefinitelyTyped cannot do. I mostly used tracking issues, but bundling them into a project/labels/milestones etc. are not really an option given the extensive shared scope.

from d3-geo.

tomwanzek avatar tomwanzek commented on April 27, 2024

Will update definitions for d3-geo to allow geoPath(...) methods context() and projecttion() to return union type including both | null | undefined for purposes of strictNullChecking.

Corresponds to current behavior of module, no further action expected under this issue.

from d3-geo.

mbostock avatar mbostock commented on April 27, 2024

I’m fixing this to be null as we speak.

from d3-geo.

tomwanzek avatar tomwanzek commented on April 27, 2024

d3-geo definitions are updated and published.

from d3-geo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.