Skip to content

Fluent configuration

Steven Fowler edited this page Jan 16, 2019 · 20 revisions

Fluent configuration is Reinforced.Typings configuration specified as sequence of calls to Reinforced.Typings.Fluent.ConfigurationBuilder class. It is easier to use than attributes configuration in some cases. Anyway fluent configuration does not restrict attributes configuration. So attributes are safe to be used together with fluent configuration.

Important! If attributes configuration are contrary to the fluent configuration then RT will act according to fluent configuration.

Table of contents

Starting with fluent configuration

To enable fluent configuration for Reinforced.Typings follow 3 simple steps:

  1. Create a static class containing a static method that consumes instance of Reinforced.Typings.Fluent.ConfigurationBuilder as follows:

    using Reinforced.Typings.Fluent;
    
    namespace YourProjectNamespace {
        public static class ReinforcedTypingsConfiguration
        {
            public static void Configure(ConfigurationBuilder builder)
            {
                // fluent configuration goes here
            }
        }    
    }
  2. Go to Reinforced.Typings.settings.xml and set there RtConfigurationMethod parameter to a full-qualified name of Configure method as follows:

    ...
        <RtConfigurationMethod>YourProjectNamespace.ReinforcedTypingsConfiguration.Configure</RtConfigurationMethod>
    ...
  3. Rebuild your solution. Your TypeScript code will be generated according to calls made to ConfigurationBuilder.

Configuration builder methods - single and plural

Configuration builder contains 8 main methods:

  • ExportAsInterface/ExportAsInterfaces
  • ExportAsClass/ExportAsClasses
  • ExportAsEnum/ExportAsEnums
  • ExportAsThirdParty (x2 variations)

Lets call:

  • ExportAsInterface, ExportAsClass, ExportAsEnum - "Single" configuration builder methods
  • ExportAsInterfaces, ExportAsClasses, ExportAsEnums, ExportAsThirdParty - "Plural" configuration builder methods

"Single" versions of these methods requires to specify exported type as follows:

public static void Configure(ConfigurationBuilder builder)
{
    builder.ExportAsInterface<IMyInterface>();
}

"Single" versions returns instance of interface/class/enum generic configuration builder. To configure exporting details for specified type you should simply continue call chain like this:

public static void Configure(ConfigurationBuilder builder)
{
    builder.ExportAsInterface<IMyInterface>()
            .WithPublicMethods()        // extension methods calls
            .WithPublicProperties()     // to interface configuration builder`
            .OverrideName("IMyCustomInterface");
}

Also it is safe to perform multiple "single" method calls:

public static void Configure(ConfigurationBuilder builder)
{
    builder.ExportAsInterface<IMyInterface>()
            .WithProperty(c => c.MyProperty, p => p.CamelCase());
            
    builder.ExportAsInterface<IMyInterface>()
            .WithProperty(c => c.AnotherProperty, p => p.Type<Func<int,bool>>()); // no crime!
}

"Plural" versions of these methods consumes 2 parameters:

  • set (IEnumerable) of types to be exported
  • action that should be performed on each type's configuration builder

Fluent configuration for "plural" methods looks like this:

public static void Configure(ConfigurationBuilder builder)
{
    builder.ExportAsInterfaces(
        new Type[] {    typeof(IMyInterface), 
                        typeof(IAnotherInterface), 
                        typeof(MyClass)
                   },
        conf => conf.WithPublicMethods().WithPublicProperties();
    );
    // this will export IMyInterface, IAnotherInterface, MyClass
    // as TS interfaces including all public methods and all public properties            
}

Note that in "single" fluent methods returns generic builders but "plural" doesn't. So you can use strongly typed calls e.g. to specify configuration for particular properties when you are using "single" method. Due to C# type system this approach is not applicable for "plural" methods:

public static void Configure(ConfigurationBuilder builder)
{
    // look, I can do this for .ExportAsInterface<T>!
    builder.ExportAsInterface<IMyInterface>()
            .WithProperty(c => c.MyProperty, p => p.CamelCase()); 
       
    builder.ExportAsInterfaces(
        new Type[] { typeof(IMyInterface) },
        conf => conf
            .WithPublicMethods()
            .WithPublicProperties()
            // but cannot for .ExportAsInterfaces :(
            // .WithProperty(c => c.MyProperty, p => p.CamelCase()) 
            
            // but still can do like this! :)
            .WithProperties(
                prop => prop.Name == "MyProperty",
                conf => conf.CamelCase())
            ;
    );           
}

Classes, interfaces and enums are exported differently. For further information see which fluent methods present for interfaces, classes and enums. Also some types can be exported as third-party types

Global configuration builder

