Generate Typescript From Enum
20 May 2016
Hello everybody,
today I want to share with the world code, which generates typescript from enum declaration. I suppose everything should be understandable from code itself:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace System { public static class AttributesSimplification { /* [Description("Enumerations")] public enum EnumSample { [Description("Choice One")] ChoiceOne, [Description("Choice Two")] ChoiceTwo, } gives following ts: module Enumerations { export module EnumSample { export enum Enum { ChoiceOne = 0, ChoiceTwo = 2 } export function describe (enumValue: Enum) { switch (enumValue) { case Enum.ChoiceOne: return "Choice One"; case Enum.ChoiceTwo: return "Choice Two"; default: throw Error("Unknown Enum Value"); } } } } export = Enumerations; */ // Since Enum Type implements IConvertible interface we can pass into method enum //http://stackoverflow.com/questions/79126/create-generic-method-constraining-t-to-an-enum public static string GetTypeScriptRepresentation<T>() where T :struct , IConvertible { if (!typeof(T).IsEnum) { throw new ArgumentException("T must be an enumerated type"); } StringBuilder sb = new StringBuilder(); var defaultInstance = new T(); var values = Enum.GetValues(typeof(T)).Cast<T>().ToList(); var descAttribute = (DescriptionAttribute) Attribute.GetCustomAttribute(defaultInstance.GetType(), typeof(DescriptionAttribute)); string moduleName = string.Empty; if (descAttribute == null || string.IsNullOrEmpty(descAttribute.Description)) { moduleName = defaultInstance.GetType().Namespace; } else { moduleName = descAttribute.Description; } var enumName = defaultInstance.GetType().Name; string openingBr = "{"; string closingBr = "}"; sb.Append($"module {moduleName} \r\n {openingBr} \r\n"); sb.Append($"\texport module {enumName} \r\n\t {openingBr} \r\n"); sb.Append($"\t\texport enum Enum \r\n\t\t{openingBr}"); var lastValue = values[values.Count - 1]; foreach (var value in values) { var intPresentation = Convert.ToInt32(value as System.Enum); sb.Append($"\r\n\t\t\t\t{value.ToString()} = {intPresentation.ToString()}" ); if (value.ToString() != lastValue.ToString()) { sb.Append(","); } else { sb.Append("\r\n"); } } sb.Append($"\t\t{closingBr}"); sb.Append("\r\n\texport function describe (enumValue: Enum) \r\n\t{"); sb.Append("\r\n\t\tswitch (enumValue) \r\n\t\t{\r\n"); foreach (var value in values) { sb.Append("\t\t\t\tcase Enum."); sb.Append(value.ToString()); sb.Append(":"); sb.Append("\r\n\t\t\t\t\t return \"" + GetDescription(value as System.Enum) + "\""); sb.Append(";\r\n"); } sb.Append("\t\t\tdefault:\r\n"); sb.Append("\t\t\t\tthrow Error(\"Unknown Enum Value\");"); sb.Append("\r\n\t\t\t}\r\n\t\t }\r\n\t}\r\n}\r\n"); return sb.ToString(); } public static void WriteFile(string filePath, string content) { if (System.IO.File.Exists(filePath)) { IO.File.Delete(filePath); } System.IO.File.WriteAllText(filePath, content); } public static string GetDescription(this Enum value) { DescriptionAttribute attribute = value.GetType() .GetField(value.ToString()) .GetCustomAttributes(typeof(DescriptionAttribute), false) .SingleOrDefault() as DescriptionAttribute; return attribute == null ? value.ToString() : attribute.Description; } public static T GetEnumValueFromDescription<T>(string description) { var type = typeof(T); if (!type.IsEnum) throw new ArgumentException(); var fields = type.GetFields(); var field = fields .SelectMany(f => f.GetCustomAttributes( typeof(DescriptionAttribute), false), ( f, a) => new { Field = f, Att = a }).SingleOrDefault(a => ((DescriptionAttribute)a.Att) .Description == description); return field == null ? default(T) : (T)field.Field.GetRawConstantValue(); } } }
Some examples of it's job:
AttributesSimplification.GetTypeScriptRepresentation<System.UriHostNameType>()
As result gives the following:
declare module System { interface Uri { AbsolutePath: string; AbsoluteUri: string; Authority: string; DnsSafeHost: string; Fragment: string; Host: string; HostNameType: System.UriHostNameType.Enum; IdnHost: string; IsAbsoluteUri: boolean; IsDefaultPort: boolean; IsFile: boolean; IsLoopback: boolean; IsUnc: boolean; LocalPath: string; OriginalString: string; PathAndQuery: string; Port: number; Query: string; Scheme: string; Segments: string[]; UserEscaped: boolean; UserInfo: string; } }
If you'll have the following declaration:
[Description("DomainModels.Location")] public enum LocationLevel { //Country - ProvincePart levels do not use as they are in nuts codes but can be added if necesary Country = 1, CountryPart = 2, Province = 3, ProvincePart = 4, Municipality = 5, City = 6, }
Then with following code
AttributesSimplification.GetTypeScriptRepresentation<QCore.Portal.Models.DomainModels.Location.LocationLevel>()
you'll see the following TypeScript generated:
module DomainModels.Location { export module LocationLevel { export enum Enum { Country = 1, CountryPart = 2, Province = 3, ProvincePart = 4, Municipality = 5, City = 6 } export function describe (enumValue: Enum) { switch (enumValue) { case Enum.Country: return "Country"; case Enum.CountryPart: return "CountryPart"; case Enum.Province: return "Province"; case Enum.ProvincePart: return "ProvincePart"; case Enum.Municipality: return "Municipality"; case Enum.City: return "City"; default: throw Error("Unknown Enum Value"); } } } }
Take note, how attribute Description was applied.
One more example:
[Description("Models.DomainModels")] public enum AwardStatus { [Description("Still in progress")] StillInProgress, [Description("Awarded")] Awarded, [Description("Withdrawn")] Withdrawn }
AttributesSimplification.GetTypeScriptRepresentation<DomainModels.AwardStatus>()
gives following TS:
module Models.DomainModels { export module AwardStatus { export enum Enum { StillInProgress = 0, Awarded = 1, Withdrawn = 2 } export function describe (enumValue: Enum) { switch (enumValue) { case Enum.StillInProgress: return "Still in progress"; case Enum.Awarded: return "Awarded"; case Enum.Withdrawn: return "Withdrawn"; default: throw Error("Unknown Enum Value"); } } } }
So, if you need some kind of enums generation, you can use my utility.