npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@avensia-oss/tstypegen

v3.1.0

Published

A tool to generate TypeScript types from C# types

Downloads

920

Readme

.NET

This program will generate TypeScript definitions from C# types. It's built on .NET Core which makes it possible to use on Windows, Mac and Linux.

Install

TSTypeGen is distributed as an npm package, install by doing:

yarn add @avensia-oss/tstypegen

Usage

dotnet node_modules/@avensia-oss/tstypegen/bin/TSTypeGen.dll -c <config-file> [-verify]

Options:

  • -c: Specify the configuration file (see below for format)
  • -verify: Do not update any definitions but instead return an error if any files need updates. This can be used on a CI server to detect if all types have been built and checked in.
  • p: Specify directories containing NuGet caches. If invoking the tool from a .targets file, specify "-p "$(NuGetPackageFolders)&quot; (Note the final backslash that is required because the MSBuild variable ends with a backslash, and if we don't have 2, the quote will be escaped which is bad)
  • f: Specify target framework version. If invoking the tool from a .targets file, specify "-f $(TargetFrameworkVersion)"
  • d: Specify dllPatterns on the command line instead of in the config. Separate patterns with , or ;

In order to generate a file, the minimum you need to do is define a C# attribute called GenerateTypeScriptDefinitionAttribute, like this:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Enum)]
public sealed class GenerateTypeScriptDefinitionAttribute : Attribute
{
    public bool Generate { get; }

    public GenerateTypeScriptDefinitionAttribute()
    {
        Generate = true;
    }

    public GenerateTypeScriptDefinitionAttribute(bool generate)
    {
        Generate = generate;
    }
}

After that you can add that attribute to the classes etc that you want to generate TypeScript types for. TSTypeGen will see your attribute regardless even if it's defined in your code as it will match based on the attribute name.

Config file

The config file is a JSON with the following options:

  • newLine: The character(s) to use to generate new lines, defaults to "\n".
  • basePath: Optional base path for where to find files. If omitted the base path becomes the path to the config file.
  • outputPath: Optional path to where generated d.ts-files are placed. If omitted the output path becomes the base path.
  • dllPatterns: An array of glob patterns to find dll files to inspect.
  • typeMappings: A dictionary that maps type full C# names (including namespaces) to corresponding TypeScript types.
  • customTypeScriptIgnoreAttributeFullName: Name of a custom attribute to treat the same as [JsonIgnore] and [TypeScriptIgnore]
  • propertyWrappers: A dictionary that defines wrappers for properties in the listed types

Example:

{
  newLine: "\n",
  basePath: "./src",
  outputPath: "./ts-types",
  dllPatterns: ["src/bin/Debug/**/*.dll"],
  typeMappings: {
    "Cms.CmsData": "@avensia/core/CmsData",
    "System.DateTime": "string",
    "System.Guid": "string",
  },
  customTypeScriptIgnoreAttributeFullName: "Avensia.MyTypeScriptIgnoreAttribute",
}

Controlling types with attributes

TSTypeGen comes with multiple attributes that lets you control how the TypeScript types are created. All of them should be defined in your code as TSTypeGen will identify them by name.

[GenerateTypeScriptNamespace("Backend")]

This attribute is typically placed in AssemblyInfo.cs and it will control the name of the namespace and .d.ts-file that the TypeScript types are placed in.

[TypeScriptType("MyType")]

Use this to override the type that TSTypeGen selects for a property. You should most likely only do this if you also make the same change in how you serialize the C# objects to JSON.

Example:

[GenerateTypeScriptDefinition]
public class MyApiModel
{
  [TypeScriptType("string")]
  public Guid Id { get; set; }
}

[TypeScriptOptional]

Use this to make TSTypeGen generate a property as optional.

Example:

[GenerateTypeScriptDefinition]
public class MyApiModel
{
  [TypeScriptOptional]
  public string Id { get; set; }
}

becomes:

interface MyApiModel {
  id?: string;
}

[GenerateTypeScriptDerivedTypesUnion]

Use this on an abstract base class to generate a union type of all derived child types. This is best used in combination with [GenerateTypeScriptTypeMember] and comes in handy when the TypeScript code needs to create command objects of a limited set of allowed types.

Example:

[GenerateTypeScriptDefinition]
[GenerateTypeScriptTypeMember]
[GenerateTypeScriptDerivedTypesUnion]
public abstract class Command
{

}

[GenerateTypeScriptDefinition]
public class UpdateCommand : Command
{
  public string Id { get; set; }
  public string Name { get; set; }
}

[GenerateTypeScriptDefinition]
public class InsertCommand : Command
{
  public string Name { get; set; }
}

becomes:

interface Command {}

interface UpdateCommand extends Command {
  $type: "UpdateCommand";
  id: string;
  name: string;
}

interface InsertCommand extends Command {
  $type: "InsertCommand";
  name: string;
}

type CommandTypes = UpdateCommand | InsertCommand;

Now you can have a method that takes CommandTypes as an argument and you can know that only valid command objects are passed to it.

[GenerateTypeScriptTypeMember]

Use this to inject a $type property with the class name. Best used in combination with [GenerateTypeScriptDerivedTypesUnion]. See above example.

[GenerateDotNetTypeNamesAsJsDocComment]

This adds a JSDoc comment to the TypeScript type with the full .NET name of the type. This can be useful if you want to use the TypeScript compiler API to find the full .NET name for a certain type. Example:

[assembly: GenerateDotNetTypeNamesAsJsDocComment]

public namespace MyNamespace
{
  [GenerateTypeScriptDefinition]
  public class MyApiModel
  {
    public string Id { get; set; }
  }
}

becomes:

/** @DotNetTypeName MyNamespace.MyApiModel,MyNamespace */
interface MyApiModel {
  id: string:
}

[GenerateCanonicalDotNetTypeScriptType]

This is used together with [GenerateDotNetTypeNamesAsJsDocComment] and lets you add an additional JSDoc comment to any class that implements an interface that has a [GenerateCanonicalDotNetTypeScriptType] attribute. An example:

[assembly: GenerateDotNetTypeNamesAsJsDocComment]

public namespace MyNamespace
{
  [GenerateTypeScriptDefinition]
  [GenerateCanonicalDotNetTypeScriptType]
  public interface IMyApiModel
  {
    string Id { get; set; }
  }

  [GenerateTypeScriptDefinition]
  public class MyApiModel : IMyApiModel
  {
    public string Id { get; set; }
  }
}

becomes:

interface IMyApiModel {
  id: string:
}

/**
 * @DotNetTypeName MyNamespace.MyApiModel,MyNamespace
 * @DotNetCanonicalTypeName MyNamespace.IMyApiModel,MyNamespace
 */
interface MyApiModel {
  id: string:
}

Contributing

Please create an issue for discussion before starting to work on something. Contributions are very welcome!

Creating a release

If you have gotten publishing rights to the npm package, you first run:

dotnet test ./src/TSTypeGen.Tests/TSTypeGen.Tests.csproj

to make sure the tests still pass. Then you run:

dotnet publish src/TSTypeGen/TSTypeGen.csproj -o ./bin

which creates a bin/ folder in the root with the exe and dll files.

Set a new version in the package.json. Then run:

npm publish

Push the version change in the package.json.

Additional details

The unit tests are quite extensive and written in a way that should make it quite clear how TSTypeGen works and the different configuration options there is.