scala-tsi has two important types
TypescriptType
which represents a valid type in Typescript.
It is an AST of a typescript type.TSType
, a type class that holds a link from a scala type to aTypescriptType
.
ATSType[T]
tells us how to transformT
into aTypescriptType
.
It fills a similar function as aplay-json
Writes[T]
or acirce
Encoder[T]
, which tell how to transform an instance of aT
into json.
scala-tsi contains some functionality to transform a TypescriptType
into valid Typescript.
This table contains some examples of the different representations:
Scala Type | TypescripType |
Typescript |
---|---|---|
Int |
TSNumber |
number |
Double |
TSNumber |
number |
Either[String,Int] |
TSUnion(TSString, TSNumber) |
string | number |
case class A(foo: Int) |
TypescriptInterface("A", Map("foo" -> TSNumber)) |
interface A {foo: number} |
42.type |
TSLiteralNumber(42) |
42 |
The link in the above table from scala type to TypescriptType
is provided by an implicit TSType
.
You will have to define these yourself and put these in scope.
Of course scala-tsi helps you with this.
The DefaultTSTypes
trait and object contain a large number of definitions for built-in Java and Scala classes, e.g. it contains a TSType[Int]
.
The most important thing is to define an implicit TSType
for your own types.
If you want to convert a case class, then you can simply use implicit val myCaseClassTSType = TSType.fromCaseClass[MyCaseClass]
.
There are other ways to construct TSType
defined in the companion object which we encourage you to check out.
Most interesting are TSType.fromCaseClass
, TSType.alias
and TSType.interface
.
scala-tsi also defines a small DSL which you can use to construct custom definitions
import nl.codestar.scalatsi._
import nl.codestar.scalatsi.dsl._
import DefaultTSTypes._
// Includes implicit conversion from literal values to literal typescript types
val literal42: TypescriptType = 42
// Link the scala type Foo to an typescript type "foo" that already exists and we don't define
implicit val fooTSType = TSType.external[Foo]("foo")
// Using TSType.interface you can construct your own interface
implicit val myClassTSType: TSType[MyClass] = TSType.interface("MyClass",
// Classes will automatically be converted to the TypescriptType if an implicit TSType exists
"foo" -> classOf[Foo],
// Tuples will be converted into arrays of specific length and type
"tuple3" -> classOf[(Int, String, Foo)],
// You can create unions with the | operator defined on TSType and TypescriptType
"oneOf" -> (TSNumber | TSString | TSBoolean),
// You can create an array of a type with .array
"stringArray" -> TSString.array,
// literal types
"fortyTwo" -> 42
)
/* Output:
interface MyClass {
foo: Foo
tuple3: [number, string, Foo]
oneOf: (number | string | boolean)
stringArray: string[]
fortyTwo: 42
}
*/
// Use +, ++, - and -- to modify existing TSIType's or TSInterface's
implicit val myCaseClassWithExtraField = TSType.fromCaseClass[myCaseClass] + ("foo" -> "bar")
Normally the SBT plugin will output Typescript for you.
However, you can also do this yourself using TypescriptTypeSerializer
.
TypescriptTypeSerializer.serialize
will transform a single type into typescript, e.g. serialize(TSNumber) == "number"
and serialize(TSInterface("Foo")) == "Foo"
TypescriptTypeSerializer.emits
will output multiple named types, e.g. emits(TSInterface("Foo")) == "interface Foo {}"