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

Square brackets added to nullable string #331

Open johnknoop opened 4 years ago

johnknoop commented 4 years ago

I'm experiencing problems after declaring some strings as nullable, using the new nullable ref types in C# 8.

For any C# string?, the property.Type.Name will be string[].

Any idea how to get around this?

grey280 commented 4 years ago

I've run into the same issue, but have yet to find a workaround.

johnknoop commented 4 years ago

@grey280 My workaround for now is to disable Typewriter and edit the .ts files manually. But that's not sustainable in the long run of course.

johnknoop commented 4 years ago

@frhagn is this something you think you'll fix eventually?

SamuelKupferschmid commented 4 years ago

For me this workaroud works:

if(p.Type.Name.EndsWith("[]") && !p.Type.FullName.StartsWith("System.Collections")) {
        return p.Type.Name.Substring(0, p.Type.Name.Length - 2);
 } else {
        return p.Type.Name;
 }

It would be nice if this project comes alive somehow.

grey280 commented 3 years ago

Here's my variant of the workaround:

// special case: nullable value types (i.e. String?) register as Enumerable (Typewriter bug), need to be handled
bool hasNullableAttribute = p.Type.Attributes.Any(x => x.Name.ToLower() == "nullable");
bool endsWithBrackets = p.Type.Name.ToLower().EndsWith("[]");
bool isEnumerable = p.Type.FullName.StartsWith("System.Collections");
if (hasNullableAttribute && endsWithBrackets && !isEnumerable){
    return $"{p.Type.Name.Substring(0, p.Type.Name.Length - 2)} | null";
}
return $"{p.Type.Name} | null";
johnknoop commented 3 years ago

@grey280 @SamuelKupferschmid Any ideas on how to make this approach work for this case?

public Dictionary<string, string?> Nodes { get; set; }
grey280 commented 3 years ago

@johnknoop There'd be some very manual checks in that case, I suspect - I've been tinkering with trying to make something to recursively handle generics, but so far I keep running up against the disconnect between a Type and a TypeParameter.

johnknoop commented 3 years ago

@grey280 I got it working:

        string ProduceDictionaryType(Type type) {
            bool endsWithBrackets = type.TypeArguments.Last().Name.ToLower().EndsWith("[]");
            bool isEnumerable = type.TypeArguments.Last().FullName.StartsWith("System.Collections");
            bool isNullableString = endsWithBrackets && !isEnumerable;

            var suffix = isNullableString ? " | null | undefined" : "";

            var valueType = isNullableString ?
                $"{type.TypeArguments.Last().Name.Substring(0, type.TypeArguments.Last().Name.Length - 2)}"
                : type.TypeArguments.Last().Name;

            return $"{{ [key: {type.TypeArguments.First()}]: {valueType}{suffix}; }}";
        }
johnknoop commented 3 years ago

Now the last thing I need in order to be able to start using TypeWriter again, is nullable reference types that aren't strings.

AdaskoTheBeAsT commented 2 years ago

fixed in unoffical release https://github.com/AdaskoTheBeAsT/Typewriter