Skip to content

Commit

Permalink
fix(api): change representation of nullable types to union with null …
Browse files Browse the repository at this point in the history
…instead of optional parameter
  • Loading branch information
George Kinsman committed Sep 25, 2018
1 parent 279d6fc commit c31ec95
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 20 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ declare namespace Api {

## Nullable Value Types

Nullable value types are rendered to optional properties in TypeScript:
Nullable value types are rendered to properties with a null union in TypeScript:

```csharp
class TypeWithNullable
Expand All @@ -170,8 +170,8 @@ class TypeWithNullable
```TypeScript
declare namespace Api {
interface TypeWithNullable {
nullableInt?: number;
nullableGuid?: string;
nullableInt: number | null;
nullableGuid: string | null;
}
}
```
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
declare namespace Api {
interface TypeWithNullableEnum {
nullableEnumProp?: 'FirstEnum' | 'SecondEnum' | 'ThirdEnum';
nullableEnumProp: 'FirstEnum' | 'SecondEnum' | 'ThirdEnum' | null;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ declare namespace Api {
nestedThing: NestedType;
}
interface NestedType {
nullableInt?: number;
nullableInt: number | null;
nullableDateTime: string;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
declare namespace Api {
interface TypeWithNullable {
nullableInt?: number;
nullableGuid?: string;
nullableInt: number | null;
nullableGuid: string | null;
}
}
33 changes: 20 additions & 13 deletions src/Typescriptr/TypeScriptGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
namespace Typescriptr
{
public delegate string FormatEnum(Type t, QuoteStyle quoteStyle);

public delegate string FormatEnumProperty(Type t, QuoteStyle quoteStyle);

public delegate string FormatDictionaryProperty(Type t, Func<Type, string> typeNameRenderer);

public delegate string FormatCollectionProperty(Type t, Func<Type, string> typeNameRenderer);

public class TypeScriptGenerator
Expand Down Expand Up @@ -55,7 +58,8 @@ private TypeScriptGenerator()
.WithPropertyTypeFormatter<TimeSpan>(t => "string")
.WithPropertyTypeFormatter<Guid>(t => "string")
.WithPropertyTypeFormatter<DateTimeOffset>(t => "string")
.WithEnumFormatter(EnumFormatter.ValueNamedEnumFormatter, EnumFormatter.UnionStringEnumPropertyTypeFormatter)
.WithEnumFormatter(EnumFormatter.ValueNamedEnumFormatter,
EnumFormatter.UnionStringEnumPropertyTypeFormatter)
.WithQuoteStyle(QuoteStyle.Single)
.WithDictionaryPropertyFormatter(DictionaryPropertyFormatter.KeyValueFormatter)
.WithCollectionPropertyFormatter(CollectionPropertyFormatter.Format)
Expand All @@ -73,13 +77,13 @@ public TypeScriptGenerator WithQuoteStyle(QuoteStyle style)
_quoteStyle = style;
return this;
}

public TypeScriptGenerator WithNamespace(string @namespace)
{
_namespace = @namespace;
return this;
}

public TypeScriptGenerator WithDictionaryPropertyFormatter(FormatDictionaryProperty formatter)
{
_dictionaryPropertyFormatter = formatter;
Expand Down Expand Up @@ -142,7 +146,7 @@ public GenerationResult Generate(IEnumerable<Type> types)
{
typeBuilder.AppendLine();
}

return new GenerationResult(typeBuilder.ToString(), enumBuilder.ToString());
}

Expand All @@ -165,8 +169,6 @@ private void RenderType(StringBuilder builder, Type type)

if (_useCamelCasePropertyNames)
propName = propName.ToCamelCase();
if (Nullable.GetUnderlyingType(propType) != null)
propName = $"{propName}?";

RenderProperty(builder, propType, propName);
}
Expand All @@ -182,25 +184,30 @@ private void RenderType(StringBuilder builder, Type type)

private string TypeNameRenderer(Type type)
{
Func<string, string> decorate = str => str;

if (Nullable.GetUnderlyingType(type) != null)
{
type = Nullable.GetUnderlyingType(type);
decorate = str => str + " | null";
}

if (_propTypeMap.ContainsKey(type))
return _propTypeMap[type];
return decorate(_propTypeMap[type]);

if (typeof(IDictionary).IsAssignableFrom(type))
return _dictionaryPropertyFormatter(type, TypeNameRenderer);
return decorate(_dictionaryPropertyFormatter(type, TypeNameRenderer));

if (typeof(IEnumerable).IsAssignableFrom(type))
return _collectionPropertyFormatter(type, TypeNameRenderer);
return decorate(_collectionPropertyFormatter(type, TypeNameRenderer));

var typeName = type.Name;
if (typeof(Enum).IsAssignableFrom(type))
typeName = _enumPropertyFormatter(type, _quoteStyle);

if (!_typesGenerated.Contains(type)) _typeStack.Push(type);
return typeName;

return decorate(typeName);
}

private void RenderProperty(StringBuilder builder, Type propType, string propName)
Expand Down

0 comments on commit c31ec95

Please sign in to comment.