This tools takes Typescript definition files (.d.ts
) as input, process them, and then outputs JsInterop
Java types for use within a GWT application.
It is written in Typescript and uses the Typescript compiler to parse definition files.
This tool is really in beta stage, many things can be added to render the generated API more user-friendly.
It is ready enough that people interested by it can try and open issues if needed.
It can be useful for people maintaining interop libraries between Javascript and GWT.
Although I don’t have myself GWT projects to work on anymore, it was a long time since I wanted to try this approach of automatically convert typescript files to Java types. The experience has proved to be doable with quite a good success (for example after converting automatically the Angular 4 API to JsInterop, I get 20 or so java errors in the generated API, which requires something like 20 minutes of my time to fix).
If you are interested in contributing this project, either because you like it or because it is useful to you, please feel welcome, I will help you in that sense.
The next commits on this project will surely be code documentation so that you are more welcomed to contribute !
This is a working GWT application code using the JsInterop classes generated by this tool from the Typescript description of the DOM api :
...
import static fr.lteconsulting.jsinterop.browser.GlobalScope.*;
public void onModuleLoad() {
HTMLButtonElement button = (HTMLButtonElement) document.createElement("button");
button.innerHTML = "<b>Click me</b>";
button.style.color = "red";
document.body.appendChild(button);
button.addEventListener("click", console::log);
console.log(document);
setInterval(event -> console.log("a second has gone"), 1000);
// Promise...
wait(2500)
.then(value -> Promise.resolve(42))
.then(value -> Promise.resolve(value > 10 ? "More than 10" : "Less than 10"))
.then(value -> {
console.log(value);
return null;
});
}
// And the wait(int duration) method :
private Promise<Void> wait(int duration) {
return new Promise<>((resolver, rejecter) -> setTimeout(evt -> resolver.call(null), duration));
}
Compile it with npm install
then tsc
.
Then launch it with nodejs target/main.js CONFIG_FILE
.
Sample configuration files can be found at the root directory (ts2java.browser.config.json
for instance).
The browser environment (the Web API), when using the default lib.es6.d.ts
file that is the Typescript description of the Web API for normal Web programming, is generated as in this url : https://github.com/ltearno/typescript2java/tree/master/apis/browser-api/src/main/java/fr/lteconsulting/jsinterop/browser.
The Angular 4 API has also been transcribed to JsInterop with this tool. The result is here : https://github.com/ltearno/angular2-gwt/tree/dev/src/main/java/fr/lteconsulting/jsinterop/ng.
Here is a configuration sample :
{
"sourceRootDir": "./tsd",
"baseJavaPackage": "fr.lteconsulting.jsinterop",
"defaultJavaPackage": "browser",
"javaPackages": {},
"processInternalTypes": false,
"outputDirectory": "./out/src/main/java",
"renaming": {
"fr.lteconsulting.jsinterop.browser": {
"IDBValidKey_UnionOfDateAndIDBArrayKeyAndNumberAndString": "IDBValidKey",
"AVeryLongClassName": "MyPreferredClassName"
}
},
"adding": {
"fr.lteconsulting.jsinterop.browser": {
"Array": "added-to-array.txt" (1)
}
},
"removing": {
"fr.lteconsulting.jsinterop.browser": {
"Array": [
"static Array of(T)" (2)
]
}
}
}
-
The
added-to-array.txt
file content will be added to theArray
class. -
The static
of(T value)
method will not be generated.
Here is the list of options :
A Java package that will be appended to the baseJavaPackage
when no js namespace is found for a js type.
A mapping from the source directories to the corresponding java package (appended to baseJavaPackage
).
Base directory for output. Of course, classes files will be put in their correct sub-directories.
Sometimes the names outputed by the tool are not so handy (especially with many types unions which generate very long names).
This configuration is an associative object organized by package name then by class name.
You can choose the name to which those classes will be renamed.
Sometimes, you want some code to be added in the generated classes.
This is the configuration to use. It is organized by package then name. The specified text is the name of a text file from which the content will be added in the corresponding classes.
Written in Typescript, executes on NodeJS.
It uses the Typescript compiler to get a type AST from the .d.ts
files.
Then those TS types are mapped to a graph of low-level almost-Java-types.
Then micro-transformations are applied on this graph to make the generated Java classes convenient.
The Typescript type system is very rich, in fact far more rich than Java’s one. So there are always different choices for the ts to java mapping policy. This tool tries to take the most user-friendly approach.
The aim is to get a good code automatically, although knowing that some edge cases may be very difficult to handle. During the development of this tool, my objective was to transcript the Angular 4 API and get a result which would be almost OK and not requiring more than 20 minutes of work for polishing. In the end, this objective has been surpassed by large!
There some few things to add :
-
Allow to iterate with the Java
for
over Arrays, Set, Map and all other Iterables ! -
Linking to already generated APIs like Elemental, …
-
Many other things…