Scala TSI can automatically generate Typescript Interfaces from your Scala classes.
To use the project add the SBT plugin dependency in project/plugins.sbt:
// See badge above for latest version number addSbtPlugin("nl.codestar" % "sbt-scala-tsi" % "0.1.3")And configure the plugin in your project:
// Replace with your project definition lazy val root = (project in file(".")) .settings( // The classes that you want to generate typescript interfaces for typescriptClassesToGenerateFor := Seq("MyClass"), // The output file which will contain the typescript interfaces typescriptOutputFile := baseDirectory.value / "model.ts", // Include the package(s) of the classes here // Optionally import your own TSType implicits to override default default generated typescriptGenerationImports := Seq("mymodel._", "MyTypescript._") )Now sbt generateTypescript will transform a file like
package mymodel import nl.codestar.scalatsi._ case class MyClass(foo: String, bar: Int)Into a typescript interface like
export interface MyClass { a: string b: number }See Example for more a more in-depth example
| Key | Type | Description |
|---|---|---|
| typescriptClassesToGenerateFor | Seq[String] | A list of all your (top-level) classes that you want to generate interfaces for |
| typescriptGenerationImports | Seq[String] | A list of all imports. This should import all classes you defined above, as well as custom TSType implicits |
| typescriptOutputFile | File | The output file with generated typescript interfaces |
You can check out the example project for a complete set-up and more examples.
Say we have the following JSON:
{ "name": "person name", "email": "abc@example.org", "age": 25, "job": { "tasks": ["Be in the office", "Drink coffee"], "boss": "Johnson" } }Generated from this Scala domain model:
package myproject case class Person( name: String, email: Email, age: Option[Int], // for privacy reasons, we do not put this social security number in the JSON ssn: Option[Int], job: Job ) // This type will get erased when serializing to JSON, only the string remains case class Email(address: String) case class Job(tasks: Seq[String], boss: String) With Typescript, your frontend can know what data is available in what format. However, keeping the Typescript definitions in sync with your scala classes is a pain and error-prone. scala-tsi solves that.
First we define the mapping as follows
package myproject import nl.codestar.scalatsi._ // A TSType[T] is what tells scala-tsi how to convert your type T into typescript // MyModelTSTypes contains all TSType[_]'s for your model // You can also spread these throughout your codebase, for example in the same place where your JSON (de)serializers object MyModelTSTypes extends DefaultTSTypes { // Tell scala-tsi to use the typescript type of string whenever we have an Email type // Alternatively, TSType.alias[Email, String] will create a `type Email = string` entry in the typescript file implicit val tsEmail = TSType.sameAs[Email, String] // TSType.fromCaseClass will convert your case class to a typescript definition // `- ssn` indicated the ssn field should be removed implicit val tsPerson = TSType.fromCaseClass[Person] - "ssn" }And in your build.sbt configure the sbt plugin to output your class:
lazy val root = (project in file(".")) .settings( typescriptClassesToGenerateFor := Seq("Person"), typescriptGenerationImports := Seq("myproject._", "MyModelTSTypes._"), typescriptOutputFile := baseDirectory.value / "model.ts" ) this will generate in your project root a model.ts:
export interface IPerson { name : string, email : string, age ?: number job: IJob } export interface IJob { tasks: string[] boss: string } This document contains more detailed explanation of the library and usage
See this list for an overview of completed features, and issues for open feature ideas.