TypeScript <-> C# DTO Converter
Convert a TypeScript interface or C# class/record to the other language.
Overview
Paste a TypeScript interface (or type alias) and get a C# class or record that mirrors its shape - and vice versa. Field names, optional markers, array types, and basic union types translate across the language boundary. Useful for keeping API DTOs in sync between a TypeScript client and a .NET backend.
It's for full-stack developers maintaining a shared contract between frontend and backend codebases without a code-generation pipeline. Reach for it when adding a new endpoint, scaffolding test fixtures, or porting a TypeScript model from a third-party SDK into a C# wrapper.
How it works
The converter parses the TypeScript syntax (using a subset of TS 5.x grammar - interfaces, type aliases, union types, generic arrays) and emits an equivalent C# declaration. Primitive types map across: string to string, number to double (or int if integer-only), boolean to bool, Date to DateTime, arrays T[] to List<T> or T[].
Optional fields (field?: T in TypeScript) become nullable in C# (T? for reference types with NRT enabled, Nullable<T> for value types). Union types narrow to the most-specific common type, with object as the fallback. Records are emitted by default for immutable DTOs; classes when mutability is needed.
Examples
- TypeScript input:
C# output:interface User { id: number; name: string; email?: string; roles: string[]; }public record User { public int Id { get; init; } public string Name { get; init; } = string.Empty; public string? Email { get; init; } public List<string> Roles { get; init; } = new(); } - C# to TypeScript:
public record Order(int Id, DateTime CreatedAt, decimal Total);interface Order { id: number; createdAt: string; // ISO 8601 total: number; } - Optional becomes nullable:
note?: string -> public string? Note { get; init; } - Union type:
status: 'pending' | 'paid' -> public string Status { get; init; }
FAQ
Should I generate a record or a class?
Records are concise and immutable (perfect for DTOs). Use a class when you need EF Core navigation properties, custom equality, or mutability.
What about Date and DateTime?
TypeScript's Date becomes DateTime in C#. When the JSON is on the wire, ISO 8601 strings are typical - System.Text.Json serialises DateTime to ISO 8601 by default.
How are TypeScript union types handled?
String unions ('a' | 'b') become string (or, optionally, an enum). Object unions narrow to a common base or object. Discriminated unions would need a manual JsonPolymorphic setup in .NET 8+.
Will the output round-trip exactly?
Mostly. Some translations are lossy by necessity (TypeScript union narrowing, lack of TS decimal). For full bidirectional fidelity, generate one side from the other rather than maintaining both.