C# PR

【TypeGem】C#のclassをTypescriptへ変換

アイキャッチ(c_sharp)
記事内に商品プロモーションを含む場合があります

こんにちは!
なかむぅです。

C#のclassに存在するフィールドやプロパティをTypescriptに変換するためにTypeLiteを使用していましたが、まったく更新されないので

なんか他に良いライブラリはないかなぁ

と思い探してみたところ、TypeGenというものを見つけました。

勉強がてら遊んでみて、気になったことをまとめていきます。

TypeGenとは

TypeGenとはどのようなものかというと、以下のC#のコードがあるとします。

ProductDto.cs

using TypeGen.Core.SpecGeneration;

namespace TypeGenTest
{
	public class ProductDto
	{
		public decimal Price { get; set; }
		public string[] Tags { get; set; }
	}

	public class MyGenerationSpec : GenerationSpec
	{
		public MyGenerationSpec()
		{
			AddClass<ProductDto>();
		}
	}
}

このC#のコードを、以下のTypescriptのコードに変換してくれるのがTypeGenです。

product-dto.ts

export class ProductDto {
	price: number;
	tags: string[];
}

生成までの準備として、ProductDto.csに生成したいクラスをセットするコードを書いて、configファイルのgenerationSpecsにその実行したいクラス名を指定します。
実行したいクラスはProductDto.csで言うとMyGenerationSpecです。

tgconfig.json

{
	"generationSpecs": [ "MyGenerationSpec" ]
}

準備ができたら、以下のコマンドをパッケージマネージャーコンソールで実行するとtsファイルが生成されます。


typegen -p "プロジェクト名" generate

ちなみにCLIをインストールすればPowerShellなどからも実行可能です。

TypeGenの特徴

TypeGenにはざっくり以下の特徴があります。

  • 対象はpublicなプロパティとフィールド
  • Attributeで指定することも可能
  • クラス単位でファイルが生成される
  • namespaceがつけられない
  • json形式で設定ファイルを使える

対象はpublicなプロパティとフィールド

publicなプロパティとフィールドが対象なので、privateやprotectedなどのプロパティや変数は生成されません。

ProductDto.cs

public class ProductDto
{
	public static string productName;
	public readonly int price;
	public const bool isBuy = true;
	public DateTime PurchaseDate { get; set; }
	private string[] Tags { get; set; } // privateなので対象外
	protected int Count { get; set; } // protectedなので対象外
}
product-dto.ts

export class ProductDto {
	readonly price: number;
	static productName: string;
	static readonly isBuy: boolean = true;
	purchaseDate: Date;
}

Attributeで指定することも可能

冒頭ではMyGenerationSpecを使った方法を紹介しましたが、クラスの数やファイルごとにコード量が多くなるため、Attributeも用意されています。

用意されているAttributeは以下の3つ。

  • ExportTsClass
  • ExportTsInterface
  • ExportTsEnum

名前の通りClass、Interface、Enumに合わせて指定しましょう。

余談ですが、継承や参照型はimport文が挿入され、Typescriptでもちゃんと継承される仕組みになっています。

ProductDto.cs

[ExportTsClass]
public class ProductDto : IProductDto
{
		public string ProductName { get; set; }
		public int Price { get; set; }
}

[ExportTsInterface]
public interface IProductDto
{
		string ProductName { get; set; }
		int Price { get; set; }
}

[ExportTsEnum]
public enum ProductEnum
{
		ProductName,
		Price
}
product-dto.ts

import { IProductDto } from "./i-product-dto"; // ちゃんと読み込まれて継承される

export class ProductDto implements IProductDto {
	productName: string;
	price: number;
}
i-product-dto.ts

export interface IProductDto {
	productName: string;
	price: number;
}
product-enum.ts

export enum ProductEnum {
	ProductName = 0,
	Price = 1,
}

Attributeを使うときは、jsonでプロジェクトのdllファイル、またはexeファイルを指定する必要があるので、設定してあげましょう。

tgconfig.json

{
	"assemblies": [ "./bin/Debug/net6.0/TypeGenTest.dll" ]
}

クラス単位でファイルが生成される

Attributeで指定することも可能」でなんとなく察せられたかもしれませんが、TypeGenはクラスごとにファイルが生成されます。

1つのファイルにまとめて生成することはできません。
(自分が見つけられてないだけかも。あったら教えてください。)

そのため、以下のようにクラスが2つある場合はファイルが2つ生成されます。

ProductDto.cs

[ExportTsClass]
public class ProductDto
{
		public string ProductName { get; set; }
}

[ExportTsClass]
public class PriceDto
{
		public int Price { get; set; }
}
product-dto.ts

export class ProductDto {
	productName: string;
}
price-dto.ts

export class PriceDto {
	price: number;
}

namespaceがつけられない

C#のクラスがnamespace内に入っていても、生成時にははずれてしまいます。

設定でもつけることはできません。

要望はあったみたいですが、TODOリストに入れただけで対応はしていないようです。

json形式で設定ファイルを使える

jsonファイル内にはassemblies以外にも設定することが可能です。

以下、自分が気になったものだけ紹介します。

tgconfig.json

{
	"assemblies": [ "./bin/Debug/net6.0/TypeGenTest.dll" ],
	"outputPath": "Script",
	"fileNameConverters": [ "UnderscoreCaseToPascalCase" ],
	"typeNameConverters": [ "PascalCaseToCamelCase" ],
	"propertyNameConverters": [ "PascalCaseToCamelCase" ],
	"explicitPublicAccessor": true
}
assemblies 生成したいクラスがあるプロジェクトのDLLファイルを指定
string型の配列で複数指定できる
必須項目
outputPath Typescriptを出力したいディレクトリ
fileNameConverters 生成するtsファイルの命名規則を変更できる
デフォルトはKebabCase
typeNameConverters classやinterfaceの命名規則を変更できる
デフォルトはPascalCase
propertyNameConverters プロパティやフィールドの命名規則を変更できる
デフォルトはCamelCase
explicitPublicAccessor プロパティやフィールドにpublicのアクセス修飾子をつけるかつけないか

その他設定が気になる方は、こちらを参考にしてください。


私の会社で一緒に働きませんか?

私が働く会社では、一緒に働いてくれるエンジニアを募集しています♪

こんな人がオススメ
  • 長く働いていても年収が全然上がらない…一気に年収を上げたい
  • 残業をしたくてしているわけではないので、残業代はしっかりと出して欲しい
  • やりたいことに挑戦させてもらえない…自分がしてみたいことに挑戦したい
  • 通勤時間が長すぎるから、できるだけ短くしたい
  • もっと勉強したいから、書籍代や資格の受験料など負担してくれるところに入りたい
  • 現場に駆り出されてからは放置プレイ…相談できる人も先輩も居ないので、自分の状況をちゃんと理解してくれるところで働きたい

上記内容に1つでも当てはまる場合は、ぜひお声がけください。
私のサイトから応募していただいた方にはお好きなギフト券5000円分プレゼントさせていただきます(条件あり)。

詳細ページ


まとめ

個人的にはnamespaceがつかないのが残念でした。
(開発中のプロジェクトで使っていたため)

それ以外だとテキストテンプレートを使ったTypeLiteよりも、処理は早いのでTypeGenのほうが使いやすいかなぁと思っています。

以上、TypeGenについてでした!

いやここは違うだろ

と思った方はコメントいただけると嬉しいです。

最後までお読みいただきありがとうございました!

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です