Skip to content
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

Generate TypeScript definitions for JS API #3567

Merged
merged 36 commits into from
Apr 6, 2023
Merged

Conversation

niloc132
Copy link
Member

There are a few pieces missing to really be happy with these types, but they are mostly accurate and fit the patterns we're expecting.

Follow-ups, ranked in order of priority:

  • Correctly mark optional fields as such, either extending the use of the nullable annotation, or with a new annotation.
  • Generate union types, in place of some object or any references. The API actually accepts any object (and will give a runtime error if an unexpected type is used), but for TypeScript we can be more specific.
  • Correctly transform Java generics (default to no covariance/contravariance) into the corresponding TypeScript generics.

@niloc132 niloc132 added this to the Mar 2023 milestone Mar 17, 2023
Copy link
Member

@mofojed mofojed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably going to be some other changes, mostly asking about the optional parameters for now as that's causing a lot of issues.

public String type;
// TODO (deephaven-core#3442) change to some kind of String+int union type
public String position;

public boolean log = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the generated type for this is:

		log:boolean;

If I add @JsNullable, then it changes to:

		log:boolean|null|undefined;

What I think it should be is:

log?: boolean

Pretty much all of these params are optional. Is there anyway to make that notation? @JsOptional doesn't seem to work on properties (though maybe it should).

Copy link
Member Author

@niloc132 niloc132 Apr 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattrunyon and I had this chat in slack (you were in the channel too, but I don't recall if you weighed in) - we have 4 cases to handle, potentially:

  • not optional, not nullable - required, non-null values
  • optional and nullable - not required, and you can explicitly state null
  • not optional, but nullable - required, but you can explicitly state null
  • optional, but not nullable - not required, but if you specify it, it cannot be null

(note that I'm using "null" as a placeholder for "null or undefined")

If we need all four states, we must have both @JsNullable and a @TsOptional that we can decorate on properties to make this clear. On the other hand, if we really only need the first and last, then in terms of values that are possible, adding @JsNullable to a property means the following:

  • it can be a real value
  • it can be assigned to null
  • it can be assigned to undefined
  • it can be left undefined

The last three are all the same in Java, and JS insists on a distinction between the last two. Matt and I decided that the last two really doesnt matter, as long as you aren't asking the object directly if it has the property defined on it, but just reading or writing to the property.

But null vs undefined still matters - if it is allowed to be null but not undefined, then TS will tell you that a foo === null check is correct, when you actually want a foo == null check to normalize out the undefined value - and vice versa. Assuming we support "nullable properties are automatically optional" we can drop the undefined from the union, but we can't/shouldn't drop the null, or nulls could escape.

For Java/GWT's part, there is no difference between a field that hasn't been initialized and one that has been initialized to null, so anywhere we handle a null, we have to have some kind of undefined handling too.

Comment on lines +20 to 21
@JsNullable
public int colspan;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This declares them as:

colspan:number|null|undefined;

I think colspan?:number would be more accurate; is there any way to make that notation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not at this time, we'll have that ready soon though.

import jsinterop.base.JsPropertyMap;

import java.util.Map;

@JsType(name = "SeriesDescriptor", namespace = "dh.plot")
public class JsSeriesDescriptor {
// TODO (deephaven-core#3442) change to some kind of String+int union type
public String plotStyle;
public String name;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of the properties on the SeriesDescriptor should be optional.

@niloc132
Copy link
Member Author

niloc132 commented Apr 4, 2023

My goal here isn't to suggest that this is complete, but that we've gotten most of the big changes in, and can follow up with optionals, unions, generics, and javadoc. This patch gets merge conflicts at least once per week, if not more - merging it sooner than later will ensure that at least new types are correct, even if we can't switch the UI over to this generated d.ts yet.

@niloc132 niloc132 requested a review from mofojed April 5, 2023 17:10
@niloc132 niloc132 merged commit 528471e into deephaven:main Apr 6, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Apr 6, 2023
@deephaven-internal
Copy link
Contributor

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants