Programming

TypeScript 프로젝트에서 기존 C # 클래스 정의를 재사용하는 방법

procodes 2020. 8. 5. 20:11
반응형

TypeScript 프로젝트에서 기존 C # 클래스 정의를 재사용하는 방법


TypeScript엔터티 프레임 워크 도메인 모델이있는 MVC 프로젝트에 속하는 HTML 클라이언트 프로젝트에서 사용을 시작하려고합니다 . 두 팀 이이 작업을 수행 할 때 두 개의 프로젝트 (클라이언트 측과 서버 측)가 완전히 분리되기를 바랍니다 .JSON과 REST는 객체를 앞뒤로 전달하는 데 사용됩니다.

물론 domain클라이언트 쪽의 객체는 서버 쪽의 객체와 일치해야합니다. 과거에는 일반적으로이 작업을 수동으로 수행했습니다. C # 클래스 정의 (특히 POJO도메인 모델의 클래스)를 재사용하여 TypeScript에서 해당 클래스를 만드는 방법이 있습니까? "


현재 C #을 TypeScript에 매핑하는 것은 없습니다. POCO가 많거나 자주 변경 될 것이라고 생각되면 변환기를 만들 수 있습니다.

public class MyPoco {
    public string Name { get; set; }
}

export class MyPoco {
    public Name: string;
}

C #에서 자동 생성에 대한 Codeplex에 대한 토론 도 있습니다 .

업데이트 된 정보를 유지하기 위해 TypeLite는 C #에서 TypeScript 인터페이스를 생성 할 수 있습니다.

http://type.litesolutions.net/


Web Essentials를 사용하면 C # 파일을 .d.ts저장시 TypeScript 파일 로 컴파일 할 수 있습니다. 그런 다음 .ts파일 에서 정의를 참조 할 수 있습니다.

여기에 이미지 설명을 입력하십시오


