GithubHelp home page GithubHelp logo

csharp-models-to-typescript's Introduction

C# models to TypeScript

This is a tool that consumes your C# domain models and types and creates TypeScript declaration files from them. There's other tools that does this but what makes this one different is that it internally uses Roslyn (the .NET compiler platform) to parse the source files, which removes the need to create and maintain our own parser.

NPM version

Dependencies

Install

$ npm install --save csharp-models-to-typescript

How to use

  1. Add a config file to your project that contains for example...
{
    "include": [
        "./models/**/*.cs",
        "./enums/**/*.cs"
    ],
    "exclude": [
        "./models/foo/bar.cs"
    ],
    "namespace": "Api",
    "output": "./api.d.ts",
    "camelCase": false,
    "camelCaseEnums": false,
    "camelCaseOptions": {
        "pascalCase": false,
        "preserveConsecutiveUppercase": false,
        "locale": "en-US"
    },
    "numericEnums": false,
    "omitFilePathComment": false,
    "omitSemicolon": false,
    "stringLiteralTypesInsteadOfEnums": false,
    "customTypeTranslations": {
        "ProductName": "string",
        "ProductNumber": "string"
    }
}
  1. Add a npm script to your package.json that references your config file...
"scripts": {
    "generate-types": "csharp-models-to-typescript --config=your-config-file.json"
},
  1. Run the npm script generate-types and the output file specified in your config should be created and populated with your models.

License

MIT © Jonathan Svenheden

csharp-models-to-typescript's People

Contributors

adnandervisevic avatar digocesar avatar eriktoyra avatar glhoest avatar lacroixdavid1 avatar safeerh avatar svenheden avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

csharp-models-to-typescript's Issues

Cannot find Namespace 'Api'

after creating file
config-typegen.json:

{ "include": [ "../DBO/**/*.cs" ], "exclude": [ ], "namespace": "Api", "output": "./api.d.ts", "camelCase": false, "camelCaseEnums": false, "camelCaseOptions": { "pascalCase": false, "preserveConsecutiveUppercase": false, "locale": "en-US" }, "numericEnums": false, "omitFilePathComment": false, "omitSemicolon": false, "stringLiteralTypesInsteadOfEnums": false, "customTypeTranslations": { "ProductName": "string", "ProductNumber": "string" } }

and adding "generate-types": "csharp-models-to-typescript --config=config-typegen.json" into package.json

whenever im trying to invoke model fom 'Api' i'm receiving error TS2503: Cannot find namespace 'Api'.

Expand on JSON configuration file validation errors

csharp-models-to-typescript version: "0.6.0"

The JSON configuration file validator simply says that the JSON is invalid. It would be useful if it expanded on which line is invalid to help debugging issues in the configuration file.

invalidjson

Bug - Conversion Error

This block:

        [OptionalField]
        public UserType UserType= UserType.Other;

is converted to this:

userType=: UserType;

but must be converted to this:

userType: UserType;

Dependency vulnerability

The use of component is not working to me.
Visual Studio is saying that Newtonsoft has vulnerabilities.
image

Dictionaries with arrays/generics are not converted

Dictionaries with arrays/generics are not converted. Such as IDictionary<string, string[]> and IDictionary<string, IList<string>>

C#:

public class ErrorResponse
{
    public string ErrorCode { get; set; }
    public IEnumerable<string> Errors { get; set; }

    public IDictionary<string, string[]> ErrorData { get; set; }
    public IDictionary<string, IList<string>> Test1 { get; set; }
    public IDictionary<string, string> Test2 { get; set; }
}

Output:

export interface ErrorResponse {
    errorCode: string;
    errors: string[];
    errorData: IDictionary<string, string[]>; // not converted
    test1: IDictionary<string, IList<string>>; // not converted
    test2: { [index: string]: string }; // converted
}

As you can see in the output, ErrorData and Test1 are not converted.

