-
Notifications
You must be signed in to change notification settings - Fork 82
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
AutoOptionalProperties
option 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 (RtTuple
AST)
- 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 onlynumber
orstring
as 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 bothTKey
andTValue
will be resolved according to current rules. In case isTKey
is not eithernumber
orstring
- 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 typeT
will be resolved according to current rules - Everything that implements
System.Collections.Generic.IEnumerable<T>
will be resolved to TypeScript arrayT[]
where array element typeT
will be resolved according to current rules
Collections are resolved to RtArrayType
AST.
- Everythis that inherits
System.MulticastDelegate
will be resolved to TypeScript function type(a:T1,B:T2...) => TResult
(RtDelegateType
AST). Types of all parameters will be resolved according to current rules as well as return type. If delegate does not have return type -void
will be assumed. Arguments will be namedarg
in case of single argument andarg1
,arg2
etc in case of multiple arguments
- Exported type will be resolved to
RtSimpleTypeName
with 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
A
inherits typeB
and both are exported then inheritance will be exported to TypeScript without changes - If type
A
inherits typeB
andB
is not exported thenB
will be removed fromA
's inheritance chain. So export your base types along with inheritors. - If type
A
inherits typeB
andB
is exported as interface whetherA
is exported as class then Reinforced.Typings will by force implement all members fromB
inA
, produce corresponding warning and leave@todo
JSDOC comment in place where accident took place
- All other types are unknown for Reinforced.Typings and fall into TypeScript
any
type
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 DateTime
s 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
TypeInferer
as 2nd parameter, returnsstring
. Result will be converted to simple type name. Use 2nd parameter (type inferer) to convertType
objects 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)))
);