위의 TypeLite와 T4TS는 모두 좋아 보였습니다. TypeLite를 골라서 지원을 얻었습니다.

  • ValueTypes ,
  • 널 입력 가능
  • camelCasing (TypeScript 루트 문서는 낙타를 사용하며 C #과 너무 잘 어울립니다)
  • 퍼블릭 필드 (깨끗하고 읽기 쉬운 POCO를 좋아하고 C # 컴파일러도 쉬움)
  • 모듈 생성 비활성화

그런 다음 C # 인터페이스가 필요 했고 내 일을 구워야 할 때라고 생각하고 필요한 것을 수행하는 간단한 T4 스크립트를 작성했습니다. Enum 도 포함되어 있습니다 . 리포지토리가 필요 없으며 <100 줄의 T4.

사용법
라이브러리, NuGet 없음,이 단순하고 단순한 T4 파일 – Visual Studio에서 "항목 추가"를 사용하고 T4 템플릿을 선택하십시오. 그런 다음 파일에 붙여 넣습니다. "ACME"를 사용하여 모든 라인을 조정하십시오. 모든 C # 클래스마다 줄을 추가하십시오.

<#= Interface<Acme.Duck>() #>

주문 문제, 알려진 모든 유형이 다음 인터페이스에 사용됩니다. 인터페이스 만 사용하는 경우 파일 확장자는 .d.ts수 있습니다. 열거 형의 경우 변수가 인스턴스화되므로 .ts 파일 이 필요합니다 .

사용자 정의
스크립트를 해킹하십시오.

<#@ template debug="true" hostSpecific="true" language="C#" #>
<#@ output extension=".ts" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ assembly name="$(TargetDir)ACME.Core.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Linq" #>

<#= Interface<Acme.Bunny>() #>
<#= Interface<Acme.Duck>() #>
<#= Interface<Acme.Birdy>() #>
<#= Enums<Acme.CarrotGrade>() #>
<#= Interface<Acme.LinkParticle>() #>

<#+  
    List<Type> knownTypes = new List<Type>();

    string Interface<T>()
    {   
        Type t = typeof(T);     
        var sb = new StringBuilder();
        sb.AppendFormat("interface {0} {{\n", t.Name);
        foreach (var mi in GetInterfaceMembers(t))
        {
            sb.AppendFormat("  {0}: {1};\n", this.ToCamelCase(mi.Name), GetTypeName(mi));
        }
        sb.AppendLine("}");
        knownTypes.Add(t);
        return sb.ToString();
    }

    IEnumerable<MemberInfo> GetInterfaceMembers(Type type)
    {
        return type.GetMembers(BindingFlags.Public | BindingFlags.Instance)
            .Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property);
    }

    string ToCamelCase(string s)
    {
        if (string.IsNullOrEmpty(s)) return s;
        if (s.Length < 2) return s.ToLowerInvariant();
        return char.ToLowerInvariant(s[0]) + s.Substring(1);
    }

    string GetTypeName(MemberInfo mi)
    {
        Type t = (mi is PropertyInfo) ? ((PropertyInfo)mi).PropertyType : ((FieldInfo)mi).FieldType;
        return this.GetTypeName(t);
    }

    string GetTypeName(Type t)
    {
        if(t.IsPrimitive)
        {
            if (t == typeof(bool)) return "bool";
            if (t == typeof(char)) return "string";
            return "number";
        }
        if (t == typeof(decimal)) return "number";            
        if (t == typeof(string)) return "string";
        if (t.IsArray)
        {            
            var at = t.GetElementType();
            return this.GetTypeName(at) + "[]";
        }
        if(typeof (System.Collections.IEnumerable).IsAssignableFrom(t)) 
        {
            var collectionType = t.GetGenericArguments()[0]; // all my enumerables are typed, so there is a generic argument
            return GetTypeName(collectionType) + "[]";
        }            
        if (Nullable.GetUnderlyingType(t) != null)
        {
            return this.GetTypeName(Nullable.GetUnderlyingType(t));
        }
        if(t.IsEnum) return "number";
        if(knownTypes.Contains(t)) return t.Name;
        return "any";
    }

    string Enums<T>() // Enums<>, since Enum<> is not allowed.
    {
        Type t = typeof(T);        
        var sb = new StringBuilder();        
        int[] values = (int[])Enum.GetValues(t);
        sb.AppendLine("var " + t.Name + " = {");
        foreach(var val in values) 
        {
            var name = Enum.GetName(typeof(T), val);
            sb.AppendFormat("{0}: {1},\n", name, val);
        }
        sb.AppendLine("}");
        return sb.ToString();
    }
#>

스크립트의 다음 레벨은 MVC JsonController 클래스에서 서비스 인터페이스를 작성하는 것입니다.


해결 방법은 다음과 같습니다. 속성으로 C # 클래스를 선언하면 .d.ts 파일이 생성됩니다 (T4 변환 사용). 거기의 nuget에 패키지 소스는 github에 볼 수 있습니다 . 나는 여전히 프로젝트를 진행하고 있지만 지원은 상당히 광범위하다.


Visual Studio를 사용하는 경우 Typewriter 확장을 추가하십시오.

비주얼 스튜디오 갤러리

웹 사이트 / 문서

최신 정보

웹 필수가 VS 2015에 설치, 당신은 클래스 파일을 마우스 오른쪽 단추로 클릭 한 다음> 웹 필수> 컨텍스트 메뉴에서 타이프 라이터 인텔리 파일을 만듭니다.


vscode를 사용하면 내 확장명 csharp2ts사용할 수 있습니다 .

붙여 넣은 C # 코드를 선택하고 Convert C# to TypeScript명령 팔레트 여기에 이미지 설명을 입력하십시오A 변환 예 에서 명령을 실행하면됩니다 .

public class Person
{
    /// <summary>
    /// Primary key
    /// </summary>
    public int Id { get; set; }

    /// <summary>
    /// Person name
    /// </summary>
    public string Name { get; set; }
}

export interface Person
{
    /**Primary key */
    Id : number;

    /**Person name */
    Name : string;
}

Reinforced.Typings 프레임 워크를 사용해보십시오. 문제가 해결 된 것 같습니다.

  1. NuGet 에서 설치
  2. POCO로 이동하여 [TsInterface]그 위에 속성을 추가 하십시오.

    using Reinforced.Typings.Attributes;
    namespace YourNamespace {
        [TsInterface]
        public class YourPoco
        {
            public int YourNumber { get;set; }
            public string YourString { get;set; }
            public List<string> YourArray { get;set; }
            public Dictionary<int, object> YourDictionary { get;set; }
        }
    }
    
  3. 프로젝트 재 구축
  4. %Your_Project_Directory%/Scripts/project.ts파일 에서 생성 된 TypeScript 코드를 찾아 수동으로 프로젝트에 추가

    module YourNamespace {
        export interface IYourPoco
        {
            YourNumber: number;
            YourString: string;
            YourArray: string[];
            YourDictionary: { [key: int]: any };
        }
    }
    
  5. 모든 project.tsPOCO에 대해 동일한 작업을 수행하고 다른 TypeScript 코드에서 참조 하십시오.

문서 위키 에서 자세한 내용을 참조하십시오


C # 클래스에서 TypeScript 인터페이스를 생성 할 수있는 작은 유틸리티를 만들었습니다. NuGet 패키지 로 제공됩니다 . 자세한 문서는 프로젝트 웹 페이지 에서 찾을 수 있습니다 .


이 라이브러리를 살펴 제발 타자기를

클래스, 열거 형, 인터페이스 등뿐만 아니라 API 컨트롤러도 변환합니다.

또한 소스 .cs 파일을 저장 하자마자이 작업을 수행하므로 외부 도구를 트리거 할 필요가 없습니다. .cs를 저장하면 .ts가 업데이트됩니다


T4 템플릿 ( 보기 소스 ) 을 사용하는 작은 솔루션이 있습니다 .

모든 CLR POCO에서 나옵니다.

public class Parent : Person
{
    public string Name { get; set; }
    public bool? IsGoodParent { get; set; }
    public virtual ICollection<Child> Children { get; set; }
}

TypeScript 인터페이스로 :

///<reference path="Child.d.ts" />
///<reference path="Person.d.ts" />
interface Parent extends Person {
    Name : string;
    IsGoodParent? : bool;
    Children : Child[];
}

오픈 소스 프로젝트 NSwag를 사용할 수 있습니다 . GUI의 기존 .NET DLL에서 .NET 클래스를 선택하고 이에 대한 TypeScript 인터페이스를 생성 할 수 있습니다.

이 프로젝트는 명령 줄 도구와 T4 템플릿 지원 및 웹 API 컨트롤러 용 클라이언트 코드 생성 기능도 제공합니다.


다른 방법은 어떻습니까?

erecruit TypeScript Translator를 확인하십시오 . C #을 지원할 준비가되었지만 실제로는 템플릿 기반 (Nujucks를 렌더링에 사용)이므로 VB.NET, F #, C ++, XML, SQL 등 템플릿으로 인코딩 할 수있는 모든 것을 생성 할 수 있습니다.

.NET 콘솔 프로그램, NodeJS 프로그램 (Windows에없는 프로그램) 또는 Visual Studio 확장으로 작동 하며 저장시 생성 기능이 있습니다. 또한 빌드 서버를 만족시키기 위해 MSBuild 지원 기능이 포함되어 있습니다. :-)


