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.
✨ 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
🗺️ Dictionary Mapping – Dictionary<K, V> → Record<K, V>
🧬 Generic Types – Preserves generic type definitions like Response<T> → Response<T>
🧬 Inheritance – Preserves class inheritance using extends
🏗️ Computed Properties – Expression-bodied and block getter properties are included
🎨 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)
🔗 Auto Imports – Automatically generates import type statements between output files
🏢 Multi-Project – Scan multiple .csproj files in a single run
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
npm install -D @siyavuyachagi/typesharpIn your target project create the following attribute (TypeSharp)
namespace YourProject.Attribute
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum)]
public class TypeSharpAttribute : Attribute { }
}[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; }
}In your frontend project run the following script
# Create TypeScript config
npx typesharp init
# ----- OR -------
# Create JSON config
npx typesharp init --format json
# Create TypeScript config (default)
npx typesharp init --format ts
# Create JavaScript config
npx typesharp init --format jsThis creates typesharp.config.json:
{
"projectFiles": [
"C:/Users/User/Desktop/MyApp/Api/Api.csproj",
"C:/Users/User/Desktop/MyApp/Domain/Domain.csproj"
],
"outputPath": "./app/types",
"targetAnnotation": "TypeSharp",
"singleOutputFile": false,
"namingConvention": "camel"
}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
| Option | Type | Default | Description |
|---|---|---|---|
projectFiles |
string | string[] |
required | Full path(s) to your C# .csproj file(s) |
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) |
namingConvention |
string | { dir: string, file: string } |
'camel' |
Property/file/dir naming: kebab, camel, pascal, snake |
fileSuffix |
string |
optional | Suffix appended to generated file names: user-dto.ts |
namingConvention accepts either a simple string that applies to everything, or a config object for separate control over directories and files:
// Simple — applies to both dirs and files
{ "namingConvention": "kebab" }
// Advanced — separate control
{
"namingConvention": {
"dir": "kebab",
"file": "camel"
}
}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 structure Various 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
│ └── ProductCreateDto
This means if you organize related DTOs in one C# file, they'll stay together in the generated TypeScript file! 🎯
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",
};Add TypeSharp to your build scripts:
{
"scripts": {
"generate-types": "typesharp",
"dev": "typesharp && nuxt dev",
"build": "typesharp && nuxt build"
}
}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;
}TypeSharp includes expression-bodied and block getter properties in the generated output:
C#:
[TypeSharp]
public class PollOptionUserLinkDto
{
public int Id { get; set; }
public int UserId { get; set; }
public UserDto User { get; set; }
// Expression-bodied
public string? Avatar => User?.Avatar;
// Block getter
public string UserFirstName { get { return User.FirstName; } }
// Init-only (Planned)
// public string Slug { get; init; }
}Generated TypeScript:
export interface PollOptionUserLinkDto {
id: number;
userId: number;
user: UserDto;
avatar: string | null;
userFirstName: string;
slug: string;
}C#:
[TypeSharp]
public class PermissionMap
{
public Dictionary<string, bool> Flags { get; set; }
public IReadOnlyDictionary<string, List<string>> RolePermissions { get; set; }
}Generated TypeScript:
export interface PermissionMap {
flags: Record<string, boolean>;
rolePermissions: Record<string, string[]>;
}Scan multiple C# projects at once:
{
"projectFiles": [
"C:/MyApp/Api/Api.csproj",
"C:/MyApp/Domain/Domain.csproj",
"C:/MyApp/Contracts/Contracts.csproj"
],
"outputPath": "./src/types"
}Config:
const config: TypeSharpConfig = {
projectFiles: "./Backend/Backend.csproj",
outputPath: "./src/types",
singleOutputFile: true,
};All types will be generated in src/types/types.ts
Config:
const config: TypeSharpConfig = {
projectFiles: "./Backend/Backend.csproj",
outputPath: "./src/types",
namingConvention: {
dir: "kebab", // ./src/types/my-feature/
file: "camel", // myFeatureDto.ts
},
};| C# Type | TypeScript Type |
|---|---|
bool |
boolean |
byte, decimal, double, float, int, long |
number |
DateTime, DateOnly, TimeOnly |
string |
Guid, string |
string |
object |
any |
| C# Type | TypeScript Type |
|---|---|
List<T>, ICollection<T>, IEnumerable<T>, T[] |
T[] |
Dictionary<K, V>, IDictionary<K, V>, IReadOnlyDictionary<K, V> |
Record<K, V> |
| C# Type | TypeScript Type |
|---|---|
IFormFile, FormFile |
File |
IFormFileCollection |
File[] |
FileStream, MemoryStream, Stream |
Blob |
You can also use TypeSharp programmatically:
import { generate } from "typesharp";
async function generateTypes() {
await generate("./path/to/config.ts");
}
generateTypes();- Node.js >= 14
- TypeScript >= 4.5 (if using TypeScript config)
MIT © Siyavuya Chagi
Siyavuya Chagi (CeeJay)
- GitHub: @siyavuyachagi
- Email: syavuya08@gmail.com
Built with ❤️ in South Africa 🇿🇦