Use discriminated union to type Shape of datasets and attributes#1952
Merged
Conversation
axelboc
commented
Jan 29, 2026
|
|
||
| export interface ScalarShape { | ||
| class: ShapeClass.Scalar; | ||
| dims: []; |
Contributor
Author
There was a problem hiding this comment.
This empty dims is just for convenience when dealing with datasets/attributes with shape ScalarShape | ArrayShape — it means I can still access obj.shape.dims and check the length to decide what to do without TypeScript complaining. See for instance renderDims(entity.shape.dims) in EntityInfo.tsx.
axelboc
commented
Jan 29, 2026
loichuder
approved these changes
Jan 30, 2026
loichuder
left a comment
Member
There was a problem hiding this comment.
Looks good and also more consistent in containers where we used to rename shape to dims.
Congrats 👍
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With
HasShape, introduced in #1951, asserting the shape of a dataset leads to slightly different types than before, for instance:Dataset<Shape, DType> & HasShape<ArrayShape>instead ofDataset<ArrayShape, DType>.While the two types are equivalent, this subtle change broke our
Valuetype due to how conditional types work. At the root of the issue is the fact thatScalarShape extends ArrayShape([] extends number[]). This has been a long-standing issue, but it hadn't really been a problem until now.Here's a a summary of the problem:
This causes issues when doing, for instance:
I thought I had found a workaround in #1951 by using
[S] extends [ScalarShape]at line(A), but it wasn't quite right: instead of breaking the 5th test case above, it was breaking the first case (Test1would resolve tostring[]instead ofstring | string[]). I uncovered the problem when trying to type-check theaxesandauxiliary_signalsNeXus attribute, as we allow these attributes to be eitherstring[]orstring.Solution
I tried to patch the
Valueconditional type in many ways but nothing worked... So I decided to fix the problem at the root by changing theShapetype.Conditional types work best with discriminated unions, so that's what I went for. This is already what we use for the
DTypetype and it works great.Here is the gist of it:
I think it's a beneficial change overall, both internally for stricter and more verbose type-checking, and externally for end users: