Skip to content
/ Tapper Public
forked from nenoNaninu/Tapper

A Tool Transpiling C# Type into TypeScript Type.

License

Notifications You must be signed in to change notification settings

Vulthil/Tapper

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tapper

Tapper is a library/CLI tool to transpile C# type (class, struct, record, enum) into TypeScript type (type, enum). Using this tool can reduce serialization bugs (type mismatch, typos, etc.) and make TypeScript code easily follow changes in C# code.

teaser

Table of Contents

Packages

Install Using .NET Tool

Use Tapper.Generator(CLI Tool) to generate TypeScript type from C# type. Tapper.Generator can be easily installed using .NET Global Tools. You can use the installed tools with the command tapper.

# install (.NET 7)
dotnet tool install --global Tapper.Generator
tapper help

# update
dotnet tool update --global Tapper.Generator

# install (.NET 6)
dotnet tool install --global Tapper.Generator --version 1.5.1

Getting Started

First, add the following packages to your project. Tapper.Analyzer is optional, but recommended.

dotnet add package Tapper.Attributes
dotnet add package Tapper.Analyzer (optional, but recommended.)

Next, apply the [TranspilationSource] Attribute to the C# type definition.

using Tapper;

namespace SampleNamespace;

[TranspilationSource] // <- Add attribute!
public class SampleType
{
    public List<int>? List { get; }
    public int Value { get; }
    public Guid Id { get; }
    public DateTime DateTime { get; }
}

Then execute the command as follows.

tapper --project path/to/XXX.csproj --output outdir

TypeScript source code is generated in the directory specified by --output. In this example, TypeScript source code named outdir/SampleNamespace.ts is generated. The contents of the generated code is as follows.

/* eslint-disable */

/** Transpiled from SampleNamespace.SampleType */
export type SampleType = {
  /** Transpiled from System.Collections.Generic.List<int>? */
  list?: number[];
  /** Transpiled from int */
  value: number;
  /** Transpiled from System.Guid */
  id: string;
  /** Transpiled from System.DateTime */
  dateTime: (Date | string);
}

Transpilation Rules

Tapper transpile C# types (class, struct, record, enum) to TypeScript types (type, enum). When transpiling class, struct, and record, only public fields and properties are transpiled.

Built-in Supported Types

C# TypeScript Description
bool boolean
byte number
sbyte number
char string or number JSON: string, MessagePack number.
decimal number
double number
float number
int number
uint number
long number
ulong number
short number
ushort number
object any
string string
Uri string
Guid string Compatible with TypeScript's crypto.randomUUID().
DateTime (Date | string) or Date Json: (Date | string), MessagePack: Date.
DateTimeOffset (Date | string) or [Date, number] Json: (Date | string), MessagePack: [Date, number]. note #41
System.Nullable<T> (T | undefined)
byte[] string or Uint8Array JSON: string (base64), MessagePack Uint8Array.
T[] T[]
System.Array any[] ❌ System.Text.Json
ArraySegment<T> T[] ❌ System.Text.Json
List<T> T[]
LinkedList<T> T[]
Queue<T> T[]
Stack<T> T[]
HashSet<T> T[]
IEnumerable<T> T[]
IReadOnlyCollection<T> T[]
ICollection<T> T[]
IList<T> T[]
ISet<T> T[]
Dictionary<TKey, TValue> { [key: TKey]: TValue }
IDictionary<TKey, TValue> { [key: TKey]: TValue }
IReadOnlyDictionary<TKey, TValue> { [key: TKey]: TValue }
Tuple [T1, T2, ...] ❌ System.Text.Json

C# Namespace

C# namespace is mapped to the filename of the generated TypeScript code.

namespace SampleNamespace;

[TranspilationSource]
record Xxx();

For example, given the above C# code, TypeScript code with the file name SampleNamespace.ts is generated.

Nesting Types

It doesn't matter if the user-defined types are nested. For example, consider the following C# code. Apply [TranspilationSource] Attribute to all types to be transpiled. If you add an analyzer package, you can avoid forgetting to apply [TranspilationSource].

#nullable enable

