Skip to content

Data Mapping with TypeScript

fonlow edited this page Feb 17, 2022 · 9 revisions

Data Types Mapping

Simple Types

The following code snippet may illustrate the mapping between .NET simple types and TypeScript types.

static readonly Dictionary<string, string> typeMap = new Dictionary<string, string>()
{
	{typeof(int).FullName, "number"},
	{typeof(uint).FullName, "number"},
	{typeof(long).FullName, "number"},
	{typeof(ulong).FullName, "number"},
	{typeof(short).FullName, "number"},
	{typeof(ushort).FullName, "number"},
	{typeof(float).FullName, "number"},
	{typeof(double).FullName, "number"},
	{typeof(decimal).FullName, "number"},
	{typeof(byte).FullName, "number"},
	{typeof(sbyte).FullName, "number"},
	{typeof(string).FullName, "string"},
	{typeof(char).FullName, "string"},
	{typeof(Guid).FullName, "string"},
	{typeof(bool).FullName, "boolean"},
	{typeof(void).FullName, "void"},
	{typeof(object).FullName, "any"},
	{typeof(DateTime).FullName, "Date"},
	{typeof(DateTimeOffset).FullName, "Date"},
	{typeof(DateOnly).FullName, "Date"},
	{typeof(Uri).FullName, "string"},
};

Remarks

DateOnly is introduced in .NET 6, however, not matured enough for prime time in ASP.NET applications without patching at the application level. Before Microsoft's ASP.NET Core team could fix the issues in .NET 7, this CodeProject article provide a solution, with a component from this WebApiClientGen project.

Array

In addition to CLR array, the types illustrated in the following code snippet are translated into TypeScript array.

        static readonly System.Collections.Generic.HashSet<string> arrayTypeNames = new System.Collections.Generic.HashSet<string>(
        new string[]() {
            typeof(IEnumerable<>).FullName,
            typeof(IList<>).FullName,
            typeof(ICollection<>).FullName,
            typeof(IQueryable<>).FullName,
            typeof(IReadOnlyList<>).FullName,
            typeof(List<>).FullName,
            typeof(System.Collections.ObjectModel.Collection<>).FullName,
            typeof(IReadOnlyCollection<>).FullName
       }
       );

Hints:

Since Javascript supports only single dimensional array, this article "Tricky Array" may help you to deal with multidimensional array.

Dictionary and KeyValuePair

A dictionary is based on a hash table available only at run time, and it is generally impossible to transport a hash table over wire. However, common practices are to transport the key / value pairs in a list, and it is up to the client programs to decide whether to reassemble the list into a dictionary, or just use the list through indexer.

.NET Client API

IDictionary<K,V> and Dictionary<K,V> are translated into Dictionary<ClientK, ClientV>.

Remarks:

Such transportation and transformation are done by Newtonsoft.JSON which can reassemble the key / value pairs into a dictionary.

TypeScript Client API

IDictionary<K,V> and Dictionary<K,V> are translated into an indexer like

{[id: string]: DemoWebApi_DemoData_Client.Person }

KeyValuePair<K, V> is translated into a structure like

{Key: string, Value: DemoWebApi_DemoData_Client.Person }

Remarks:

In Javascript, the key of an indexer must be string.

Nullable or Required

By default, all members generated in a TypeScript interface are optional/nullable, unless the members in the .NET classes are decorated with one of the following:

[DataMember(IsRequired =true)]
...
[JsonProperty(Required = Required.Always)]
...
[Required]
...

Remarks:

In contrast, in generated C# codes, whether a value type property is nullable is matching to the respective property in the service model. In JavaScript, all properties are basically reference types, and an object initialization like const someone: Person = {} has all properties undefined, while in C# or other high level programming language, runtime will initialize all properties of a newly created typed object.

Stream

Stream is supported only in HTTP GET. For jQuery, the return type is "any". For Angular2, the return type is "Response".

Byte Array

Byte array is supported only in HTTP GET. For jQuery and Angular 2, the return type is "Array".

Generics

TypeScript supports generics, and WebApiClientGen 2.5 supports custom generic classes.

Remarks:

If you need to handle a lot Stream or Byte Array, it is better to put respective functions to a dedicated ApiController, and exclude the controller from the code generation process.

Clone this wiki locally