TypeScript <-> C# DTO Converter

Convert a TypeScript interface or C# class/record to the other language.

Open tool

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:
    interface User {
      id: number;
      name: string;
      email?: string;
      roles: string[];
    }
    
    C# output:
    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.

Try TypeScript <-> C# DTO Converter

An unhandled error has occurred. Reload ×