-
Notifications
You must be signed in to change notification settings - Fork 86
Types Resolution
Reinforced.Typings automatically resolves your types according to following (more or less formal) rules:
-
(s)byte,(u)short,(u)int,(u)long,float,double,decimal=>number -
string,char=>string -
object=>any -
bool=>boolean -
void=>void(did you know thattypeof(void)is correct C# construction?)
- Nullables are resolved as they are not nullables. You can enable
AutoOptionalPropertiesoption in[TsGlobal]attribute or use corresponding fluent configuration method to make RT export properties ofNullable<>type as optional properties if you wish.
Both nullables and simple types will be resolved to RtSimpleTypeName AST.
- Everything that is of
System.Tuple<>type will be resolved to TypeScript tuples (RtTupleAST)
- Everything that is non-generic dictionary (implements
System.Collections.IDictionary) will be resolved to{ [key:any] :any }. Reinforced.Typings will produce warning in this case because TypeScript hashes can have onlynumberorstringas key. Try to avoid using nongeneric Dictionaries - Everything that implements
System.Collections.Generic.IDictionary<,>,System.Collections.Generic.IReadOnlyDictionary<,>or has typeSystem.Collections.Generic.Dictionary<,>will be resolved as TypeScript hash{ [key:TKey]:TValue }where bothTKeyandTValuewill be resolved according to current rules. In case isTKeyis not eithernumberorstring- warning will be produced
Dictionaries are resolved to RtDictionaryType AST.
- Everything that implements
System.Collections.IEnumerable(without generic parametrization) will be strictly resolved toany[]- array of any - Every array
T[]will be resolved to TypeScript arrayT[]where array element typeTwill be resolved according to current rules - Everything that implements
System.Collections.Generic.IEnumerable<T>will be resolved to TypeScript arrayT[]where array element typeTwill be resolved according to current rules
Collections are resolved to RtArrayType AST.
- Everythis that inherits
System.MulticastDelegatewill be resolved to TypeScript function type(a:T1,B:T2...) => TResult(RtDelegateTypeAST). Types of all parameters will be resolved according to current rules as well as return type. If delegate does not have return type -voidwill be assumed. Arguments will be namedargin case of single argument andarg1,arg2etc in case of multiple arguments
- Exported type will be resolved to
RtSimpleTypeNamewith respect to overriden name and generic parameters until it derives collection class/interface or dictionary class/interface. In this case rules of collections and dictionaries resolution will be applied
- If exported type is generic one then all generic parameters will be left in place and exported type will be generic
- If some of generic parameters are materialized by context (e.g. property of generic type sharing generic parameter with declaring type) - they will be also left in place leaving type generic
- If some of generic parameters are intentilnally materialized either with inheritance or using [TsGeneric] attribute - they will behave like usual C# materialized generics
- If type
Ainherits typeBand both are exported then inheritance will be exported to TypeScript without changes - If type
Ainherits typeBandBis not exported thenBwill be removed fromA's inheritance chain. So export your base types along with inheritors. - If type
Ainherits typeBandBis exported as interface whetherAis exported as class then Reinforced.Typings will by force implement all members fromBinA, produce corresponding warning and leave@todoJSDOC comment in place where accident took place
- All other types are unknown for Reinforced.Typings and fall into TypeScript
anytype
You can intentionally instruct Reinforced.Typings which type AST node to resolve particular type to. This mechanism called "substitutions" and can be used only from fluent configuration due to technical limitations. Use .Substitute method of ConfigurationBuilder to define substitution:
builder.Substitute(typeof(System.Guid), new RtSimpleTypeName("string"));This configuration will strictly resolve System.Guid type to string wherever it appears among all the files. In the same way you can define substitution type-wide:
builder.ExportAsInterface<MyType>()
.Substitute(typeof(System.DateTime), new RtSimpleTypeName("Date"))
.WithPublicProperties();This configuration will strictly resolve System.DateTime to Date TypeScript type, but only within of MyType exporting. In other words, it will not touch DateTimes in other exported classes leaving them any.
You also can use other types from namespace Reinforced.Typings.Ast.TypeNames derived from RtTypeName (RtDelegateType,RtArrayType, RtDictionaryType,RtTuple). Please refer to XMLDOC for these types to properly instantiate them.
(since version 1.3.2)
There is also ability to override type inferer for particular property/field/method/parameter using inline type inferer. Use .InferType method that is available within property/field/method/parameter configuration. .InferType method presents in 4 variations. All variations have exactly one and only parameter - delegate that:
- Consuming source member (
MemberInfo/ParameterInfo/MethoInfo) and returnsstring. Result will be converted to simple type name- ...the same, but returning RtTypeName
- Consuming source member as 1st parameter and
TypeInfereras 2nd parameter, returnsstring. Result will be converted to simple type name. Use 2nd parameter (type inferer) to convertTypeobjects toRtTypeName- ... the same, but returning RtTypeName
Examples:
// results MyProperty : Observable<number>
builder.ExportAsInterface<MyType>()
.WithProperty(x => x.MyProperty, x => x.InferType(_ => "Observable<string>"));
// the same, but in other words
builder.ExportAsInterface<MyType>()
.WithProperty(x => x.MyProperty, x =>
new RtSimpleTypeName("Observable", new RtSimpleTypeName("string")));
// Wraps all public properties with Observable<>
builder.ExportAsInterface<MyType>()
.WithPublicProperties(x => x.InferType(
(m, t) => new RtSimpleTypeName("Observable", t.ResolveTypeName(((PropertyInfo)m).PropertyType))
)
);
// Wraps method parameter and return type with Observable<>
builder
.WithMethod(x => x.SomeMethod3(
Ts.Parameter<int>(t => t.InferType(
(m, r) => new RtSimpleTypeName("Observable", r.ResolveTypeName(m.ParameterType)))
)
),
x => x.InferType((m, r) => new RtSimpleTypeName("Observable", r.ResolveTypeName(m.ReturnType)))
);