이것을 사용할 수도 있습니다 : https://github.com/pankleks/TypeScriptBuilder

이 작은 라이브러리는 C # 형식을 기반으로 TypeScript 형식 정의를 생성합니다. 백엔드 C # 프로젝트에서 직접 사용하여 프론트 엔드 TypeScript 프로젝트의 코드를 생성하십시오. 소형 콘솔 앱을 작성하여 사전 빌드 도구로 코드를 생성 할 수도 있습니다.

Full & NET Core 프레임 워크에서 작동합니다!

너겟으로 설치 : Install-Package TypeScriptBuilder

지원되는 기능

  • 타입 의존성 해결
  • 제네릭
  • 유형 상속
  • 네임 스페이스 (모듈)
  • 열거 형
  • 널 입력 가능 유형
  • 사전 수렴 (강력한 TS 인덱스 개체로)
  • 코드 생성 제어 속성 세트
  • any 변환 할 수없는 유형의 경우

자세한 설명 : https://github.com/pankleks/TypeScriptBuilder/blob/master/README.md


사람들은 https://github.com/reinforced/ Reinforced.Typings를 살펴보십시오 . 나는 지난 며칠 동안 typelite와 t4 템플릿을 가지고 놀고 있었고이 프로젝트로 끝났습니다. 매우 간단하고 매력처럼 작동합니다. 패키지를 가져 와서 구성 파일을 수정하고 (10 초 정도) 빌드하십시오. 모든 문제없이 자동으로 수행됩니다. 저자를 축복하십시오!

