google / google/jsinterop-generator
@JsEnum types cannot be used in a union
- Dominant language
- Java
- Stars
- 85
- Forks
- 24
- PR merge metrics
- No merged PRs in 30d
Description
Steps to repro - use an externs file with an enum that is referenced by a union type. Roughly:
```
/**
* @enum {number}
*/
foo.bar.SomeEnum = {
ONE: 0,
TWO: 1,
THREE: 2,
FIVE: 3,
SEVEN: 4
};
/**
* @type {foo.bar.SomeEnum|string}
*/
foo.bar.ObjectWithProperties.prototype.thing;
```
The error is when j2cl tries to transpile the sources into js, it is reported that the union type is attempting an `instanceof` on the enum instead of just treating it like a number (which in this case is all it is).
Easy workaround: rewrite ObjectWithProperties.thing's type to be {number|string}, though that defeats the purpose a bit.
Proposed fix (not having given it great thought): The union type should instanceof based on the type label: in this case, `number`. This seems to be a bit difficult to implement though, since the original `@enum` might be already made into a java type? The `jsinterop.generator.model.Type` instances don't keep track of the type label at this time, so that would need to be added? It could potentially also be helpful in general, j2cl itself could implement `$isInstance` with this knowledge if it were part of the `@JsEnum` annotation?
Easier error reporting option: instead of waiting for j2cl to fail the generated java, something like this could throw when the generator is trying to emit the union's isFoo() method:
```diff --git a/java/jsinterop/generator/visitor/UnionTypeHelperTypeCreator.java b/java/jsinterop/generator/visitor/UnionTypeHelperTypeCreator.java
index b72a70a..c9d2e7b 100644
--- a/java/jsinterop/generator/visitor/UnionTypeHelperTypeCreator.java
+++ b/java/jsinterop/generator/visitor/UnionTypeHelperTypeCreator.java
@@ -262,6 +262,10 @@ public class UnionTypeHelperTypeCreator implements ModelVisitor {
return new ArrayTypeReference(OBJECT);
}
+ if (typeReference.getTypeDeclaration() != null && typeReference.getTypeDeclaration().isEnum()) {
+ throw new IllegalStateException("Can't use @enum in instanceof, so cannot construct union type");
+ }
+
// remove Type parameters
if (typeReference instanceof ParametrizedTypeReference) {
return ((ParametrizedTypeReference) typeReference).getMainType();
```
Contributor guide
Assessment
This issue has not been assessed yet.