frhagn / Typewriter

Automatic TypeScript template generation from C# source files
http://frhagn.github.io/Typewriter
Apache License 2.0
537 stars 132 forks source link

Wrong property type when rendering a $Type #303

Open johnknoop opened 5 years ago

johnknoop commented 5 years ago

This is my C# class that is being generated using $Classes:

        public class Species
        {
            public string Name { get; set; }
            public IList<TreeItem<string>> SubspeciesNames { get; set; }
        }

I use this template to generate TS interfaces:

export interface $Name$TypeParameters {$Properties[
    $Prop;]
}]

which results in a Species.ts that looks like this:

export interface Species {
    name: string;
    subspeciesNames: TreeItem<string>[];
}

So far so good. But now I want to also include the referenced type TreeItem in the same output file.

The TreeItem class looks like this:

    public class TreeItem<T>
    {
        public T Item { get; set; }
        public IEnumerable<TreeItem<T>> Children { get; set; }
    }

In order to do that, I've created a function called ReferencedTypes like this:

    IEnumerable<Type> ReferencedTypes(File f)
    {
        bool IsDefinedInFile(Type t) {
            return f.Classes.Any(x => x.FullName == t.FullName) || f.Interfaces.Any(x => x.FullName == t.FullName);
        }

        Type GetImportableType(Type t) {
            if (t.IsEnumerable && t.TypeArguments.Any()) {
                return GetImportableType(t.TypeArguments.First());
            }

            return !IsDefinedInFile(t) && t.IsDefined && !t.IsEnum && t.Namespace.StartsWith("MyNamespace")
                ? t
                : null;
        }

        var allClassesInFile = f.Classes.Concat(f.Classes.SelectMany(c => c.NestedClasses));

        return allClassesInFile.SelectMany(x => x.Properties.Select(p => GetImportableType(p.Type)).Where(t => t != null));
    }

And I'm calling it like this:

$ReferencedTypes[
export interface $OriginalName$TypeParameters $BaseClass[extends $Name]{ $Properties[
    $name: $Type[$Unwrap[$OriginalName]$TypeParameters];]
}
]

The expected output of $ReferencedTypes would be:

export interface TreeItem<T> { 
    item: T;
    children: TreeItem<T>;
}

But the actual output is this:

export interface TreeItem<T> { 
    item: string;
    children: TreeItem<T>;
}

Notice how the type of the item property is string and not T. I suppose this is because the Species class is passing string as type argument, but that's not what I'm telling it to render.

Is this a bug, or am I doing it wrong?