T4 템플릿의 나쁜 점은 VS에서 빌드 한 후에 스캔 한 어셈블리가 잠기고 VS를 다시 시작해야한다는 것입니다 (어떻게 바보입니까?). T4 Toolbox에는 몇 가지 해결 방법이 있으며 일부 VS 청소 지침이 있지만 그중 아무것도 나를 위해 일하지 않았습니다.


나는 citykid 솔루션을 좋아한다. 나는 그것을 조금 확장했다. 따라서 솔루션은 T4 템플릿을 사용한 코드 생성 기술을 기반으로합니다.

일반적인 TypeScript 유형과 앰비언트 선언을 생성 할 수 있습니다.

상속 및 인터페이스 구현을 지원합니다.

제네릭, 배열 및 목록을 유형 필드로 지원합니다.

또한 구성에서 명시 적으로 언급되지 않은 TypeScript 유형으로 변환됩니다 (예 : 유형 A를 가져오고 TS 출력에서 ​​다른 유형을 찾을 수 있습니다 : 필드 유형, 기본 유형 및 인터페이스).

유형 이름을 재정의 할 수도 있습니다.

열거 형도 지원됩니다.

사용 예 (프로젝트 저장소에서 찾을 수 있음) :

// set extension of the generated TS file
<#@ output extension=".d.ts" #>

// choose the type of TS import TsMode.Ambient || TsMode.Class
<# var tsBuilder = new TsBuilder(TsMode.Ambient); #>

// reference assembly with the c# types to be transformed
<#@ assembly name="$(SolutionDir)artifacts\...\CsT4Ts.Tests.dll" #>

// reference namespaces
<#@ import namespace="CsT4Ts.Tests" #>
<#
    //add types to processing
    tsBuilder.ConsiderType(typeof(PresetDTOBase), "PresetBase");
    tsBuilder.ConsiderType(typeof(PresetDTO), "Preset");
    tsBuilder.ConsiderType(typeof(TestInterface<,>));
#>

// include file with transformation algorithms
<#@ include file="CsT4Ts.t4" #>

그리고 당신은 출력을 얻을 것이다

//CsT4Ts.Tests.PresetDTOBase => PresetBase
// CsT4Ts.Tests.PresetDTO => Preset
// CsT4Ts.Tests.TestInterface`2 => TestInterface
// CsT4Ts.Tests.TestEnum => TestEnum

declare class PresetBase
{
    PresetId: string;
    Title: string;
    InterviewDate: string;
}

declare class Preset extends PresetBase
{
    QuestionsIds: string[];
}

declare interface TestInterface<TA, TB>
{
    A: string;
    B: number;
    C: TestEnum;
    D: TestEnum[];
    E: number[];
    F: TA;
    G: TB[];
}

declare enum TestEnum
{
    Foo = 10,
    Boo = 100
}

전체 솔루션을 확인하십시오 : https://bitbucket.org/chandrush/cst4ts


당신은 (는 "하나의 클래스 파일 당"방식으로, 즉) 생성 된 모든 타이프 라이터 클래스 / 인터페이스에 대한 별도의 파일을 작성해야하는 경우, 당신은 시도 할 수 TypeGen을 . 패키지 관리자 콘솔에서 C # 클래스 / 열을 기반으로 TypeScript 파일을 생성하는 데 사용할 수있는 도구입니다. 현재 다음을 지원합니다.

  • 열거 형 내보내기; POCO를 TS 클래스 또는 인터페이스로 내보내기
  • 계승
  • 일반 유형
  • 컬렉션 / 중첩 컬렉션 유형

몇 가지 추가 기능. 또한 오픈 소스입니다 ( github 에서 확인할 수 있습니다 ).


Bridge.net을 사용할 수도 있습니다. 버전 1.7부터는 C # 유형에 대한 TypeScript 정의 생성을 지원합니다. http://bridge.net/docs/generate-typescript-definitions/를 참조하십시오