Since varsion 1.3.0 ConfigurationBuilder contains .Global method that supplies configuration action for global configuration builder. Basically it contains all the same parameters as [[TsGlobal attribute|Configuration-attributes]] but optimized for fluent usage. Basic usage is: builder.Global(x=>x.DontWriteWarningComment()). Global configuration builder contains following methods:

Method Parameters Description
DontWriteWarningComment bool dontWrite = true Disables writing of "auto-generated warning" comment to each generated file. It meant the comment like // This code was generated blah blah blah.... 'true' (default) will disable this comment. false will restore it back.
RootNamespace string ns Specifies your app's root namespace. Useful in case of using RtDivideTypesAmongFiles. It is needed to make Reinforced.Typings do not create redundant directories under RtTargetDirectory since there is no way to determine root namespace programmatically.
CamelCaseForMethods bool cameCase = true When true, forces Reinforced.Typings to generate METHODS names in "camelCase" instead of .NET-common "PascalCase"
CamelCaseForProperties bool cameCase = true When true, forces Reinforced.Typings to generate PROPERTIES names in "camelCase" instead of .NET-common "PascalCase"
GenerateDocumentation bool generate = true This setting controls JSDOC generation for your exported TypeScript from .NET XMLDOC. Check out how to use JSDOC generation [[here
TabSymbol string symbol Specifies symbol used for tabulation. By default tabulation symbol - '\t' is used.
UseModules bool useModules = true
bool discardNamespaces = true
Switches RT to using TS modules system (--module tsc.exe parameter) with types exports/imports. import directives will not appear in your export results until you set this useModules parameter to true. For more flexibility, 2nd related parameter - discardNamespaces is also moved to this method. When it is true then RT will totally ignore all namespaces when exporting. This parameter does not work without useModules parameter
ExportPureTypings bool typings = true Since .d.ts has a slightly different syntax than a regular .ts file, RT has that boolean parameter that controls generation mode switch between .ts/.d.ts. If typings set to true, then export will be performed in .d.ts manner (only typings, declare module etc). Otherwise, export will be performed in manner of regular .ts file
WithReferencesProcessor where T: ReferenceProcessorBase Specify here class, that inherit ReferenceProcessorBase to obtain more flexible control over all generated references and imports. You can obtain example of usage here
ReorderMembers bool reorder = true Enables or disables exporting members reordering (aphabetical, constructors-fields-properties-methods). Warning! Enabling this option discards .Order calls as well as Order property of member attributes - such like [TsProperty(Order = 10)], [TsFunction(Order=20)] etc
AutoOptionalProperties bool autoOptional = true Tells RT to export all nullable value-type properties as optional automatically. So it will turn your public bool? IsAlive {get;set;} into IsAlive?:boolean; without additional usage of ForceNullable. The things around this option are being explained here

Core ConfigurationBuilder methods

Besides methods mentioned above ConfigurationBuilder has 4 more:

AddImport

Specifies import directive that will appear in each exported files when exporting to multiple files. This method will not take effect until .Global(x=>x.UseModules(true)) called.

Arguments:

  • string target: What is being imported from module. Literally, everything that is placed after import keyword and before from or = require(..). If ImportTarget is null then side-effect import will be generated.
  • string from: Import source is everything that follows after from keyword. Please note that you do not have to specify quotes here! Quotes will be added automatically
  • bool isRequire = false: When true, require-import will be generated like: import %ImportTarget% = require('%ImportSource%')

Examples of target parameter:

  • import * as shape from './Shapes' -> * as shape is target
  • import { Foo } from 'Bar' -> { Foo } is target
  • import { Bar2 as bar } from 'Baz' -> { Bar2 as bar } is target

AddReference

Specifies path to file that will be written in ///<reference path="..."> directive that will be placed on top of every generated file (analogue for [TsReference] attribute)

Please note that AddReference will not stop work even if you are using modules export

Arguments: string reference: path for ///<reference ...> directive being added to each exported file

TryLookupDocumentationForAssembly

Tries to find documentation .xml file for specified assembly and take it in account when generating documentaion. See details on JSDOC support page

Arguments:

  • Assembly assmbly: Assembly which documentation should be included
  • string documentationFileName = null: Override XMLDOC file name if differs (please include .xml extension)

Substitute

This method is used for handling substitutions. To know how to use it, please refer to article about types resolution.

Fluent methods for types

Tip: since version 1.3.1 you can use Type property of fluent configurator to configure exporting depending on type:

s.ExportAsInterfaces(..., c => c.OverrideName("_" + c.Type.Name));

will add prefix "_" to all exported types' names. Use it if you want to retrieve type name or other paramters from attribute.

Interface

Methods family Description
WithProperty/With*Properties Contains 7 different overloads allowing to variously select properties to be included to typing for specified type. Note that all there is not auto-export in fluent configuration. You must specify which properties to export and configuration for exporting them. See property configuration for all avaiable property exporting configuration methods.
WithMethod/With*Methods Contains 11 different overloads to variously select methods to be included to typing for specified type as class/interface functions. Note that all there is not auto-export in fluent configuration. You must specify which methods to export and configuration for exporting them. See method configuration for all avaiable method exporting configuration methods. Also some of overloads allow to specify export configuration for method parameters. Refer to this section to see how to specify configuration for methods parameters.
WithCodeGenerator Allows to specify ITsCodeGenerator that should be used to export this member. For more details please refer to Custom code generators page
AddReference Allows to specify additional paths or types that will be added as ///<reference ... > directive to file containing type being configured. This call only makes sense in case of [[multiple files export
ExportTo Specifies file where current type will be exported to. This call only makes sense in case of [[multiple files export
OverrideName Overrides name
DontIncludeToNamespace Configures exporter dont to export type to corresponding namespace
OverrideNamespace Configures exporter to export type to specified namespace
AutoI Forces exporter to add I letter as interface prefix.
Order Defines order this class member will be exported in. Greater order means that interface will be placed placed lower in resulting file
FlattenHierarchy Tells RT to "flatten" class/interface hierarchy. All methods/properties from base classes will be brought to TS interface itself, extends clause will be eliminated. You can specify "flatten limiter" type as 2nd parameter. When RT reaches limiter type processing class hierarchy - it will stop and not propagate limiter's members to exported class along with all that lies below. By default "flatten limiter" is typeof(object). Important! This method must be called before .With* methods! Otherwise it will not work!

Class

Method family Description
WithProperty/With*Properties Contains 7 different overloads allowing to variously select properties to be included to typing for specified type. Note that all there is not auto-export in fluent configuration. You must specify which properties to export and configuration for exporting them. See property configuration for all avaiable property exporting configuration methods.
WithField/With*Fields Mostly similar to WithProperty/With*Properties but for class fields
WithMethod/With*Methods Contains 11 different overloads to variously select methods to be included to typing for specified type as class/interface functions. Note that all there is not auto-export in fluent configuration. You must specify which methods to export and configuration for exporting them. See method configuration for all avaiable method exporting configuration methods. Also some of overloads allow to specify export configuration for method parameters. Refer to this section to see how to specify configuration for methods parameters.
WithCodeGenerator Allows to specify ITsCodeGenerator that should be used to export this member. For more details please refer to Custom code generators page
AddReference Allows to specify additional paths or types that will be added as ///<reference ... > directive to file containing type being configured. This call only makes sense in case of [[multiple files export
ExportTo Specifies file where current type will be exported to. This call only makes sense in case of [[multiple files export
OverrideName Overrides name
DontIncludeToNamespace Configures exporter dont to export member to corresponding namespace
OverrideNamespace Configures exporter to export type to specified namespace
Order Defines order this class member will be exported in. Greater order means that class will be placed placed lower in resulting file
Decorator Defines decorator to be applied to class. First parameters specifies decorator text (everything that must follow after @), second parameter defines order that this decorator must be applied in
FlattenHierarchy Tells RT to "flatten" class/interface hierarchy. All methods/properties from base classes will be brought to TS interface itself, extends clause will be eliminated. You can specify "flatten limiter" type as 2nd parameter. When RT reaches limiter type processing class hierarchy - it will stop and not propagate limiter's members to exported class along with all that lies below. By default "flatten limiter" is typeof(object). Important! This method must be called before .With* methods! Otherwise it will not work!
Abstract Will force this class to be exported as abstract or not
WithConstructor Will make RT to also export constructor of class. In TypeScript you only limited to one constructor per class. So, using WithConstructor will make RT to take the first class constructor (even if it is compiler-generated) and add it to TS code of class. Also here you can provide RtRaw AST node that will be used as constructor body. Be careful here and always remember to generate proper super(...) call. If you will not provide body implementation - then RT will try to generate correct super(...) call by itself. And... well, you'd better to do that manually. But anyway, if there are no base type found then RT will leave constructor body empty.

Enum

Method family Description
WithCodeGenerator Allows to specify ITsCodeGenerator that should be used to export this member. For more details please refer to Custom code generators page
AddReference Allows to specify additional paths or types that will be added as ///<reference ... > directive to file containing type being configured. This call only makes sense in case of [[multiple files export
ExportTo Specifies file where current type will be exported to. This call only makes sense in case of [[multiple files export
DontIncludeToNamespace Configures exporter dont to export member to corresponding namespace
OverrideNamespace Configures exporter to export type to specified namespace
Value Retrieves configuration builder for particular enumeration value. Consumes enum value itself or string enum value name.
Order Defines order this class member will be exported in. Greater order means that enum will be placed placed lower in resulting file
Const Turns enum to const enum (TS 2.4.2)
UseString Makes enum to use string initializer for its values (TypeScript 2.4)
Decorator Defines decorator to be applied to enumeration. First parameters specifies decorator text (everything that must follow after @), second parameter defines order that this decorator must be applied in

Third party

If you want to make C# wrapper for some types from existing TypeScript/JavaScript libraries, but do not want to generate code for them - then your choice is exporting types as third party. It can be done like this:

s.ExportAsThirdParty<YourThirdPartyType>()
    .WithName("full.qualified.Name")
    .Imports(new RtImport() { From = "../vendor/some.thirdparty.ts", Target = "{ full.qualified.Name }" });

Now you can use YourThirdPartyType in exported C# classes (as property, parent class, parameter type etc) - RT will automatically replace it with full.qualified.Name also maintaining specified import.

Method family Description
WithName Allows to specify full-qualified name of third-party type
Imports Gives ability to add one or multiple imports - they will be added to every export file where this third-party type will appear
References The same as Imports but if you use references

Fluent methods for members

Tip: since version 1.3.1 you can use Member property of fluent configurator to configure exporting depending on type member:

s.ExportAsInterfaces(..., c => c.WithPublicProperties(x => x.OverrideName("_" + x.Member.Name)));

will add prefix "_" to all public exported properties' names of specified types. Use it if you want to retrieve property name or other paremters from attribute.

Method

Method family Description
Ignore Ignores specified members during exporting. Ignored members won't appear in resulting typing.
WithCodeGenerator Allows to specify ITsCodeGenerator that should be used to export this member. For more details please refer to Custom code generators page
CamelCase Forces member name to be in camelCase notation
Returns Overrides member type name on export with textual string. Beware of using this setting because specified type may not present in your TypeScript code and this may lead to TypeScript compilation errors
Order Defines order this class member will be exported in. Greater order means that method will be placed placed lower in resulting file
Implement Defines inline function code to be converted to RtRaw and used as function body
Decorator Defines decorator to be applied to method. First parameters specifies decorator text (everything that must follow after @), second parameter defines order that this decorator must be applied in

Property

Method family Description
CamelCase Forces member name to be in camelCase notation
ForceNullable Forces property to be a nullable. When set to true then property will be generated as [property]? : [type] with forcibly added question mark denoting nullable field
Ignore Ignores specified members during exporting. Ignored members won't appear in resulting typing.
WithCodeGenerator Allows to specify ITsCodeGenerator that should be used to export this member. For more details please refer to Custom code generators page
Type Overrides member type name on export with textual string. Beware of using this setting because specified type may not present in your TypeScript code and this may lead to TypeScript compilation errors
Order Defines order this class member will be exported in. Greater order means that property will be placed placed lower in resulting file
Decorator Defines decorator to be applied to property. First parameters specifies decorator text (everything that must follow after @), second parameter defines order that this decorator must be applied in

Enum value

Method family Description
OverrideName Overrides enumeration value name
Initializer Overrides enumeration value's string initializer. Works only if usage of string initializers enabled either with [TsEnum] attribute or fluent configuration. Please escape quotes manually.
Ignore Ignores specified members during exporting. Ignored members won't appear in resulting typing.

Method parameter

To specify configuration for method parameter you should use .WithMethod fluent configuration method for class/interface and specify exported method using lambda expression replacing all parameters with Ts.Parameter call. Like this:

public interface IMyInterface
{
    void DoSomething(int a, string b);
}

public static void Configure(ConfigurationBuilder builder)
{
    builder.ExportAsInterface<IMyInterface>()
        .WithMethod(c => 
            c.DoSomething(
                // conf is parameter configuration builder
                Ts.Parameter<int>(conf => conf.OverrideName("blah")), 
                Ts.Parameter<string>()));
}

Reinforced.Typings.Fluent.Ts class is special dummy class used only for specifying configuration for parameter export

Method family Description
Type Overrides member type name on export with textual string. Beware of using this setting because specified type may not present in your TypeScript code and this may lead to TypeScript compilation errors
CamelCase Forces member name to be in camelCase notation
DefaultValue Sets parameter default value
Ignore Ignores specified members during exporting. Ignored members won't appear in resulting typing.
WithCodeGenerator Allows to specify ITsCodeGenerator that should be used to export this member. For more details please refer to Custom code generators page
Decorator Defines decorator to be applied to parameter. First parameters specifies decorator text (everything that must follow after @), second parameter defines order that this decorator must be applied in