Thanks,
Safeer

Use records instead of object with typed key accessors

Hey,

Been running into the issue since I upgraded typescript of: An index signature parameter type cannot be a union type. Consider using a mapped object type instead.ts(1337)

This is for a case like
ArbitraryMember: { [key: Enum]: Object };

where I am no longer allowed to use the Enum or a Type Alias even. This is quite annoying in our project since we rely on that a lot, especially type aliases. There's a pretty nice and easy fix though, which is to use the Record type.

The aboev case would be then:
ArbitraryMember: Record<Enum, Object>

Which is imo a pretty nice type, very usable with intellisense and fits very well for what we're trying to actually accomplish here, which is to match a dictionary type or in javascript an object with a key index accessor. This has worked great in all the situations I've tried it, including stuff like

Member: Record<string, boolean> which is then used as true && this.object.member["customerId"].

The only drawback I can see is that Record is not backwards compatible past TypeScript 2.1 but I'm not sure that's a big deal? Could be opt-in if that's the case. I'll make a PR if you don't disagree with this, or we can discuss alternate solutions :)

ERR_CHILD_PROCESS_STDIO_MAXBUFFER error when running

When running on node v11.13.0, I am getting the error below. However if I set the maxBuffer higher for this line:

exec(`dotnet run --project "${dotnetProject}" "${path.resolve(configPath)}"`, { maxBuffer: 1024 * 500 }, (err, stdout) => {

then it works like normal. So my proposal is to either let maxBuffer be a config option in the json, or possibly use process.stream which seems like it might be better for this task.

Error:

{ RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout maxBuffer length exceeded
    at Socket.onChildStdout (child_process.js:357:14)
    at Socket.emit (events.js:193:13)
    at addChunk (_stream_readable.js:296:12)
    at readableAddChunk (_stream_readable.js:273:13)
    at Socket.Readable.push (_stream_readable.js:232:10)
    at Pipe.onStreamRead (internal/stream_base_commons.js:150:17)

Ability to choose between a declared module or an exported module when generating types

Problem

I used to access my enum values (in a type-safe way) from my Angular view whenever I needed, by exposing it from my component as below.

E.g.

// my-enum.ts
export enum MyEnum {
  Ebay = 'Ebay',
  Amazon = 'Amazon',
}

// my-component.ts
import { MyEnum } from 'my-enum';

export class MyComponent {
  MyEnum: typeof MyEnum = MyEnum;
}

Now I'm running into to a problem where I can't access my generated enum values from my Angular view as I used to do because of the generated enums are defined under a declared module.

// my-component.ts
export class MyComponent {
  MyEnum: typeof ApiModel.MyEnum = ApiModel.MyEnum;
}
// ERROR: **ReferenceError: ApiModel is not defined**

Solution

The solution for this problem would be to generate types (e.g. enums) under an exported module (instead of a declared module as the declare keyword will not generate any JS code and only being used by the TS compiler)

So, it would be nice to have an option in the config file to choose between a declared module (e.g. model.d.ts) or an exported module (e.g. model.ts) when generating types.

Custom type Translation from byte[] isn't working

I can't convert the type byte[] to another type, causing my typescript file to output incorrect types.
Example:
Config file:

{
  "customTypeTranslations": {
    "byte[]" : "string"
  }
}

Source c# file:

public class Test {
  public string Name { get; set; }
  public byte[] Data { get; set; }
}

output typescript file content:

export interface Test {
  name: string;
  data: byte[] //should be string
}

I've created another custom type translations, like TimeSpan to string and even KeyValuePair<string, string> to { key: string; value: string; } and it worked file, but byte[] to string isn't working.

Any ideias on this?

Thanks in advance.

Wrong enum conversion

Converts this

public enum ContentType {
  HTML = 1,
  Text = 2
}

Into this (which should have numeric values instead)

export enum ContentType {
    HTML = 'HTML',
    Text = 'Text',
}

Class objects should be converted to optional properties

Hi, thanks for this great tool !
I've got a question, maybe i'm missing something.

Let's say I've this 2 classes :

class myClass1 {
   int prop1
}

class myClass2 {
    public MyClass1 obj ; 
}

shouldn't this be converted to :

interface myClass1 {
   prop1: number
}
interface myClass2 {
    obj?: myClass1
}

I'm asking this because of TS2322 i'm not able to set non-optional properties to undefined.

How to handle nullable reference types

Hey, really cool tool. Tried it on on set of c# code models we have to compare it to our TypeScript models.
This does reveal one issue - some types like string could be nullable by default.
https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references

An example would be the following conversion:

public class LinkViewModel {
  public Href { get; set; }
  public string Label { get; set; }
  public string Title { get; set; }
  public LinkTargetTypes? Target { get; set; }
}
export interface LinkViewModel {
  href: string;
  label: string;
  title: string;
  target?: LinkTargetTypes;
}

The problem is, these values could actually be null, or undefined (depending on how you ship the data).
TypeScript would not throw an error if you try to use a string method on on any of the string values.

Would it make sense to be able to control how reference types are handled?

How to exclude some interfaces from being inherited?

Let's say I have a class in csharp which implements IEquatable. Is there a way to exclude this interface from being inherited in typescript? This interface obviously does not exist in typescript an therefore generates an error.

public class DiffPiece : IEquatable<DiffPiece> 
{
    public ChangeType Type { get; set; }
    public int? Position { get; set; }
    public string Text { get; set; }
    public List<DiffPiece> SubPieces { get; set; } = new List<DiffPiece>();
}
export interface DiffPiece extends IEquatable<DiffPiece> {
    type: ChangeType;
    position?: number;
    text: string;
    subPieces: DiffPiece[];
}

Currently I'm helping myself by cleaning out the extends IEquatable<DiffPiece> after each generation, but this is not very convinient.
I may set up a pull request in the next days.

Interfaces don't get converted

Hey,

I just came to your project from https://stackoverflow.com/questions/54253927/convert-c-sharp-classes-and-interfaces-to-typescript and tried the following:

models/demo.cs

public interface IPhoneNumber {
    string Label { get; set; }
    string Number { get; set; }
    int MyProperty { get; set; }
}

public interface IPoint
{
   // Property signatures:
   int x
   {
      get;
      set;
   }

   int y
   {
      get;
      set;
   }
}


public class X {
    public IPhoneNumber test { get; set; }
    public IPoint test2 { get; set; }
}

Output:

declare module Api {
    // models/demo.cs
    export interface X {
        test: IPhoneNumber;
        test2: IPoint;
    }
}

As you can see IPoint and IPhoneNumber are not exported.

Is there any way to achieve that?

Add exceptions as part of the config.json

Hello,

I have the following property in my c# class public DateTime CreatedTimeStampUTC the tool generates createdTimeStampUtc: string. Would it be possible to add some kind of exception? in this case UTC so I can keep it all capital case?

Thanks for this project.

Enum offsets aren't converted correctly

Hey there,

I think I found a bug.

Consider the following C#:

public enum BillingCycle
{
   Yearly = 7,
   Monthly,
   Never = 4
}

If no explicit value is defined for an enum field, the C# compiler will increment the previous field value by +1. The C# compiler actually generates the above enum as:

public enum BillingCycle
{
    Yearly = 7,
    Monthly = 8,
    Never = 4
}

You can test that here: https://sharplab.io/#v2:CYLg1APgAgzABAUwHYFcC2cBCBLANr7JAcwGEBPAY1wQFgAoAb3rhYE0EBDAJ1zLgF44AdgA0zFgFkA9kgAuAC15i6LOADkEANwRcBcACz0AvkA=

The csharp-models-to-typescript will generate the incorrect enum mapping as follows:

export enum BillingCycle {
    Yearly = 7,
    Monthly = 1,
    Never = 4,
}

Version Info:
"csharp-models-to-typescript": "^0.16.0"

I'm getting 'Error: EISDIR: illegal operation on a directory'

Error upon running: csharp-models-to-typescript --config=csharp.config.json

{ [Error: EISDIR: illegal operation on a directory, open '<Dir>\src\models\input']
  errno: -4068,
  code: 'EISDIR',
  syscall: 'open',
  path: '<Dir>\\src\\models\\input' }

csharp.config.json

{
    "include": [
        "../<Dir>/InputModels/**/*.cs"
    ],
    "exclude": [],
    "namespace": "Api",
    "output": "./src/models/input",
    "camelCase": false,
    "camelCaseEnums": false,
    "numericEnums": false,
    "stringLiteralTypesInsteadOfEnums": false,
    "customTypeTranslations": {}
}

I also tried running this command as administrator in case something is wrong with the file permissions and gave everyone full control to this folder and I'm still getting the same error.

issue

Generate interfaces for all implementations of some interface

The thing I would like to do is to generate TS interfaces for all classes of some specific interface. I.e. I am using MediatR to model commands, so any command type implements the interface MediatR.IRequest.

It would be nice to be able to not specify all specific classes (they are all over the project). Is this possible? If not would consider accepting PRs for this feature (or even add it yourself)?

Allow camelcase options to be defined in config.

First of all, thank you for this awesome package.
I've been using it to great effect at one of the companies I work for.

Now I wanted to use it in another project, yet had to abort due to a conflict with the default camelcase options.
I could not use the package without having to change our public api to conform to the types this package emits.
Needless to say, that is not an acceptable option.

I think the solution would be quite simple.
Allow for the camelcase options object to be defined in the config json, and pass it through to where camelcase is used.
This should not result in any breaking changes.

Underscores are not handled correctly as attributes

public class Testing
{
        public int Success { get; set; }
        public int GU_ID { get; set; }
        public int GUID { get; set; }
        public int G_UID { get; set; }
        public int _GUID { get; set; }
        public int GUID_ { get; set; }
}
public enum TestEnum
{
        GU_ID,
        _GUID,
        GUID,
        GUID_
}

is converted to this:

export interface Testing {
        success: number;
        guid: number;
        guid: number;
        gUID: number;
        guid: number;
        guid: number;
    }
    export enum TestEnum {
        GU_ID = 0,
        _GUID = 1,
        guid = 2,
        GUID_ = 3,
    }

As you see, the underscore is not correctly handled in class attributes, it is removed, but it is correctly handled in enums.
my config is like this:

{
    "include": [
        ".\\BO\\**\\*.cs"
    ],
    "exclude": [
    ],
    "namespace": "\"ApiTypes\"",
    "output": "types.d.ts",
    "camelCase": true,
    "camelCaseEnums": false,
    "camelCaseOptions": {
        "pascalCase": false,
        "preserveConsecutiveUppercase": true,
        "locale": "en-US"
    },
    "numericEnums": true,
    "stringLiteralTypesInsteadOfEnums": false,
    "customTypeTranslations": {
        "char": "string",
        "Exception":"any"
    }
}

I'd love to try to solve this problem, if you would merge it to the project.

Error "The output from `csharp-models-to-json` contains invalid JSON." on nuget warnings in projects

Version: "csharp-models-to-typescript": "^0.21.1"

After recent Visual Studio 2022 update I started to get NU1803 warnings compiling projects (actually not compiling, but restoring). And npm run generate-types stopped working.

generate-types defined in package.json scripts:

"generate-types": "csharp-models-to-typescript --config=cs-to-ts-config.json"

Output from npm run generate-types:

> csharp-models-to-typescript --config=cs-to-ts-config.json

The output from `csharp-models-to-json` contains invalid JSON.

Unexpected token C in JSON at position 0

C:\sources\ReactApp\ClientApp\node_modules\csharp-models-to-typescript\lib\csharp-models-to-json\csharp-models-to-json.csproj : warning NU1803: You are running the 'restore' operation with an 'HTTP' source, 'http://nuget.mycompany.com/v3/index.json'. Non-HTTPS access will be removed in a future version. Consider migrating to an 'HTTPS' source.
C:\sources\ReactApp\ClientApp\node_modules\csharp-models-to-typescript\lib\csharp-models-to-json\csharp-models-to-json.csproj : warning NU1803: You are running the 'restore' operation with an 'HTTP' source, 'http://nuget.mycompany.com/v3/index.json'. Non-HTTPS access will be removed in a future version. Consider migrating to an 'HTTPS' source.
[{"FileName":"C:\\sources\\ReactApp\Backend\\Models\\Customer.cs","Models":[{"ModelName":
...

Proper JSON goes after warnings.

The quick fix is to change line in index.js to remove warning lines:

json = JSON.parse(stdout);

to this:

const removeWarningLines = (str) =>
    str.includes("csharp-models-to-json.csproj : warning") ? "" : str;

stdout = stdout.split("\n").map(removeWarningLines).join("\n");
stdout = stdout.split("\r").map(removeWarningLines).join("\r");
json = JSON.parse(stdout);

Convert enums for member type of class to ts enum.

It will be good to add logic to add Enums for member type of converting class to output .d.ts
For example:
There is class ./Proejct1/Models/TargetDto.cs

public class TargetDto
{
    public RelatedEnum PropName { get; set; }
}

and enum ./Proejct2/Models/TargetEnum.cs

public class TargetEnum
{
    First, Second
}

and configuration

{
    "include": [
        "./Proejct1/Models/*Dto.cs"
    ],
    "output": "./api.d.ts",
    "camelCase": true,
    "stringLiteralTypesInsteadOfEnums": false
}

As result, api.d.ts will contain only definition of TargetDto with property propName of type TargetEnum, that was not converted to ts enum.

Actualapi.d.ts:

export interface TargetDto {
    propName: TargetEnum;
}

Expected api.d.ts:

export interface TargetDto {
    propName: TargetEnum;
}

export enum TargetEnum{
    First= 'First',
    Second = 'Second'
}

Net Core 3 support

Am I missing something of is it impossible to use this tool using only Net Core 3 installed? I am getting the following output trying to run the code. Huge thanks I appreciate that library.

csharp-models-to-typescript --config=tsgen.config.json

It was not possible to find any compatible framework version

The framework 'Microsoft.NETCore.App', version '2.0.0' was not found.
  - The following frameworks were found:
      3.0.1 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
      3.1.3 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

You can resolve the problem by installing the specified framework and/or SDK.

Are public const supported?

Hi
My class

name MyNamespace {
    public class MyClass
    {
        #region Constants.

        public const string DefaultLanguage= "English";

        public const string AllowedArea = "index.html"

        #endregion
   }
}

When run through the tool, comes out as:

declare module MyNamespace {
    // MyNamespace\MyClass.cs
    export interface MyClass{

    }
}

How to gain this output please:

namespace MyNamespace {
    // MyNamespace\MyClass.cs
    export class MyClass {
       public static DefaultLanguage: string = "English";
       public static AllowedArea: string = "index.html"
    }
}

Thank you for your help in this.

Kind Regards
Fawad

JsonIgnoreAttribute.Condition is not handled

Both classic Newtonsoft.Json and System.Text.Json have JsonIgnoreAttribute to prevent properties from being Json-serialized. However Newtonsoft's JsonIgnore is unconditional: if public property is marked with it, it's not in Json output.

Microsoft's JsonIgnore has Condition property to control more aspects. Only Always which is default value shall not produce no TypeScript property in generated output while 3 other enum values should.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.