@citykid의 답변도 많이 좋아서 한 번에 전체 네임 스페이스를 수행하도록 확장했습니다. POCO 클래스를 네임 스페이스에 넣고 T4 템플릿을 다시 빌드하십시오. 나는 각각에 대해 별도의 파일을 생성하는 방법을 알고 싶지만 세계의 끝은 아닙니다.

윗부분 (클래스가 원하는 위치)에서 .DLL 파일을 참조해야하며 네임 스페이스를 언급해야합니다. 편집 할 모든 줄은 ACME로 표시됩니다. @citykid의 주요 단서, 감사합니다!

<#@ template debug="true" hostSpecific="true" language="C#" #>
<#@ output extension=".ts" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ assembly name="$(TargetDir)YOUR_DLL_NAME_HERE_ACME.dll" #>
<#@ assembly name="$(TargetDir)YOUR_OTHER_DLL_NAME_HERE_ACME.dll" #>
<#@ assembly name="$(TargetDir)YOUR_OTHER_DLL_NAME_HERE_ACME.dll" #>
<#@ assembly name="$(TargetDir)YOUR_OTHER_DLL_NAME_HERE_ACME.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Reflection" #>

<#= Process("My.Very.Special.Namespace.ACME") #>
<#= Process("My.Other.Very.Special.Namespace.ACME") #>
<#= Process("My.Other.Very.Special.Namespace.ACME") #>
<#= Process("My.Other.Very.Special.Namespace.ACME") #>

<#+  

    List<Type> knownTypes = new List<Type>();

    string Process(string nameSpace) {
      var allass = AppDomain.CurrentDomain.GetAssemblies();
      var ss = "";
      foreach (var ass in allass)
      {
         ss += ProcessAssembly(ass, nameSpace);
      }
      return ss;
    }

   string ProcessAssembly(Assembly asm, string nameSpace) {
      try {
            Type[] types;
            try
            {
                types = asm.GetTypes();
            }
            catch (ReflectionTypeLoadException e)
            {
                types = e.Types;
            }
            var s = "";
            foreach (var t in types.Where(t => t != null))
            {
               try {

               if (String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal))
               {
                    s += InterfaceOfType(t);
               }

               } catch (Exception e)
               {
               }
            }
            return s;      
      }
      catch (Exception ee2) {
        return "// ERROR LOADING TYPES: " + ee2;
      }

   }

    string InterfaceOfType(Type T)
    {   
        Type t = T;     
        var sb = new StringBuilder();
        sb.AppendFormat("interface {0} {{\r\n", t.Name);
        foreach (var mi in GetInterfaceMembers(t))
        {
            sb.AppendFormat("  {0}: {1};\r\n", this.ToCamelCase(mi.Name), GetTypeName(mi));
        }
        sb.AppendLine("}");
        knownTypes.Add(t);
        return sb.ToString();
    }

    string Interface<T>()
    {   
        Type t = typeof(T);     
        var sb = new StringBuilder();
        sb.AppendFormat("interface {0} {{\n", t.Name);
        foreach (var mi in GetInterfaceMembers(t))
        {
            sb.AppendFormat("  {0}: {1};\r\n", this.ToCamelCase(mi.Name), GetTypeName(mi));
        }
        sb.AppendLine("}");
        knownTypes.Add(t);
        return sb.ToString();
    }

    IEnumerable<MemberInfo> GetInterfaceMembers(Type type)
    {
        return type.GetMembers(BindingFlags.Public | BindingFlags.Instance)
            .Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property);
    }

    string ToCamelCase(string s)
    {
        if (string.IsNullOrEmpty(s)) return s;
        if (s.Length < 2) return s.ToLowerInvariant();
        return char.ToLowerInvariant(s[0]) + s.Substring(1);
    }

    string GetTypeName(MemberInfo mi)
    {
        Type t = (mi is PropertyInfo) ? ((PropertyInfo)mi).PropertyType : ((FieldInfo)mi).FieldType;
        return this.GetTypeName(t);
    }

    string GetTypeName(Type t)
    {
        if(t.IsPrimitive)
        {
            if (t == typeof(bool)) return "boolean";
            if (t == typeof(char)) return "string";
            return "number";
        }
        if (t == typeof(decimal)) return "number";            
        if (t == typeof(string)) return "string";
        if (t.IsArray)
        {            
            var at = t.GetElementType();
            return this.GetTypeName(at) + "[]";
        }
        if(typeof (System.Collections.IEnumerable).IsAssignableFrom(t)) 
        {
            var collectionType = t.GetGenericArguments()[0]; // all my enumerables are typed, so there is a generic argument
            return GetTypeName(collectionType) + "[]";
        }            
        if (Nullable.GetUnderlyingType(t) != null)
        {
            return this.GetTypeName(Nullable.GetUnderlyingType(t));
        }
        if(t.IsEnum) return "number";
        if(knownTypes.Contains(t)) return t.Name;
        return "any";
    }

    string Enums<T>() // Enums<>, since Enum<> is not allowed.
    {
        Type t = typeof(T);        
        var sb = new StringBuilder();        
        int[] values = (int[])Enum.GetValues(t);
        sb.AppendLine("var " + t.Name + " = {");
        foreach(var val in values) 
        {
            var name = Enum.GetName(typeof(T), val);
            sb.AppendFormat("{0}: {1},\r\n", name, val);
        }
        sb.AppendLine("}");
        return sb.ToString();
    }
