Description
I would like to discuss the current best way to use typing features of TypeScript with Emscripten. If you are looking for a WebIDL -> TypeScript .d.ts converter for C++ application specifically, you may refer to the above two issues.
I recently found @types/emscripten from NPM and I spent a few hours to figure out how to integrate it with my Emscripten project and contributed the package a little bit too. The .d.ts
typing file can be found here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/emscripten/index.d.ts
Suppose I make add.c
like this:
// add.c
int add (int a, int b) {
return a + b;
}
Two ways I have figured out:
add--post-js.ts
add.d.ts
+add--post-js.js
In my case I found option 2 is better. Will be explained later.
1. add--post-js.ts
add—post-js.ts
/// <reference types="emscripten" />
/** Above will import declarations from @types/emscripten, including Module etc. */
// This will merge to the existing EmscriptenModule interface from @types/emscripten
// If this doesn't work, try globalThis.EmscriptenModule instead.
interface EmscriptenModule {
// Module.cwrap() will be available by doing this.
// Requires -s "EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap']"
cwrap: typeof cwrap;
// Exported from add.cpp
// Requires "EXPORTED_FUNCTIONS=['_add']"
_add(number, number): number;
// or using cwrap. See below
add(number, number): number;
}
Module['onRuntimeInitialized'] = function() {
// Just Module._add() will work, but I'm just demonstrating usage of cwrap()
Module['add'] = cwrap('add', 'number', ['number', 'number']);
}
2. add.d.ts
+ add--post-js.js
add.d.ts
/// <reference types="emscripten" />
/** Above will import declarations from @types/emscripten, including Module etc. */
// This will merge to the existing EmscriptenModule interface from @types/emscripten
// If this doesn't work, try globalThis.EmscriptenModule instead.
export interface AddModule extends EmscriptenModule {
// Module.cwrap() will be available by doing this.
// Requires -s "EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap']"
cwrap: typeof cwrap;
// Exported from add.cpp
// Requires "EXPORTED_FUNCTIONS=['_add']"
_add(number, number): number;
// or using cwrap. See below
add(number, number): number;
}
// Declare any name
declare const addModule: AddModule;
// Only for -s MODULARIZE=1
export = addModule;
// Only for -s MODULARIZE=1 -s EXPORT_ES6=1
export default addModule;
add—post-js.js
/// <reference types="emscripten" />
/** Above will import declarations from @types/emscripten, including Module etc. */
/** It is not .ts file but declaring reference will pass TypeScript Check. */
Module['onRuntimeInitialized'] = function() {
// Just Module._add() will work, but I'm just demontrating usage of cwrap
Module['add'] = cwrap('add', 'number', ['number', 'number']);
}
I know, both of them don't particularly look pretty but they are the cleanest ones so far.
I found that the second one is better for two reasons: add--post-js.ts
file must be compiled to js in order to work with emcc
command. And there are problems when you want to use export
statement because -s MODULARIZE=1
creates another export statement automatically.
Please share any better tricks if you have one. Also you will notice that @types/emscripten is not complete when you look at the source code it would be great if anyone can make the package better.
Thanks :)