google / google/jsinterop-generator

`@record` types with no members have no create() method

Open
#51 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
85
Forks
24
PR merge metrics
No merged PRs in 30d

Description

Steps to reproduce, create a record type with no members.

```javascript
/**
* @record
*/
function MyRecord() {}
```
Expected, a Java interface with a static `create()` method. Actual output is a Java interface with no contents.

--

While this might seem like a weird edge case, there are at least two ways that this comes up. First, when tsickle generates externs from typescript where a type is re-exported in another file, tsickle will generate a new type that extends the existing type. Second, a record type that extends from two other record types, but doesn't contribute new fields.

```
/**
* @record
*/
function ParentRecordA() {}

/**
* @type {string}
*/
ParentRecordA.prototype.name;

/**
* @record
*/
function ParentRecordB() {}

/**
* @type {number}
*/
ParentRecordB.prototype.value;

/**
* @record
* @extends {ParentRecordA}
* @extends {ParentRecordB}
*/
function ChildRecord() {}
```

Expected Java output,
```
@JsType(isNative = true, namespace = JsPackage.GLOBAL)
public interface ChildRecord extends ParentRecordA, ParentRecordB {
@JsOverlay
static ChildRecord create() {
return Js.uncheckedCast(JsPropertyMap.of());
}
}
```

Actual Java output
```
@JsType(isNative = true, namespace = JsPackage.GLOBAL)
public interface ChildRecord extends ParentRecordA, ParentRecordB { }
```

An easy workaround is to just create an instance of a supertype, or just a plain `JsObject.create(null)` or `JsPropertyMap.of()`, then wrap in a cast as the usual implementation does. But this isn't expected to be the correct way, since all other records get a generated factory method.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.