@siyavuyachagi/typesharp
v0.1.0
Published
Generate TypeScript types from C# models with TypeSharp attribute
Downloads
117
Maintainers
Readme
TypeSharp
Generate TypeScript types from C# models with ease! TypeSharp scans your ASP.NET Core projects and automatically generates TypeScript interfaces from your C# classes decorated with the [TypeSharp] attribute.
Features
✨ Automatic Type Generation – Convert C# models to TypeScript interfaces
🎯 Custom Attribute Targeting – Use [TypeSharp] or any custom attribute
🔄 Nullable Support – string? → string | null
📦 Collection Handling – Supports List<T>, IEnumerable<T>, arrays and generic collections
🧬 Generic Types – Preserves generic type definitions like Response<T> → Response<T>
🧬 Inheritance – Preserves class inheritance using extends
🎨 Naming Conventions – Convert property names (camel, pascal, snake, kebab)
📁 Flexible Output – Single file or multiple files
🔢 Enum Support – Converts C# enums to TypeScript string enums
🗂️ File Grouping – Preserves C# file organization (multiple classes per file stay together)
How TypeSharp Compares
This is not an OpenApi-based tool ! | Feature | TypeSharp | NSwag | openapi-typescript | TypeGen | | --------------------- | --------- | ----- | ------------------ | ------- | | Direct C# parsing | ✅ | ❌ | ❌ | ✅ | | Attribute targeting | ✅ | ⚠️ | ❌ | ⚠️ | | Non-API models | ✅ | ❌ | ❌ | ✅ | | Generics preserved | ✅ | ⚠️ | ⚠️ | ⚠️ | | File grouping | ✅ | ❌ | ❌ | ❌ | | Naming control | ✅ | ⚠️ | ⚠️ | ❌ | | API client generation | ❌ | ✅ | ❌ | ❌ |
For more docs/why-typesharp
Installation
npm install -D @siyavuyachagi/typesharpQuick Start
1. Create an attribute to target
In your target project create the following attribute (TypeSharp)
namespace YourProject.Attribute
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum)]
public class TypeSharpAttribute : Attribute { }
}2. Decorate your C# models or DTOs
[TypeSharp]
public class User
{
public int Id { get; set; }
public string? Name { get; set; }
public string Email { get; set; }
public List<UserRole> Roles { get; set; }
public List<string> Permissions { get; set; }
public DateTime CreatedAt { get; set; }
}
[TypeSharp]
public enum UserRole
{
Admin,
User,
Guest
}
[TypeSharp]
public class ApiResponse<T>
{
public bool Success { get; set; }
public string? Message { get; set; }
public T Data { get; set; }
public List<string> Errors { get; set; }
}3. Create a configuration file
In your frontend end project run the following script
# Create TypeScript config
npx typesharp init
# ----- OR -------
# Create JSON config (default)
npx typesharp init --format json
# Create TypeScript config
npx typesharp init --format ts
# Create JavaScript config
npx typesharp init --format js
This creates typesharp.config.json:
{
"projectFile": [
"C:/Users/User/Desktop/MyApp/Api/Api.csproj",
"C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"
],
"outputPath": "./app/types",
"targetAnnotation": "TypeSharp",
"singleOutputFile": false,
"fileNamingConvention": "kebab",
"namingConvention": "camel"
}4. Generate TypeScript types
npx typesharp
# ----- OR -------
npx typesharp generate
# or with custom config
npx typesharp generate --config ./custom-config.tsOutput (app/types/user.ts):
/**
* Auto-generated by TypeSharp
* Generated at: 2024-12-12T10:30:00.000Z
* Do not edit this file manually
*/
export interface User {
id: number;
name: string | null;
email: string;
roles: UserRole[];
permissions: string[];
createdAt: string;
}Output (app/types/user-role.ts):
/**
* Auto-generated by TypeSharp
* Generated at: 2024-12-12T10:30:00.000Z
* Do not edit this file manually
*/
export enum UserRole {
Admin = "Admin",
User = "User",
Guest = "Guest",
}Output (app/types/api-response.ts):
/**
* Auto-generated by TypeSharp
* Generated at: 2024-12-12T10:30:00.000Z
* Do not edit this file manually
*/
export interface ApiResponse<T> {
success: boolean;
message: string | null;
data: T;
errors: string[];
}For more advanced usage docs/usage
Configuration
1. Configuration Options
| Option | Type | Default | Description |
| ---------------------- | ---------- | ------------- | ------------------------------------------------ |
| projectFiles | string[] | required | Full path(s) to your C# .csproj file |
| outputPath | string | required | Where to generate TypeScript files |
| targetAnnotation | string | 'TypeSharp' | C# attribute name to look for |
| singleOutputFile | boolean | false | Generate one file or multiple files (see below) |
| fileNamingConvention | string | 'kebab' | File naming: kebab, camel, pascal, snake |
| namingConvention | string | 'camel' | Property naming: camel, pascal, snake |
| fileSuffix | string | optional | Suffix for file names: user-dto.ts |
2. Output File Behavior
TypeSharp preserves your C# file organization. Here's how it works:
| C# File Structure | singleOutputFile: false | singleOutputFile: true |
| ---------------------------------------------------------- | ------------------------------------------------ | ------------------------- |
| One class per fileUser.cs → 1 class | user.ts (1 interface) | All classes in types.ts |
| Multiple classes per fileUserDtos.cs → 3 classes | user-dtos.ts (3 interfaces) | All classes in types.ts |
| Mixed structureVarious C# files | Each C# file → 1 TS file(preserves grouping) | All classes in types.ts |
Example:
C# Structure: TypeScript Output (singleOutputFile: false):
Backend/ src/types/
├── DTOs/ └── DTOs/
│ ├── UserDtos.cs │ ├── user-dtos.ts ← All 3 classes together
│ │ ├── UserCreateDto │ └── product-dtos.ts ← All 2 classes together
│ │ ├── UserUpdateDto
│ │ └── UserResponseDto
│ └── ProductDtos.cs
│ ├── ProductDto
│ └── ProductCreateDtoThis means if you organize related DTOs in one C# file, they'll stay together in the generated TypeScript file! 🎯
3. Configuration File Formats
TypeSharp supports multiple configuration formats:
JSON (typesharp.config.json): (recommended)
{
"projectFiles": ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
"outputPath": "./src/types"
}TypeScript (typesharp.config.ts):
import { TypeSharpConfig } from "typesharp";
const config: TypeSharpConfig = {
projectFiles: ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
outputPath: "./src/types",
};
export default config;JavaScript (typesharp.config.js):
module.exports = {
projectFiles: ["C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"],
outputPath: "./src/types",
};Usage in package.json
Add TypeSharp to your build scripts:
{
"scripts": {
"generate-types": "typesharp",
"dev": "typesharp && nuxt dev",
"build": "typesharp && nuxt build"
}
}Advanced Examples
1. With Inheritance
C#:
[TypeSharp]
public class BaseEntity
{
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
}
[TypeSharp]
public class Product : BaseEntity
{
public string Name { get; set; }
public decimal Price { get; set; }
}Generated TypeScript:
export interface BaseEntity {
id: number;
createdAt: string;
}
export interface Product extends BaseEntity {
name: string;
price: number;
}2. Single Output File
Config:
const config: TypeSharpConfig = {
projectFile: "./Backend/Backend.csproj",
outputPath: "./src/types",
singleOutputFile: true,
};All types will be generated in src/types/index.ts
3. Custom Naming Conventions
Config:
const config: TypeSharpConfig = {
projectFile: "./Backend/Backend.csproj",
outputPath: "./src/types",
fileNamingConvention: "snake", // user_model.ts
namingConvention: "pascal", // UserName, not userName
};Type Mappings
| C# Type | TypeScript Type |
| ------------------------------------------- | ---------------- |
| string | string |
| int, long, double, float, decimal | number |
| bool | boolean |
| DateTime, DateOnly, TimeOnly | string |
| Guid | string |
| List<T>, IEnumerable<T>, T[] | T[] |
| string? | string \| null |
Programmatic Usage
You can also use TypeSharp programmatically:
import { generate } from "typesharp";
async function generateTypes() {
await generate("./path/to/config.ts");
}
generateTypes();Requirements
- Node.js >= 14
- TypeScript >= 4.5 (if using TypeScript config)
License
MIT © Siyavuya Chagi
Author
Siyavuya Chagi (CeeJay)
- GitHub: @siyavuyachagi
- Email: [email protected]
Built with ❤️ in South Africa 🇿🇦
