-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Types By Refactoring JSDoc #397
Conversation
src/layers/BitmapLayer.js
Outdated
constructor(props) { | ||
// needed for TypeScript types that are generated from the JSDoc | ||
// eslint-disable-next-line prefer-rest-params | ||
super(...arguments); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't love this. Typescript and JSDoc should just disappear from the final JS. Unfortunately this is actually changing our JavaScript code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tried it in my own code but you are changing the constructor signature of CompositeLayer
here: https://deck.gl/docs/api-reference/core/composite-layer#constructor-1
It's supposed to accept any number of props
objects that are combined by Object.assign
(or something similar).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big fan of the solution, but it works and am not aware of alternatives and it seems to tick the box for what we need.
A question and a comment:
1.) Have you check what the new generated documentation end up looking like? I've found that changing JSDoc usage can effect that output in unexpected ways.
2.) I wouldn't worry about some type of prop inheritance for now. If its something you're keen to explore, you can always create a types.d.ts
and import types in jsdoc:
export interface MyInterface {
foo: string;
bar: number;
}
/**
* @param {import('./types').MyInterface} props
*/
function fn(props) {
/* ... */
}
I tried doing this for class definitions but couldn't figure it out. The other issue is that could lose some of the documentation comments which are more valuable. My hope was just to have:
/**
* @type {import('./types').MultiscaleImageLayer}
*/
class MultiScaleImageLayer extends MultiscaleImageLayerBase
/* ... */
}
Yeah, certainly a tradeoff though. I notice it says |
Not sure I know what I'm looking at for the screenshot you've posted. I built the project locally and have the following: Which seems reasonable, but there are two outstanding issues: 1.) The fields defined on To make optional types in JSDoc is done by adding a e.g. 2.) As @andreasg123 pointed out, the constructor definition doesn't actually match what deck.gl allows. In its current form, the constructor type definition says it takes one argument (of /**
* @type {{ new (...props: LayerProps[]) }}
*/
const ImageLayer = class extends CompositeLayer { /* ... */ }
ImageLayer.layerName = 'ImageLayer';
ImageLayer.defaultProps = defaultProps;
export default ImageLayer; Unfortunately |
BTW, you can extract the Unfortunately JSDoc annotations for objects more complex than JS primitive types (e.g. JSDoc annotations/**
* @typedef LayerProps
* @type {Object}
* @property {Array} sliderValues List of [begin, end] values to control each channel's ramp function.
* @property {Array} colorValues List of [r, g, b] values for each channel.
* @property {Array} channelIsOn List of boolean values for each channel for whether or not it is visible.
* @property {number} opacity Opacity of the layer.
* @property {string} colormap String indicating a colormap (default: ''). The full list of options is here: https://github.com/glslify/glsl-colormap#glsl-colormap
* @property {Array} domain Override for the possible max/min values (i.e something different than 65535 for uint16/'<u2').
* @property {string} viewportId Id for the current view. This needs to match the viewState id in deck.gl and is necessary for the lens.
* @property {Object} loader PixelSource. Represents an N-dimensional image.
*/ TS syntax/**
* @typedef LayerProps
* @type {Object}
* @property {[start: number, end: number][]} sliderValues List of [begin, end] values to control each channel's ramp function.
* @property {[r: number, b: number, g: number][]} colorValues List of [r, g, b] values for each channel.
* @property {boolean[]} channelIsOn List of boolean values for each channel for whether or not it is visible.
* @property {number} opacity Opacity of the layer.
* @property {string} colormap String indicating a colormap (default: ''). The full list of options is here: https://github.com/glslify/glsl-colormap#glsl-colormap
* @property {[min: number, max: number][]} domain Override for the possible max/min values (i.e something different than 65535 for uint16/'<u2').
* @property {string} viewportId Id for the current view. This needs to match the viewState id in deck.gl and is necessary for the lens.
* @property {import('../types').PixelSource<string[]>} loader PixelSource. Represents an N-dimensional image.
*/ Which results in: The main benefit here is that our types are much more precise, and by importing the
|
@manzt I think I was able to add typed arrays to the JSDoc interfaces: Does this look right? The other thing I was able to do was to fix the array spread business @andreasg123 brought up via: Does this address this issues? Maybe I am missing something, and I know the second solution is a little different, but it seems to work. |
The docs don't respect "the array of props" still but we are no worse off there than before. |
Yeah I think those annotations from JSDoc are much better! They still aren't quite as precise as what TS syntax offers (e.g. an array of fixed length tuples is more strict that an array of variable length arrays), but slightly more strict which is great. For example, const layer = new Layer({
domain: [[1,2,34], [2,3], [1,2,3,34,5,6,7]], // this ok with `Array.Array<number>` and we know it's not.
/* ... */
}); Second, it would be my preference to remove the addition of the "magic" constructor in favor of using JSDoc /**
* @type {{ new (...props: LayerProps[]) }}
*/
const ImageLayer = class extends CompositeLayer { /* ... */ }
ImageLayer.layerName = 'ImageLayer';
ImageLayer.defaultProps = defaultProps;
export default ImageLayer; We don't need to explain ourselves for every class and disable linting. This method just changes how the objects are exported. |
Forgot about this, let me try it now! |
* @property {number=} opacity Opacity of the layer. | ||
* @property {function=} onClick Hook function from deck.gl to handle clicked-on objects. | ||
* @property {Object=} modelMatrix Math.gl Matrix4 object containing an affine transformation to be applied to the image. | ||
* @property {Array.<number>=} transparentColor An RGB (0-255 range) color to be considered "transparent" if provided. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
photometricInterpretation
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work Ilan! Thanks for going through all that with me. Hopefully this will make our end-users happier :)
src/layers/ImageLayer.js
Outdated
* @property {Array} loader PixelSource. Represents an N-dimensional image. | ||
* @property {Array} loader Selection to be used for fetching data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'd prefer if the the "required" fields proceeded all optional props.
src/layers/XRLayer/XRLayer.js
Outdated
* @property {number=} lensBorderRadius Percentage of the radius of the lens for a border (default 0.02). | ||
* @property {number} dtype Dtype for the layer. | ||
* @property {function=} onClick Hook function from deck.gl to handle clicked-on objects. | ||
* @property {Object} modelMatrix Math.gl Matrix4 object containing an affine transformation to be applied to the image. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Listed as a required fielded; don't see where this gets used. Could be missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I think the push was rejected. My internet has been flaking in and out. Switched to hotspot, will try again.
CHANGELOG.md
Outdated
@@ -4,6 +4,7 @@ | |||
|
|||
### Added | |||
|
|||
- Add constructors to layer classes so that types are emitted properly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit. We technically don't "emit" any types from our JSDoc annotations. They just remain in the bundled dist/index.js
as comments. Maybe "Refactor JSDoc comments to properly annotate Layer classes with constructor signatures."
No, thank you @manzt for pushing to make this perfect (and @andreasg123!) - this seems well worth the effort considering that we now have very nice types and internal accountability for the docs. |
Background
For #346 (comment) this adds a constructor and also types for the constructor's arguments (which are the layer props).
@andreasg123 I believe this should resolve that issue. Thanks for mentioning it!
Opening this as a draft while waiting on visgl/deck.gl#5587
Question:
LayerProps
typedef for all the layers to share that includes the basics likechannelIsOn
,opacity
etc.?I think this fixes #342
Change List
constructor
s to the layer classes.constructor
so that TypeScript definition includes constructor and its argumentsChecklist