cincheo / jsweet

A Java to JavaScript transpiler.
http://www.jsweet.org
Other
1.46k stars 160 forks source link

TS Interface constraining any number of attributes. Equivalent? #116

Closed rupebac closed 8 years ago

rupebac commented 8 years ago

Hi,

I am trying to convert some TypeScript code to JSweet so that I can reuse it in Java as well, but I have a problem. I have got an interface such as:

export interface FieldsContainer {

}

How could I do the JSweet equivalent? I thought on putting a getter instead, but it is not quite the same, any other alternative?

Thanks!

renaudpawlak commented 8 years ago

Umm... I am unsure... if it is the actual syntax, it looks like an indexed access... What is F by the way?

Did you try:

@jsweet.lang.Interface
public class FieldsContainer {
   F $get(String fieldName);
}
rupebac commented 8 years ago

Yes, exactly, it is an indexed access. So, FieldsContainer is a javascript object containing many Fields (F) as members of the object.

I just tried what you propose (which btw, I guess you mean an interface, not a class ), and it simply gets replaced with a TypeScript interface containing that method.

renaudpawlak commented 8 years ago

Ok. It seems that version 1.0.0 has a limitation. It does not understand $get definitions in your own classes/interfaces. So you need to switch to the 1.1.0-SNAPSHOT version (even for the Maven plugin if you use it). Version 1.1.0 will be released very soon... I promise.

However, I am pretty sure that you don't need to switch to the latest snapshot and just use $get method without having to declare it in your classes/interface. First, you can make your classes extend the jsweet.lang.Object, which defines a generic $get method, which allows indexed access on any object. Second (even simpler), you can use the jsweet.util.Globals.$get helper method to perform indexed accesses on any object (see also the $set counterparts). Basically, you usually don't need to define indexed access methods on your own classes/interfaces because you can use these generic ones.

As an example:

import static jsweet.util.Gobals.$get;
...
// indexed access
F myValue = (F)$get(myObject, "myField");

Here are more notes about your remarks.

In JSweet, you can define interfaces either with plain Java interfaces, either with classes annotated with @Interface. However, you are right, I forgot the native modifier, which is important for having a valid Java definition. Most of the time I use the @Interface annotation because it is more flexible (it allows fields in interfaces and to create objects out of the interfaces). But it actually depends on what you are trying to achieve.

With the current snapshot of JSweet (1.1.0-SNAPHOT), overriding the indexed accesses in your own classes/interfaces is possible. The following definitions:

@Interface
class Test {
    public native F $get(String name);
}

interface Test {
    public F $get(String name);
}

Will both generate:

export interface Test {
    [name : string]: F;
}