A native TypeScript declaration (.d.ts) bundler built on Oxc
See the code
ty(pe) + pack — pack your TypeScript declarations.
A native TypeScript declaration (.d.ts) bundler built on Oxc.
Bundles one or more .d.ts (or .ts) entry points into a single output file using a three-stage AST pipeline — no TypeScript compiler required.
tsc dependencySymbolId-level analysis to avoid name collisions across modules.d.ts sourcesexport = syntax for CommonJS default exports.ts entry points — automatically generates declarations via Oxc's IsolatedDeclarations transform (requires isolatedDeclarations in tsconfig)The bundler runs a three-stage pipeline:
.d.ts files (or .ts files via IsolatedDeclarations) with oxc_parser, build semantic scoping via oxc_semantic, resolve imports with oxc_resolver, and produce a topologically sorted module graphimport() types, wrap namespace imports, filter unused declarations, and emit the bundled output with optional source maps.ts entry pointsIn addition to .d.ts files, typack accepts .ts entry points directly. When a .ts file is encountered (as an entry or as a dependency), it is transformed to .d.ts in-memory using Oxc's IsolatedDeclarations transform before bundling.
This means your .ts source must conform to TypeScript's isolatedDeclarations constraints — primarily, all exported functions and variables need explicit return/type annotations.
typack reads tsconfig.json to pick up two relevant settings. By default it walks up from cwd to find the nearest tsconfig.json, or you can pass an explicit path via --tsconfig (CLI) or the tsconfig option (API):
| tsconfig field | Effect |
|---|---|
isolatedDeclarations | Suppresses a warning when .ts files are used without this enabled |
stripInternal | Excludes declarations marked with /** @internal */ from the output |
A warning is emitted if .ts files are used but isolatedDeclarations is not enabled in tsconfig. The transform still runs — any errors from non-conforming code will surface naturally.
[dependencies]
typack = "0.1.0"
use typack::{TypackBundler, TypackOptions};
let result = TypackBundler::bundle(&TypackOptions {
input: vec!["types/index.d.ts".to_string()],
cwd: std::env::current_dir().unwrap(),
external: vec!["react".to_string()],
sourcemap: true,
..Default::default()
});
match result {
Ok(bundle) => {
for output in &bundle.output {
println!("{}", output.code);
if let Some(map) = &output.map {
// write source map to disk
let _ = map;
}
}
for warning in &bundle.warnings {
eprintln!("warning: {warning}");
}
}
Err(diagnostics) => {
for diagnostic in diagnostics {
eprintln!("error: {diagnostic}");
}
}
}
TypackOptions
| Field | Type | Default | Description |
|---|---|---|---|
input | Vec<String> | [] | Entry .d.ts or .ts file paths to bundle |
external | Vec<String> | [] | Module specifiers to keep as external imports |
cwd | PathBuf | "." | Working directory for relative path resolution |
sourcemap | bool | false | Generate source map (.d.ts.map) |
cjs_default | bool | false | Emit export = for single default export |
tsconfig | Option<PathBuf> | None | Path to tsconfig.json (default: auto-detect) |
BundleResult
| Field | Type | Description |
|---|---|---|
output | Vec<BundleOutput> | Per-entry bundled output |
warnings | Vec<OxcDiagnostic> | Non-fatal warnings |
BundleOutput
| Field | Type | Description |
|---|---|---|
code | String | The bundled .d.ts output |
map | Option<SourceMap> | Source map (when sourcemap: true) |
Requires the cli feature:
cargo run --features cli -- [OPTIONS] <ENTRY>...
<ENTRY>... Entry .d.ts or .ts files to bundle
--external <SPEC> Module specifiers to keep external (repeatable)
--cwd <DIR> Working directory (default: current directory)
--sourcemap Generate source map (.d.ts.map)
--cjs-default Emit `export =` for single default export
-o, --outfile <PATH> Write output to file instead of stdout (single entry only)
--outdir <DIR> Write outputs to directory (one per entry)
--tsconfig <PATH> Path to tsconfig.json (default: auto-detect from cwd)
# Bundle .d.ts entry
cargo run --features cli -- \
--external react \
--external react-dom \
--sourcemap \
-o dist/index.d.ts \
types/index.d.ts
# Bundle .ts entry (requires isolatedDeclarations in tsconfig.json)
cargo run --features cli -- \
-o dist/index.d.ts \
src/index.ts
npm install typack
Requires Node.js >= 20. Pre-built binaries are available for:
| Platform | Architectures |
|---|---|
| macOS | aarch64, x86_64 |
| Linux (glibc) | aarch64, x86_64 |
| Linux (musl) | aarch64, x86_64 |
| Windows | aarch64, x86_64 |
import { bundle } from "typack";
const result = bundle({
input: ["types/index.d.ts"], // or ["src/index.ts"] for .ts entry
cwd: process.cwd(),
external: ["react"],
sourcemap: true,
});
for (const output of result.output) {
console.log(output.code);
if (output.map) {
// output.map is a JSON string
fs.writeFileSync("dist/index.d.ts.map", output.map);
}
}
for (const warning of result.warnings) {
console.warn(`warning: ${warning.message}`);
}
interface BundleDtsOptions {
/** Entry `.d.ts` or `.ts` file paths to bundle */
input: Array<string>;
external?: Array<string>;
cwd?: string;
sourcemap?: boolean;
cjsDefault?: boolean;
tsconfig?: string;
}
interface BundleDtsOutput {
code: string;
map?: string;
}
interface BundleDtsResult {
output: Array<BundleDtsOutput>;
warnings: Array<BundleDtsDiagnostic>;
}
interface BundleDtsDiagnostic {
message: string;
file?: string;
span?: Array<number>;
severity: string;
}
Module resolution uses oxc_resolver with the "types" export condition enabled, respecting package.json exports and conditional exports.
external list are preserved in the output (exact match)import "pkg" statements are preserved when the target contains global or module augmentations/// <reference path="..." /> directives are collected and deduplicatedjust ready # fmt + check + test + lint
just fmt # cargo fmt
just check # cargo check
just test # cargo test
just lint # cargo clippy
tests/fixtures/, each with an index.d.ts input and snapshot.d.ts expected outputThe three-stage architecture (scan, link, generate) is inspired by Rolldown. Test fixtures were adapted from rolldown-plugin-dts and rollup-plugin-dts.
4,839 followers · starred Mar 2026
8,408 followers · starred Mar 2026
912 followers · starred Mar 2026
1,860 followers · starred Mar 2026
A native TypeScript declaration (.d.ts) bundler built on Oxc
See the code
ty(pe) + pack — pack your TypeScript declarations.
A native TypeScript declaration (.d.ts) bundler built on Oxc.
Bundles one or more .d.ts (or .ts) entry points into a single output file using a three-stage AST pipeline — no TypeScript compiler required.
tsc dependencySymbolId-level analysis to avoid name collisions across modules.d.ts sourcesexport = syntax for CommonJS default exports.ts entry points — automatically generates declarations via Oxc's IsolatedDeclarations transform (requires isolatedDeclarations in tsconfig)The bundler runs a three-stage pipeline:
.d.ts files (or .ts files via IsolatedDeclarations) with oxc_parser, build semantic scoping via oxc_semantic, resolve imports with oxc_resolver, and produce a topologically sorted module graphimport() types, wrap namespace imports, filter unused declarations, and emit the bundled output with optional source maps.ts entry pointsIn addition to .d.ts files, typack accepts .ts entry points directly. When a .ts file is encountered (as an entry or as a dependency), it is transformed to .d.ts in-memory using Oxc's IsolatedDeclarations transform before bundling.
This means your .ts source must conform to TypeScript's isolatedDeclarations constraints — primarily, all exported functions and variables need explicit return/type annotations.
typack reads tsconfig.json to pick up two relevant settings. By default it walks up from cwd to find the nearest tsconfig.json, or you can pass an explicit path via --tsconfig (CLI) or the tsconfig option (API):
| tsconfig field | Effect |
|---|---|
isolatedDeclarations | Suppresses a warning when .ts files are used without this enabled |
stripInternal | Excludes declarations marked with /** @internal */ from the output |
A warning is emitted if .ts files are used but isolatedDeclarations is not enabled in tsconfig. The transform still runs — any errors from non-conforming code will surface naturally.
[dependencies]
typack = "0.1.0"
use typack::{TypackBundler, TypackOptions};
let result = TypackBundler::bundle(&TypackOptions {
input: vec!["types/index.d.ts".to_string()],
cwd: std::env::current_dir().unwrap(),
external: vec!["react".to_string()],
sourcemap: true,
..Default::default()
});
match result {
Ok(bundle) => {
for output in &bundle.output {
println!("{}", output.code);
if let Some(map) = &output.map {
// write source map to disk
let _ = map;
}
}
for warning in &bundle.warnings {
eprintln!("warning: {warning}");
}
}
Err(diagnostics) => {
for diagnostic in diagnostics {
eprintln!("error: {diagnostic}");
}
}
}
TypackOptions
| Field | Type | Default | Description |
|---|---|---|---|
input | Vec<String> | [] | Entry .d.ts or .ts file paths to bundle |
external | Vec<String> | [] | Module specifiers to keep as external imports |
cwd | PathBuf | "." | Working directory for relative path resolution |
sourcemap | bool | false | Generate source map (.d.ts.map) |
cjs_default | bool | false | Emit export = for single default export |
tsconfig | Option<PathBuf> | None | Path to tsconfig.json (default: auto-detect) |
BundleResult
| Field | Type | Description |
|---|---|---|
output | Vec<BundleOutput> | Per-entry bundled output |
warnings | Vec<OxcDiagnostic> | Non-fatal warnings |
BundleOutput
| Field | Type | Description |
|---|---|---|
code | String | The bundled .d.ts output |
map | Option<SourceMap> | Source map (when sourcemap: true) |
Requires the cli feature:
cargo run --features cli -- [OPTIONS] <ENTRY>...
<ENTRY>... Entry .d.ts or .ts files to bundle
--external <SPEC> Module specifiers to keep external (repeatable)
--cwd <DIR> Working directory (default: current directory)
--sourcemap Generate source map (.d.ts.map)
--cjs-default Emit `export =` for single default export
-o, --outfile <PATH> Write output to file instead of stdout (single entry only)
--outdir <DIR> Write outputs to directory (one per entry)
--tsconfig <PATH> Path to tsconfig.json (default: auto-detect from cwd)
# Bundle .d.ts entry
cargo run --features cli -- \
--external react \
--external react-dom \
--sourcemap \
-o dist/index.d.ts \
types/index.d.ts
# Bundle .ts entry (requires isolatedDeclarations in tsconfig.json)
cargo run --features cli -- \
-o dist/index.d.ts \
src/index.ts
npm install typack
Requires Node.js >= 20. Pre-built binaries are available for:
| Platform | Architectures |
|---|---|
| macOS | aarch64, x86_64 |
| Linux (glibc) | aarch64, x86_64 |
| Linux (musl) | aarch64, x86_64 |
| Windows | aarch64, x86_64 |
import { bundle } from "typack";
const result = bundle({
input: ["types/index.d.ts"], // or ["src/index.ts"] for .ts entry
cwd: process.cwd(),
external: ["react"],
sourcemap: true,
});
for (const output of result.output) {
console.log(output.code);
if (output.map) {
// output.map is a JSON string
fs.writeFileSync("dist/index.d.ts.map", output.map);
}
}
for (const warning of result.warnings) {
console.warn(`warning: ${warning.message}`);
}
interface BundleDtsOptions {
/** Entry `.d.ts` or `.ts` file paths to bundle */
input: Array<string>;
external?: Array<string>;
cwd?: string;
sourcemap?: boolean;
cjsDefault?: boolean;
tsconfig?: string;
}
interface BundleDtsOutput {
code: string;
map?: string;
}
interface BundleDtsResult {
output: Array<BundleDtsOutput>;
warnings: Array<BundleDtsDiagnostic>;
}
interface BundleDtsDiagnostic {
message: string;
file?: string;
span?: Array<number>;
severity: string;
}
Module resolution uses oxc_resolver with the "types" export condition enabled, respecting package.json exports and conditional exports.
external list are preserved in the output (exact match)import "pkg" statements are preserved when the target contains global or module augmentations/// <reference path="..." /> directives are collected and deduplicatedjust ready # fmt + check + test + lint
just fmt # cargo fmt
just check # cargo check
just test # cargo test
just lint # cargo clippy
tests/fixtures/, each with an index.d.ts input and snapshot.d.ts expected outputThe three-stage architecture (scan, link, generate) is inspired by Rolldown. Test fixtures were adapted from rolldown-plugin-dts and rollup-plugin-dts.
4,839 followers · starred Mar 2026
8,408 followers · starred Mar 2026
912 followers · starred Mar 2026
1,860 followers · starred Mar 2026