#>

내 솔루션은 단순히 프로젝트 어셈블리 (및 어셈블리 참조)를 취하는 작은 codegen util을 작성하고 typescript와 c # 간의 상호 작용과 관련된 유형을 스캔하는 것이 었습니다. 이 유틸리티는 자바 스크립트를 d.ts로 출력합니다 ... 도구는 빌드 후 이벤트에서 호출됩니다 ... 매력처럼 작동합니다!


관심이 있으시면 TypedRpc 를 사용할 수 있습니다 . 그 목적은 TypeScript에서 인터페이스를 만드는 것뿐만 아니라 JsonRpc 프로토콜을 사용하여 .Net의 서비스와의 모든 통신을 만드는 것입니다.

서버 클래스의 예 :

[TypedRpc.TypedRpcHandler]
public class RpcServerExample
{
    public String HelloWorld()
    {
        return "Hello World!";
    }
}

생성 된 TypeScript 코드의 사용법 :

/// <reference path="Scripts/TypedRpc.ts" />

let rpc: TypedRpc.RpcServerExample = new TypedRpc.RpcServerExample();

var callback = function(data, jsonResponse) {
    console.log(data);
};

rpc.HelloWorld().done(callback).fail(callback);

사용 방법에 대한 다른 예는 https://github.com/Rodris/TypedRpc확인하십시오 .


ASP.NET 웹 API 클라이언트 생성기 는 SDLC 동안 swagger 도구 체인 및 기타 도구보다 더 편리하고 오버 헤드가 적을 수 있습니다.

프로그래머는 일반적으로 WebApiClientGen을 사용하여 클라이언트 API 코드를 생성하지만이 프로젝트는 POCO 클래스에서 TypsScript 인터페이스를 생성하는 명령 줄 프로그램 인 POCO2TS.exe도 제공합니다. Poco2ts.exe 또는 poco2ts 구성 요소를 사용하여 코드 생성을 빌드 파이프 라인과 통합 할 수 있습니다.


node.js를 통해 변환하려면이 패키지 (csharp-to-typescript)를 사용할 수 있습니다. https://www.npmjs.com/package/csharp-to-typescript

소스 코드 : https://github.com/YuvrajSagarRana/csharp-to-typescript

eg: 
// After installation, import the package.
var { CsharpToTs, getConfiguration } = require("csharp-to-typescript");

// Use CsharpToTs to convert your source code a. Method one give your source code as string:
const sourceCodeInString =   `public class Address
{
  public int Id {get; set;}
  public string Street { get; set; }
  public string City { get; set; }
}`

var outputTypescript = CsharpToTs(sourceCodeInString, getConfiguration());
console.log(outputTypescript);

// Output is

export class Address
{
  Id: number;
  Street: string;
  City: string;
}

참고 URL : https://stackoverflow.com/questions/12957820/how-to-reuse-existing-c-sharp-class-definitions-in-typescript-projects

반응형