well-typed mbt(i) to d.ts converter and utils
Dependencies
deno install -Afg @mizchi/mbts --name mbts
# TODO: npm# As a CLI tool
pnpm add mbts
# Or use directly
npx mbts --help# Create a new project
mbts new myapp --user myname
cd myapp
moon update
# Build and generate TypeScript definitions
mbts build .
# Use from JavaScript
node -e "const m = require('./target/js/release/build/myapp/myapp.js'); console.log(m.hello())"mbts new <pkgname> --user <username># Create project
mbts new myapp --user myname
# Without --user (uses "username" as default with warning)
mbts new myappmbts build <path># Build current directory
mbts build .
# Build specific directory
mbts build examples
# With options
mbts build . --out js --naming camelCasembts link <path># Update exports after running 'moon info'
moon info
mbts link .
# Multiple targets
mbts link . --targets js,wasm-gc
# Exclude methods
mbts link . --no-methods
# Dry run
mbts link . --dry-runmbts dts <src> [--out <dir>]# Generate .d.ts in same directory
mbts dts .
# Output to different directory
mbts dts src --out js
# Wrap in namespace
mbts dts src --namespace
# Include runtime type preamble
mbts dts src --preamble
# Convert function names to camelCase
mbts dts src --naming camelCasembts mbt <file.d.ts> [options]# Basic conversion
mbts mbt lib.d.ts
# Specify output directory and package name
mbts mbt lib.d.ts --out src --package myapp
# Also generate .mbti interface file
mbts mbt lib.d.ts --mbti| MoonBit | TypeScript |
|---|---|
| String | string |
| Int, UInt, Float, Double | number |
| Bool | boolean |
| Unit | void |
| Bytes | Uint8Array |
| BigInt | bigint |
| Array[T] | Array<T> |
| Map[K, V] | Map<K, V> |
| Json | any |
| T? / Option[T] | T \| undefined |
| (A, B, C) | [A, B, C] |
| TypeScript | MoonBit |
|---|---|
| string | String |
| number | Int |
| boolean | Bool |
| void | Unit |
| Uint8Array | Bytes |
| bigint | BigInt |
| T[] / Array<T> | Array[T] |
| Map<K, V> | @collection.JsMap[K, V] |
| Set<T> | @collection.JsSet[T] |
| Promise<T> | @js.Promise[T] |
| T \| undefined | T? |
| any / unknown | Json |
// MoonBit
pub struct User {
name : String
age : Int
mut email : String
}// TypeScript
export interface User {
readonly name: string;
readonly age: number;
email: string;
}// MoonBit
pub enum Status {
Pending
Active
Done
}// TypeScript (Discriminated Union)
export interface Status_Pending { readonly $tag: "Pending"; }
export interface Status_Active { readonly $tag: "Active"; }
export interface Status_Done { readonly $tag: "Done"; }
export type Status = Status_Pending | Status_Active | Status_Done;// MoonBit - Generic function (needs wrapper for JS export)
pub fn[T] identity(value : T) -> T {
value
}
// FFI functions must use @js.Any (no type parameters allowed)
extern "js" fn Box::new(value : @js.Any) -> Box[@js.Any] =
#| (v) => ({ value: v })// Auto-generated
pub fn __jsglue_identity(arg0 : @js.Any) -> @js.Any {
identity(arg0)
}| MoonBit | TypeScript (default) | TypeScript (--naming camelCase) |
|---|---|---|
| get_user_name | get_user_name | getUserName |
| Type::method | type$method | type$method |
pub struct User {
id : Int // immutable
mut name : String // mutable
}export interface User {
readonly id: number; // readonly (immutable)
name: string; // writable (mut)
}pub enum Result[T, E] {
Ok(T)
Err(E)
}export interface Result_Ok<T> { readonly $tag: "Ok"; readonly $0: T; }
export interface Result_Err<E> { readonly $tag: "Err"; readonly $0: E; }
export type Result<T, E> = Result_Ok<T> | Result_Err<E>;pub fn find(id : Int) -> User?export function find(id: number): User | undefined;pub fn get_pair() -> (Int, String)export function get_pair(): [number, string];pub fn User::new(name : String) -> User
pub fn User::greet(self : User) -> Stringexport function user$new(name: string): User;
export function user$greet(self: User): string;import { generateDts } from "mbts";
const mbtiContent = `
package "myapp"
pub struct User {
name : String
age : Int
}
pub fn get_user(id : Int) -> User
`;
const dts = generateDts(mbtiContent, "myapp.mbti");import { parseDts, generateMbt, generateMbti } from "mbts";
const dtsContent = `
export interface User {
name: string;
age: number;
}
export function createUser(name: string): User;
`;
const binding = parseDts(dtsContent, "lib.d.ts", { packageName: "myapp" });
const mbt = generateMbt(binding);
const mbti = generateMbti(binding);# Install dependencies
moon update
pnpm install
# Build CLI
pnpm build:cli
# Run tests
moon test
pnpm test.mbti (parsed) → AST → analyze generics → generate __jsglue.mbtpub struct MbtField {
name : String
type_ : String
mutable : Bool
}pub struct MbtMethod {
name : String
js_name : String
}pub struct MbtParam {
name : String
type_ : String
optional : Bool
}pub struct MbtType {
name : String
kind : MbtTypeKind
fields : Array[MbtField]
variants : Array[MbtVariant]
type_params : Array[String]
js_name : String
}fn generate_dts_from_mbt(content : String, filename : String) -> Stringfn package_to_namespace(package_name : String) -> Stringfn preprocess_mbti(content : String) -> Stringwell-typed mbt(i) to d.ts converter and utils
Dependencies