Library Mode
Library mode generates declarations for your assembly without duplicating types from existing packages.
Use Case
When building a TypeScript package with .NET bindings:
- BCL types come from
@tsonic/dotnet(published package) - Runtime primitives come from
@tsonic/core(installed as a dependency;@tsonic/dotnetimports these types) - Your types are generated fresh with references to these packages
Workflow
Step 1: Have BCL Types
Either generate BCL or use the published package:
# Option A: Generate BCL yourself
npx tsbindgen generate -d $DOTNET_RUNTIME -o ./bcl-types
# Option B: Use published package
npm install @tsonic/dotnet
# Types are in node_modules/@tsonic/dotnet
Step 2: Generate Your Library
npx tsbindgen generate \
-a ./MyLibrary.dll \
-d $DOTNET_RUNTIME \
-o ./my-lib-types \
--lib ./bcl-types
What --lib Does
- Skips library types - Types from assemblies in
--libpackages are not regenerated - Generates imports - Cross-references become import statements to the library package
- Validates references - Ensures all referenced types exist in one of the
--libpackages - Merges contracts - Multiple
--liboptions combine their type registries
Multiple Library References
You can specify --lib multiple times to reference several packages:
npx tsbindgen generate \
-a ./MyLibrary.dll \
-d $DOTNET_RUNTIME \
-o ./my-lib-types \
--lib ./node_modules/@tsonic/dotnet \
--lib ./node_modules/@tsonic/microsoft-extensions
When a type is referenced, tsbindgen checks each library in order and imports from the first one that provides it. This allows layered package structures:
@tsonic/dotnet- .NET BCL types@tsonic/microsoft-extensions- Additional shared framework assemblies (e.g., DI/Logging/Config)- Your package - Your types (references both)
Output Structure
Without --lib:
output/
+-- System.d.ts
+-- System.js
+-- System/
+-- System.Collections.Generic.d.ts
+-- System.Collections.Generic.js
+-- System.Collections.Generic/
+-- MyNamespace.d.ts
+-- MyNamespace.js
+-- MyNamespace/
+-- ... (all emitted namespaces)
With --lib ./bcl-types:
output/
+-- MyNamespace.d.ts
+-- MyNamespace.js
+-- MyNamespace/
+-- bindings.json
+-- internal/
+-- index.d.ts
BCL references become imports:
// In MyNamespace/internal/index.d.ts
import type { List_1 } from '@tsonic/dotnet/System.Collections.Generic.js';
import type { Exception } from '@tsonic/dotnet/System.js';
export interface MyClass$instance {
GetItems(): List_1<string>;
GetError(): Exception;
}
Example: Custom Library
Your C# Library
// MyLibrary/MyClass.cs
namespace MyCompany.Utils
{
public class DataProcessor
{
public List<string> Process(string[] items) { ... }
public void HandleError(Exception ex) { ... }
}
}
Generate
npx tsbindgen generate \
-a ./MyLibrary.dll \
-d $DOTNET_RUNTIME \
-o ./my-lib-types \
--lib ./node_modules/@tsonic/dotnet
Output
// my-lib-types/MyCompany.Utils/internal/index.d.ts
import type { List_1 } from '@tsonic/dotnet/System.Collections.Generic.js';
import type { Exception } from '@tsonic/dotnet/System.js';
export interface DataProcessor$instance {
Process(items: string[]): List_1<string>;
HandleError(ex: Exception): void;
}
export declare const DataProcessor: {
new (): DataProcessor;
};
export type DataProcessor = DataProcessor$instance;
Validation Errors
Library mode performs strict validation:
| Error | Description | Fix |
|---|---|---|
LIB001 |
Type not found in library | Ensure BCL is complete |
LIB002 |
Member signature mismatch | Regenerate with the same inputs |
LIB003 |
Generic constraint mismatch | Check constraint compatibility |
Best Practices
- Keep BCL updated - Regenerate when .NET version changes
- Pin versions - Use a specific
@tsonic/dotnetversion inpackage.json - Regenerate together - Generate your library and its referenced libs with the same dotnet/toolchain inputs