Skip to content

@JsEnum types cannot be used in a union #40

@niloc132

Description

@niloc132

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:

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();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions