private void WriteConstructorToBlock(TypeScriptBlock classBlock, WebApiAction action, WebApiHttpVerb verb) { var actionName = action.GetActionNameForVerb(verb); var constructorParameterMappings = action.GetConstructorParameterMappings(); var areAllParametersOptional = constructorParameterMappings .All(m => m.IsOptional); var optionalString = areAllParametersOptional ? "?" : string.Empty; var constructorBlock = classBlock .AddAndUseBlock($"constructor(args{optionalString}: I{actionName})"); foreach (var mapping in constructorParameterMappings) { constructorBlock .AddStatement($"this.{mapping.Name} = args != null ? args.{mapping.Name} : null;"); if (mapping.TypeMapping?.AutoInitialize ?? false) { constructorBlock .AddAndUseBlock($"if (this.{mapping.Name} == null)") .AddStatement($"this.{mapping.Name} = new {mapping.TypeMapping.TypeScriptTypeName}();"); } } }
private void WriteGetQueryStringToBlock(TypeScriptBlock classBlock, string actionName, WebApiAction action) { var queryStringParameters = action.QueryStringParameters; if (!queryStringParameters.Any()) { return; } var queryStringBlock = classBlock .AddAndUseBlock($"{actionName}.prototype.getQueryString = function(): string") .AddStatement("var parameters: string[] = [];"); foreach (var routePart in queryStringParameters) { var argumentName = routePart.Name; var block = queryStringBlock; var argumentType = routePart.GetTypeScriptType(); block.AddStatement($"addParameter(parameters, '{argumentName}', this.{argumentName});"); } queryStringBlock .AddAndUseBlock("if (parameters.length > 0)") .AddStatement("return '?' + parameters.join('&');") .Parent .AddStatement("return '';"); }
public TypeScriptBlock CreateEndpointBlock() { var block = new TypeScriptBlock($"{Config.NamespaceOrModuleName} {Config.EndpointsNamespace}"); block .AddAndUseBlock($"export interface {IEndpoint}") .AddStatement("_verb: string;") .AddStatement("toString(): string;") .Parent .AddAndUseBlock("function addParameter(parameters: string[], key: string, value: any)") .AddAndUseBlock("if (value == null)") .AddStatement("return;") .Parent .AddAndUseBlock($"if (_.isArray(value))") .AddStatement($"var encodedItems = _.map(value, (item: any) => encodeURIComponent(item.toString()));") .AddStatement($"_(encodedItems).each(item => parameters.push(`${{key}}=${{item}}`));") .Parent .AddAndUseBlock("else if (_.isObject(value) && value.getQueryParams)") .AddStatement(@"addParameter(parameters, key, value.getQueryParams());") .Parent .AddAndUseBlock("else if (_.isObject(value))") .AddStatement(@"Object.keys(value).forEach((key) => { addParameter(parameters, key, value[key]); });") .Parent .AddAndUseBlock("else") .AddStatement($"parameters.push(`${{key}}=${{encodeURIComponent(value.toString())}}`);"); return(block); }
private void WriteViewEntry(TypeScriptBlock viewsBlock, ViewNode featureViewNode, bool isChild = false) { var namespaceBlock = !isChild ? $"export namespace {featureViewNode.Name}" : $"{featureViewNode.Name} : "; var featureBlock = viewsBlock .AddAndUseBlock(namespaceBlock, terminationString: isChild ? "," : ""); var viewGroup = Config.UseViewsGroupingNamespace && !isChild ? "Views" : string.Empty; if (!string.IsNullOrEmpty(viewGroup)) { featureBlock = featureBlock.AddAndUseBlock($"export var {viewGroup} = "); } foreach (var viewEntry in featureViewNode.ViewEntries) { featureBlock .AddStatement($"{viewEntry.Name} : '{viewEntry.Path}',"); } foreach (var childView in featureViewNode.ChildViews) { WriteViewEntry(featureBlock, childView, isChild: true); } }
public void WriteEndpointClassToBlock(TypeScriptBlock endpointsBlock, WebApiController webApiController) { var controllerBlock = endpointsBlock .AddAndUseBlock($"export {Config.NamespaceOrModuleName} {webApiController.Name}"); var actions = webApiController.Actions.Where(a => a.IsMobileAction); foreach (var action in actions) { if (action.BodyParameters.Count > 1) { LogMessage($"Multiple conflicting call parameters detected in action [{action.Name}] of controller [{webApiController.Name}]!"); LogMessage("Please use [FromBody] or [FromUri] on all non-primitives!"); var parameters = action.BodyParameters.Select(bp => $"[{bp.Name}]"); LogMessage($"Parameters: {string.Join(" ", parameters)}"); LogMessage(""); continue; } foreach (var verb in action.Verbs) { var actionName = action.GetActionNameForVerb(verb); var interfaceBlock = controllerBlock .AddAndUseBlock($"export interface I{actionName}"); WriteInterfaceToBlock(interfaceBlock, action); var endpointBlock = controllerBlock .AddAndUseBlock($"export interface I{actionName}Endpoint extends I{actionName}, IEndpoint"); var ctorBlock = controllerBlock .AddAndUseBlock($"export interface I{actionName}Ctor") .AddStatement($"new(args?: I{actionName}): I{actionName}Endpoint"); var ctorImplBlock = controllerBlock .AddAndUseBlock($"export var {actionName} : I{actionName}Ctor = <any>(function(args?: I{actionName})", false, ");") .AddStatement($"this._verb = '{verb.VerbMethod}';"); var constructorParameterMappings = action.GetConstructorParameterMappings(ignoreEnumDefinitions: true); foreach (var mapping in constructorParameterMappings) { ctorImplBlock.AddStatement($"this.{mapping.Name} = args != null ? args.{mapping.Name} : null;"); if (mapping.TypeMapping?.AutoInitialize ?? false) { ctorImplBlock .AddAndUseBlock($"if (this.{mapping.Name} == null)") .AddStatement($"this.{mapping.Name} = new {mapping.TypeMapping.TypeScriptTypeName}();"); } } WriteGetQueryStringToBlock(controllerBlock, actionName, action); WriteToStringToBlock(controllerBlock, actionName, action); } } }
public void WriteEndpointClassToBlock(TypeScriptBlock endpointBlock, WebApiController webApiController) { var controllerBlock = endpointBlock .AddAndUseBlock($"export {Config.NamespaceOrModuleName} {webApiController.Name}"); TypeScriptBlock serviceBlock = null; if (Config.GenerateService) { serviceBlock = controllerBlock .AddAndUseBlock($"export interface I{webApiController.Name}Service"); } var actions = webApiController.Actions; foreach (var action in actions) { foreach (var verb in action.Verbs) { var actionName = action.GetActionNameForVerb(verb); var interfaceBlock = controllerBlock .AddAndUseBlock($"export interface I{actionName}"); WriteInterfaceToBlock(interfaceBlock, action); if (Config.GenerateService) { var interfaceWithCallBlock = controllerBlock .AddAndUseBlock($"export interface I{actionName}WithCall extends I{actionName}, {IEndpoint}"); WriteInterfaceWithCallToBlock(interfaceWithCallBlock, action, verb); serviceBlock .AddStatement($"{actionName}: (args?: I{actionName}) => I{actionName}WithCall"); } var classBlock = controllerBlock .AddAndUseBlock($"export class {actionName} implements I{actionName}, {IEndpoint}") .AddStatement($"_verb = '{verb.VerbMethod}';"); var constructorParameterMappings = action.GetConstructorParameterMappings(); foreach (var constructorParameterMapping in constructorParameterMappings) { classBlock .AddStatement($"{constructorParameterMapping.String};"); } WriteConstructorToBlock(classBlock, action, verb); WriteGetQueryStringToBlock(classBlock, action); WriteToStringToBlock(classBlock, action); } } }
private void WriteToStringToBlock(TypeScriptBlock classBlock, WebApiAction action) { var toStringBlock = classBlock .AddAndUseBlock("toString = (): string =>"); var queryString = action.QueryStringParameters.Any() ? " + this.getQueryString()" : string.Empty; toStringBlock .AddStatement($"return `{action.Controller.BaseEndpoint}{action.Endpoint}`{queryString};"); }
private void CreateEnumForType(TypeScriptBlock enumsBlock, TypeDefinition typeDefinition) { var fields = typeDefinition.Fields .Where(f => f.HasConstant && !f.IsSpecialName); var enumBlock = enumsBlock .AddAndUseBlock($"export enum {typeDefinition.Name}"); foreach (var field in fields) { enumBlock.AddStatement($"{field.Name} = {field.Constant},"); } }
public void WriteServiceObjectToBlock(TypeScriptBlock serviceBlock, WebApiController webApiController) { var controllerBlock = serviceBlock .AddAndUseBlock($"public {webApiController.Name} ="); var actions = webApiController.Actions; for (var a = 0; a < actions.Count; a++) { var action = actions[a]; var constructorParameterMappings = action.GetConstructorParameterMappings(); for (var v = 0; v < action.Verbs.Count; v++) { var verb = action.Verbs[v]; var actionName = action.GetActionNameForVerb(verb); var isLastActionAndVerb = a == actions.Count - 1 && v == action.Verbs.Count - 1; var areAllParametersOptional = constructorParameterMappings .All(m => m.IsOptional); var optionalString = areAllParametersOptional ? "?" : string.Empty; var callArgumentDefinition = action.GetCallArgumentDefinition(verb); var callArgumentValue = action.GetCallArgumentValue(verb); var interfaceFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.I{actionName}"; var interfaceWithCallFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.I{actionName}WithCall"; var endpointFullName = $"{Config.EndpointsNamespace}.{webApiController.Name}.{actionName}"; controllerBlock .AddAndUseBlock ( outer: $"{actionName}: (args{optionalString}: {interfaceFullName}): {interfaceWithCallFullName} =>", isFunctionBlock: false, terminationString: !isLastActionAndVerb ? "," : string.Empty ) .AddStatement($"var endpoint = new {endpointFullName}(args);") .AddAndUseBlock("return _.extendOwn(endpoint,", isFunctionBlock: true, terminationString: ";") .AddAndUseBlock($"call<TView>({callArgumentDefinition})") .AddStatement($"return {Config.ServiceName}.call<TView>(this, {callArgumentValue});"); } } }
private void CreateGetDescriptionExtensionForType(TypeScriptBlock enumsBlock, TypeDefinition typeDefinition) { var fields = typeDefinition.Fields .Where(f => f.HasConstant && !f.IsSpecialName); var switchBlock = enumsBlock .AddAndUseBlock($"export namespace {typeDefinition.Name}") .AddAndUseBlock($"export function getDescription(enumValue: {typeDefinition.Name})") .AddAndUseBlock("switch (enumValue)"); foreach (var field in fields) { var fieldDescription = GetFieldDescription(field); switchBlock .AddStatement($"case {typeDefinition.Name}.{field.Name}: return \"{fieldDescription}\";"); } }
private void WriteViewEntry(TypeScriptBlock viewsBlock, ViewNode featureViewNode, bool isChild = false) { var viewNamespace = Config.UseViewsGroupingNamespace && !isChild ? ".Views" : string.Empty; var featureBlock = viewsBlock .AddAndUseBlock($"export namespace {featureViewNode.Name}{viewNamespace}"); foreach (var viewEntry in featureViewNode.ViewEntries) { featureBlock .AddStatement($"export const {viewEntry.Name} = '{viewEntry.Path}';"); } foreach (var childView in featureViewNode.ChildViews) { WriteViewEntry(featureBlock, childView, isChild: true); } }
private void WriteGetQueryStringToBlock(TypeScriptBlock classBlock, WebApiAction action) { var queryStringParameters = action.QueryStringParameters; if (!queryStringParameters.Any()) { return; } var queryStringBlock = classBlock .AddAndUseBlock("private getQueryString = (): string =>") .AddStatement("var parameters: string[] = [];"); foreach (var routePart in queryStringParameters) { var argumentName = routePart.Name; var block = queryStringBlock; var argumentType = routePart.GetTypeScriptType(); if (argumentType.IsPrimitive || argumentType.IsEnum) { block .AddStatement($"addParameter(parameters, '{argumentName}', this.{argumentName});"); } else { block .AddStatement($"addObjectParameters(parameters, this.{argumentName});"); } } queryStringBlock .AddAndUseBlock("if (parameters.length > 0)") .AddStatement("return '?' + parameters.join('&');") .Parent .AddStatement("return '';"); }
private void WriteInterfaceNode(TypeScriptBlock interfacesBlock, InterfaceNode interfaceNode) { var typeDefinition = interfaceNode.TypeDefinition; string implementsString = null; string extendsString = null; var iHaveGenericParameters = typeDefinition.HasGenericParameters; if (iHaveGenericParameters) { var genericParameters = typeDefinition.GenericParameters .Select(p => p.Name); implementsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } var hasBaseClass = interfaceNode.BaseInterface?.TypeDefinition != null; var baseTypeName = CleanName(interfaceNode.BaseInterface?.TypeDefinition?.Name); if (hasBaseClass) { var iHaveGenericArguments = typeDefinition.BaseType.IsGenericInstance; if (iHaveGenericArguments) { var baseTypeInstance = typeDefinition.BaseType as GenericInstanceType; var genericArguments = baseTypeInstance.GenericArguments .Select(p => p.IsGenericParameter ? p.Name : TypeService.GetTypeScriptType(p.GetElementType(), p.Name).TypeName); extendsString = WrapInAngledBrackets(string.Join(", ", genericArguments)); } var baseTypeHasGenericParameters = typeDefinition.BaseType.HasGenericParameters; if (baseTypeHasGenericParameters) { var genericParameters = typeDefinition.BaseType.GenericParameters .Select(p => p.Name); extendsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } } var interfaceExtendsString = hasBaseClass ? $" extends I{baseTypeName}{extendsString}" : string.Empty; var classExtendsString = hasBaseClass ? $" extends {baseTypeName}{extendsString}" : string.Empty; var blockTypeName = CleanName(typeDefinition.Name); if (!TypeService.IsValidTypeName(blockTypeName)) { LogMessage($"Interface name [{blockTypeName}] of type [{typeDefinition.FullName}] is invalid!"); return; } var classImplementsString = $" implements I{blockTypeName}{implementsString}"; var parameterOrInstanceString = iHaveGenericParameters ? implementsString : string.Empty; var interfaceBlock = interfacesBlock .AddAndUseBlock($"export interface I{blockTypeName}{parameterOrInstanceString}{interfaceExtendsString}"); TypeScriptBlock classBlock = null; if (Config.GenerateInterfaceClasses) { classBlock = interfacesBlock .AddAndUseBlock($"export class {blockTypeName}{parameterOrInstanceString}{classExtendsString}{classImplementsString}"); } var things = GetMembers(typeDefinition); foreach (var thing in things) { var thingType = thing.CSharpType.TypeDefinition; var union = SameNamedDerivedMembers(thing, interfaceNode) .Select(e => e.CSharpType.TypeDefinition) .ToList(); union.Add(thingType); string interfaceName; string typeName; if (thing.CSharpType.IsGenericParameter) { typeName = interfaceName = thing.CSharpType.GenericParameterName; } else { if (thingType.IsInterface) { continue; } if (union.Count == 1) { var typeScriptType = TypeService.GetTypeScriptType(union[0], thing.Name); interfaceName = typeScriptType.InterfaceName; typeName = typeScriptType.TypeName; } else { typeName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.TypeName); }) .Distinct()); interfaceName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.InterfaceName); }).Distinct()); } } var thingName = Config.InterfaceMembersInCamelCase ? Helpers.ToCamelCaseFromPascalCase(thing.Name) : thing.Name; var collectionString = thing.CSharpType.IsCollection ? "[]" : string.Empty; thingName = TypeService.FixIfReservedWord(thingName); interfaceBlock .AddStatement($"{thingName}: {interfaceName}{collectionString};"); if (Config.GenerateInterfaceClasses) { classBlock .AddStatement($"{thingName}: {typeName}{collectionString};"); } } if (Config.GenerateInterfaceClasses) { if (hasBaseClass) { classBlock .AddAndUseBlock("constructor()") .AddStatement("super();"); } } }
private void WriteInterfaceNode(TypeScriptBlock interfacesBlock, InterfaceNode interfaceNode) { var typeDefinition = interfaceNode.TypeDefinition; string implementsString = null; string _interfaceExtendsString = null; string _classExtendsString = null; var iHaveGenericParameters = typeDefinition.HasGenericParameters; if (iHaveGenericParameters) { var genericParameters = typeDefinition.GenericParameters .Select(p => p.Name); implementsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } var hasBaseClass = interfaceNode.BaseInterface?.TypeDefinition != null; var baseTypeName = TypeService.CleanGenericName(interfaceNode.BaseInterface?.TypeDefinition?.Name); var things = GetMembers(typeDefinition); if (hasBaseClass) { if (typeDefinition.BaseType is GenericInstanceType baseTypeInstance) { var classGenericArguments = baseTypeInstance.GenericArguments .Select(p => p.IsGenericParameter ? p.Name : TypeService.GetTypeScriptType(p.GetElementType(), p.Name).TypeName); var interfaceGenericArguments = baseTypeInstance.GenericArguments .Select(p => p.IsGenericParameter ? p.Name : TypeService.GetTypeScriptType(p.GetElementType(), p.Name).InterfaceName); _classExtendsString = WrapInAngledBrackets(string.Join(", ", classGenericArguments)); _interfaceExtendsString = WrapInAngledBrackets(string.Join(", ", interfaceGenericArguments)); } else { var baseTypeHasGenericParameters = typeDefinition.BaseType.HasGenericParameters; if (baseTypeHasGenericParameters) { var genericParameters = typeDefinition.BaseType.GenericParameters .Select(p => p.Name); _classExtendsString = _interfaceExtendsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } } } var interfaceExtendsString = hasBaseClass ? $" extends I{baseTypeName}{_interfaceExtendsString}" : string.Empty; var classExtendsString = hasBaseClass ? $" extends {baseTypeName}{_classExtendsString}" : string.Empty; var blockTypeName = TypeService.CleanGenericName(typeDefinition.Name); if (!TypeService.IsValidTypeName(blockTypeName)) { LogMessage($"Interface name [{blockTypeName}] of type [{typeDefinition.FullName}] is invalid!"); return; } var classImplementsString = $" implements I{blockTypeName}{implementsString}"; var parameterOrInstanceString = iHaveGenericParameters ? implementsString : string.Empty; var interfaceBlock = interfacesBlock .AddAndUseBlock($"export interface I{blockTypeName}{parameterOrInstanceString}{interfaceExtendsString}"); TypeScriptBlock classBlock = null; if (Config.GenerateInterfaceClasses) { classBlock = interfacesBlock .AddAndUseBlock($"export class {blockTypeName}{parameterOrInstanceString}{classExtendsString}{classImplementsString}"); } foreach (var thing in things) { var thingType = thing.CSharpType.TypeDefinition; var union = SameNamedDerivedMembers(thing, interfaceNode) .Select(e => e.CSharpType.TypeDefinition) .ToList(); union.Add(thingType); string interfaceName; string typeName; if (thing.CSharpType.IsGenericParameter) { typeName = interfaceName = thing.CSharpType.GenericParameterName; } else if (thing.CSharpType.IsGenericInstance) { var baseTypeScriptType = TypeService.GetTypeScriptType(thing.CSharpType.TypeDefinition, thing.Name); if (baseTypeScriptType.IsMappedType) { typeName = baseTypeScriptType.TypeName; interfaceName = baseTypeScriptType.InterfaceName; } else { var typeNames = string.Join(", ", thing.CSharpType.GenericArgumentTypes .Select(t => { var genericArgumentTypeScriptType = TypeService.GetTypeScriptType(t, thing.Name); return(genericArgumentTypeScriptType.TypeName); })); var interfaceNames = string.Join(", ", thing.CSharpType.GenericArgumentTypes .Select(t => { var genericArgumentTypeScriptType = TypeService.GetTypeScriptType(t, thing.Name); return(genericArgumentTypeScriptType.InterfaceName); })); typeName = $"{baseTypeScriptType.TypeName}<{typeNames}>"; interfaceName = $"{baseTypeScriptType.InterfaceName}<{interfaceNames}>"; } } else { if (thingType.IsInterface) { continue; } if (union.Count == 1) { var typeScriptType = TypeService.GetTypeScriptType(union[0], thing.Name); typeName = typeScriptType.TypeName; interfaceName = typeScriptType.InterfaceName; } else { typeName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.TypeName); }) .Distinct()); interfaceName = string.Join(" | ", union .Select(t => { var type = TypeService.GetTypeScriptType(t, thing.Name); return(type.InterfaceName); }).Distinct()); } } var thingName = thing.Name; var jsonProperty = thing.CustomAttributes.SingleOrDefault(a => a.AttributeType.Name == "JsonPropertyAttribute"); if (jsonProperty != null) { try { thingName = jsonProperty?.HasProperties ?? false ? jsonProperty.Properties.Single(p => p.Name == "PropertyName").Argument.Value.ToString() : jsonProperty?.HasConstructorArguments ?? false ? jsonProperty.ConstructorArguments.Single().Value.ToString() : thing.Name; } catch { // This is to suppress a assembly load execption which I am unsure of why it is happening } } if (Config.InterfaceMembersInCamelCase || typeDefinition.CustomAttributes.Any(a => a.AttributeType.Name == Config.InterfaceCamelCaseCustomAttribute)) { thingName = Helpers.ToCamelCaseFromPascalCase(thingName); } var collectionString = Helpers.GetCollectionPostfix(thing.CSharpType.CollectionLevel); thingName = TypeService.FixIfReservedWord(thingName); interfaceBlock .AddStatement($"{thingName}: {interfaceName}{collectionString};"); if (Config.GenerateInterfaceClasses) { classBlock .AddStatement($"{thingName}: {typeName}{collectionString};"); } } if (Config.GenerateInterfaceClasses) { if (hasBaseClass) { classBlock .AddAndUseBlock("constructor()") .AddStatement("super();"); } } }
private void WriteInterfaces(TypeScriptBlock interfacesBlock, InterfaceNode interfaceNode) { var typeDefinition = interfaceNode.TypeDefinition; if (typeDefinition != null) { string implementsString = null; string extendsString = null; var iHaveGenericParameters = typeDefinition.HasGenericParameters; if (iHaveGenericParameters) { var genericParameters = typeDefinition.GenericParameters .Select(p => p.Name); implementsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } var hasBaseClass = interfaceNode.BaseInterface?.TypeDefinition != null; var baseTypeName = CleanName(interfaceNode.BaseInterface?.TypeDefinition?.Name); if (hasBaseClass) { var iHaveGenericArguments = typeDefinition.BaseType.IsGenericInstance; if (iHaveGenericArguments) { var baseTypeInstance = typeDefinition.BaseType as GenericInstanceType; var genericArguments = baseTypeInstance.GenericArguments .Select(p => p.IsGenericParameter ? p.Name : TypeService.GetTypeScriptType(p.GetElementType(), p.Name).TypeName); extendsString = WrapInAngledBrackets(string.Join(", ", genericArguments)); } var baseTypeHasGenericParameters = typeDefinition.BaseType.HasGenericParameters; if (baseTypeHasGenericParameters) { var genericParameters = typeDefinition.BaseType.GenericParameters .Select(p => p.Name); extendsString = WrapInAngledBrackets(string.Join(", ", genericParameters)); } } var interfaceExtendsString = hasBaseClass ? $" extends I{baseTypeName}{extendsString}" : string.Empty; var classExtendsString = hasBaseClass ? $" extends {baseTypeName}{extendsString}" : string.Empty; var blockTypeName = CleanName(typeDefinition.Name); var classImplementsString = $" implements I{blockTypeName}{implementsString}, {Config.EndpointsNamespace}.{nameof(IHaveQueryParams)}"; var parameterOrInstanceString = iHaveGenericParameters ? implementsString : string.Empty; var interfaceBlock = interfacesBlock .AddAndUseBlock($"export interface I{blockTypeName}{parameterOrInstanceString}{interfaceExtendsString}"); var classBlock = interfacesBlock .AddAndUseBlock($"export class {blockTypeName}{parameterOrInstanceString}{classExtendsString}{classImplementsString}"); var things = GetMembers(typeDefinition); foreach (var thing in things) { var interfaceName = string.Empty; var typeName = string.Empty; if (thing.CSharpType.IsGenericParameter) { typeName = interfaceName = thing.CSharpType.GenericParameterName; } else { var thingType = thing.CSharpType.TypeDefinition; var typeScriptType = TypeService.GetTypeScriptType(thingType, thing.Name); interfaceName = typeScriptType.InterfaceName; typeName = typeScriptType.TypeName; } var thingName = Config.InterfaceMembersInCamelCase ? Helpers.ToCamelCaseFromPascalCase(thing.Name) : thing.Name; var collectionString = thing.CSharpType.IsCollection ? "[]" : string.Empty; interfaceBlock .AddStatement($"{thingName}: {interfaceName}{collectionString};"); classBlock .AddStatement($"{thingName}: {typeName}{collectionString};"); } if (hasBaseClass) { classBlock .AddAndUseBlock("constructor()") .AddStatement("super();"); } classBlock .AddAndUseBlock("getQueryParams()") .AddStatement("return this;"); } foreach (var derivedInterfaceNode in interfaceNode.DerivedInterfaces) { WriteInterfaces(interfacesBlock, derivedInterfaceNode); } }