Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typelite: Why is Dictionary<string, object> mapped to KeyValuePair and not to any or [index:string]:any

Tags:

typelite

I have a class,

public class Instance : IResource
{
   public Dictionary<string, object> Value { get; set; }

and it is mapped to

interface Instance {
   Value: System.Collections.Generic.KeyValuePair[];

interface KeyValuePair {
   Key: any;
   Value: any;
}

I would have expected

interface Instance {
   Value: any;

or

interface Instance {
   Value: {[index:string]:any};

How can I change the generation?

Also, how can I skip the name space in the generation?

like image 252
mattias Avatar asked Jan 25 '14 12:01

mattias


2 Answers

A quick and dirty workaround is to use a regex to alter output:

Using

<#= Regex.Replace( ts.Generate(TsGeneratorOutput.Properties)
        , @":\s*System\.Collections\.Generic\.KeyValuePair\<(?<k>[^\,]+),(?<v>[^\,]+)\>\[\];"
        , m=>": {[key: "+m.Groups["k"].Value+"]: "+m.Groups["v"].Value+"};"
        , RegexOptions.Multiline)
#>

Transforms a field

    myField: System.Collections.Generic.KeyValuePair<string,OtherClass>[];

to

    myField: {[key: string]: OtherClass};
like image 63
Olivier Avatar answered Oct 03 '22 09:10

Olivier


Collection types (any type implementing IEnumerable) is converted to arrays. Dictionary<> implements IEnumerable<KeyValuePair<>> and thus is converted to an array. The item-type is then expanded to its fully qualified name (FQN): System.Collections.Generic.KeyValuePair.

Using Type Converters will let you change the type-name, but not the FQN. So it is only applicable to local types. In the case of dictionaries, you can't change the item type by inheritance.

You could either create a new dictionary type, without inheriting from Dictionary<>. Another way around this problem, is to also use Type Formatters:

ts.WithConvertor<Dictionary<string,object>>(t => {
    // Embed the real type in $
    // "System.Collections.Generic.${ [key: string]: any }$[]"
    return "${ [key: string]: any }$";
});
ts.WithFormatter((string memberTypeName, bool isMemberCollection) => {
    // Extract the content inside $
    string[] pieces = memberTypeName.Split('$');
    if (pieces.Length == 3) return pieces[1];
    // Default behaviour
    return memberTypeName + (isMemberCollection ? "[]" : "");
});
like image 37
Markus Jarderot Avatar answered Oct 03 '22 08:10

Markus Jarderot