namespace Space1
{
    [TranspilationSource]
    public class CustomType1
    {
        public int Value;
        public Guid Id;
    }

    namespace Sub
    {
        [TranspilationSource]
        public enum MyEnum
        {
            Zero = 0,
            One = 1,
            Two = 1 << 1,
            Four = 1 << 2,
        }
    }
}

namespace Space2
{
    [TranspilationSource]
    public record CustomType3(float Value, DateTime ReleaseDate);
}

namespace Space3
{
    using Space1;
    using Space1.Sub;
    using Space2;

    [TranspilationSource]
    public class NastingNamespaceType
    {
        public CustomType1? Value { get; set; }
        public MyEnum MyEnumValue { get; set; }
        public List<CustomType3> List { get; set; } = new();
    }
}

The following TypeScript code is generated.

  • Space1.ts
/** Transpiled from Space1.CustomType1 */
export type CustomType1 = {
  /** Transpiled from int */
  value: number;
  /** Transpiled from System.Guid */
  id: string;
}
  • Space1.Sub.ts
/** Transpiled from Space1.Sub.MyEnum */
export enum MyEnum {
  Zero = 0,
  One = 1,
  Two = 2,
  Four = 4,
}
  • Space2.ts
/** Transpiled from Space2.CustomType3 */
export type CustomType3 = {
  /** Transpiled from float */
  value: number;
  /** Transpiled from System.DateTime */
  name: (Date | string);
}
  • Space3.ts
import { CustomType1 } from './Space1';
import { MyEnum } from './Space1.Sub';
import { CustomType3 } from './Space2';

/** Transpiled from Space3.NastingNamespaceType */
export type NastingNamespaceType = {
  /** Transpiled from Space1.CustomType1? */
  value?: CustomType1;
  /** Transpiled from Space1.Sub.MyEnum */
  myEnumValue: MyEnum;
  /** Transpiled from System.Collections.Generic.List<Space2.CustomType3> */
  list: CustomType3[];
}

Options

Naming Style

You can select camelCase, PascalCase, or none for the property name of the generated TypeScript type. For none, the property name in C# is used. The default is the standard naming style for TypeScript.

tapper --project path/to/Xxx.csproj --output outdir --naming-style camelCase --enum-naming-style PascalCase

Serializer

The TypeScript code generated by Tapper is supposed to be serialized/deserialized with json or MessagePack. And the appropriate type is slightly different depending on the serializer. You can specify which one to use by passing the --serializer option. The default is json.

tapper --project path/to/Xxx.csproj --output outdir --serializer MessagePack --naming-style none --enum-naming-style none

Also, it is supposed that the following serializers are used.

MessagePack

If you use MessagePack-CSharp for the serializer, be careful how you apply the [MessagePackObject] Attribute. It is recommended to use [MessagePackObject(true)]. Also, in that case, set --naming-style to none and --enum-naming-style to none .

[MessagePackObject(true)]
public class SampleType
{
    public Guid Id { get; set; }
    public int Value { get; set; }
}

Transpile the Types Contained in Referenced Assemblies.

By default, only types defined in the project specified by the --project option are targeted for transpiling. By passing the -asm true option, types contained in project/package reference assemblies will also be targeted for transpiling.

tapper --project path/to/Xxx.csproj --output outdir -asm true

Analyzer

Tapper has some rules. You can easily follow those rules by adding Tapper.Analyzer.

  • If the fields and property types contained in the type to which [TranspilationSource] applies are user-defined types, you must also apply [TranspilationSource] to those types.
  • You cannot apply [TranspilationSource] to Generic type.

Unity Support

For Unity projects, first, copy and paste the TranspilationSourceAttribute.cs into your project. Then apply [TranspilationSource] to types you want to transpile.

Next, a file named Assembly-CSharp.csproj is generated by Unity. It is in the same hierarchy as Assets. Use this project file as an argument to --project.

tapper --project path/to/Assembly-CSharp.csproj --output outdir

About

A Tool Transpiling C# Type into TypeScript Type.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 92.6%
  • TypeScript 7.2%
  • JavaScript 0.2%