From 8106de6189f4901a03604a23598d6f44223f0f35 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Fri, 9 Sep 2022 09:51:59 +0800
Subject: [PATCH 01/40] Update

---
 .../src/main/scala/mlscript/NewParser.scala   |   3 +-
 shared/src/main/scala/mlscript/syntax.scala   |   1 +
 .../js/src/main/scala/ts2mls/JSWriter.scala   |   2 +
 .../src/main/scala/ts2mls/TSNamespace.scala   |  46 +++---
 .../js/src/main/scala/ts2mls/TSProgram.scala  |   2 +-
 .../main/scala/ts2mls/types/Converter.scala   |  69 +++++----
 ts2mls/js/src/test/diff/Array.d.mls           | 139 ++++++++++++------
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  |  82 +++--------
 ts2mls/js/src/test/diff/ClassMember.d.mls     |  61 ++++++--
 ts2mls/js/src/test/diff/Enum.d.mls            |  16 +-
 ts2mls/js/src/test/diff/Heritage.d.mls        |  99 +++++++++----
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   |  58 ++++++--
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 117 +++++++++++----
 ts2mls/js/src/test/diff/Intersection.d.mls    |  79 +++++-----
 ts2mls/js/src/test/diff/MultiFiles.d.mls      |  64 ++++----
 ts2mls/js/src/test/diff/Namespace.d.mls       |  81 ++++++----
 ts2mls/js/src/test/diff/Optional.d.mls        |  85 +++++------
 ts2mls/js/src/test/diff/Overload.d.mls        | 104 +++++++------
 ts2mls/js/src/test/diff/Tuple.d.mls           | 118 ++++++++++-----
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 103 ++++++++-----
 ts2mls/js/src/test/diff/Union.d.mls           |  53 ++++---
 21 files changed, 863 insertions(+), 519 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala
index 3791564012..2e2993451b 100644
--- a/shared/src/main/scala/mlscript/NewParser.scala
+++ b/shared/src/main/scala/mlscript/NewParser.scala
@@ -235,12 +235,13 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
       case (SPACE, _) :: _ => consume; block
       case c =>
         val t = c match {
-          case (KEYWORD(k @ ("class" | "trait" | "type")), l0) :: c =>
+          case (KEYWORD(k @ ("class" | "trait" | "type" | "namespace")), l0) :: c =>
             consume
             val kind = k match {
               case "class" => Cls
               case "trait" => Trt
               case "type" => Als
+              case "namespace" => Nms
               case _ => die
             }
             val (tn, success) = yeetSpaces match {
diff --git a/shared/src/main/scala/mlscript/syntax.scala b/shared/src/main/scala/mlscript/syntax.scala
index c5745e3aee..5c24f95cdc 100644
--- a/shared/src/main/scala/mlscript/syntax.scala
+++ b/shared/src/main/scala/mlscript/syntax.scala
@@ -48,6 +48,7 @@ sealed trait ObjDefKind
 case object Cls extends TypeDefKind("class") with ObjDefKind
 case object Trt extends TypeDefKind("trait") with ObjDefKind
 case object Als extends TypeDefKind("type alias")
+case object Nms extends TypeDefKind("namespace")
 
 sealed abstract class Term                                           extends Terms with TermImpl
 sealed abstract class Lit                                            extends SimpleTerm with LitImpl
diff --git a/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala b/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala
index bc4065a58f..b29ae08f7c 100644
--- a/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala
@@ -11,6 +11,8 @@ class JSWriter(filename: String) {
   private var fileSize = 0 // how many bytes we've written in the file
   private var needTruncate = false
 
+  writeln(":NewParser\n:ParseOnly")
+
   def writeln(str: String) = {
     val strln = str + "\n"
     val buffer = createBuffer(strln.length)
diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index c45834c75e..ccd6315367 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -34,30 +34,38 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
   def containsMember(name: String, searchParent: Boolean = true): Boolean =
     if (parent.isEmpty) members.contains(name) else (members.contains(name) || (searchParent && parent.get.containsMember(name)))
 
-  def generate(writer: JSWriter): Unit =
+  def generate(writer: JSWriter, indent: String): Unit =
     order.toList.foreach((p) => p match {
-      case Left(name) => subSpace(name).generate(writer)
+      case Left(subName) => {
+        writer.writeln(s"${indent}namespace $subName {")
+        subSpace(subName).generate(writer, indent + "  ")
+        writer.writeln(s"$indent}")
+      }
       case Right(name) => {
         val mem = members(name)
-        val fullName = getFullPath(name)
+        // val fullName = getFullPath(name)
         mem match {
           case inter: TSIntersectionType => // overloaded functions
-            writer.writeln(s"def ${fullName}: ${Converter.convert(inter)}")
-          case f: TSFunctionType => {
-            val typeParams = f.typeVars.map((t) => t.name)
-            if (typeParams.isEmpty)
-              writer.writeln(s"def ${fullName}: ${Converter.convert(f)}")
-            else // TODO: add constraints
-              writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(f)}")
-          }
-          case overload @ TSIgnoredOverload(base, _) => {
-            val typeParams = base.typeVars.map((t) => t.name)
-              if (typeParams.isEmpty)
-                writer.writeln(s"def ${fullName}: ${Converter.convert(overload)}")
-              else // TODO: add constraints
-                writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(overload)}")
-          }
-          case _ => writer.writeln(Converter.convert(mem))
+            writer.writeln(s"${indent} fun ${name}${Converter.convert(inter)}")
+          case f: TSFunctionType =>
+            writer.writeln(s"${indent}fun ${name}${Converter.convert(f)}")
+          // {
+          //   val typeParams = f.typeVars.map((t) => t.name)
+          //   if (typeParams.isEmpty)
+          //     writer.writeln(s"def ${fullName}: ${Converter.convert(f)}")
+          //   else // TODO: add constraints
+          //     writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(f)}")
+          // }
+          case overload @ TSIgnoredOverload(base, _) =>
+            writer.writeln(s"${indent}fun ${name}${Converter.convert(overload)}")
+          // {
+          //   val typeParams = base.typeVars.map((t) => t.name)
+          //     if (typeParams.isEmpty)
+          //       writer.writeln(s"def ${fullName}: ${Converter.convert(overload)}")
+          //     else // TODO: add constraints
+          //       writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(overload)}")
+          // }
+          case _ => writer.writeln(indent + Converter.convert(mem))
         }
       }
     })
diff --git a/ts2mls/js/src/main/scala/ts2mls/TSProgram.scala b/ts2mls/js/src/main/scala/ts2mls/TSProgram.scala
index 8660ad397b..631e08df61 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSProgram.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSProgram.scala
@@ -15,7 +15,7 @@ class TSProgram(filenames: Seq[String]) {
   implicit val checker = TSTypeChecker(program.getTypeChecker())
   filenames.foreach(filename => TSSourceFile(program.getSourceFile(filename), globalNamespace))
 
-  def generate(writer: JSWriter): Unit = globalNamespace.generate(writer)
+  def generate(writer: JSWriter): Unit = globalNamespace.generate(writer, "")
 }
 
 object TSProgram {
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index be2cf33173..8c2c7e6b8d 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -13,9 +13,9 @@ object Converter {
     "null" -> "null",
     "undefined" -> "undefined",
     "never" -> "nothing",
-    "object" -> "{}",
-    "true" -> "true",
-    "false" -> "false"
+    "object" -> "object",
+    "true" -> "bool", // will not appear individually
+    "false" -> "" // will not appear individually
   )
 
   def convert(tsType: TSType): String = tsType match {
@@ -23,9 +23,19 @@ object Converter {
     case TSReferenceType(name) => name
     case TSFunctionType(params, res, _) =>
       // since functions can be defined by both `def` and `method`, it only returns the type of functions
-      if (params.length == 0) s"${primitiveName("void")} -> (${convert(res)})"
-      else params.foldRight(convert(res))((tst, mlst) => s"(${convert(tst)}) -> (${mlst})")
-    case TSUnionType(lhs, rhs) => s"(${convert(lhs)}) | (${convert(rhs)})"
+      if (params.length == 0) s"(): ${convert(res)}"
+      else {
+        val list = params.map((p) => s"_: ${convert(p)}").reduceLeft((r, p) => s"$r, $p")
+        s"($list): ${convert(res)}"
+      }
+    case TSUnionType(lhs, rhs) => {
+      val lres = convert(lhs)
+      val rres = convert(rhs)
+
+      if (lres.isEmpty()) rres
+      else if (rres.isEmpty()) lres
+      else s"($lres) | ($rres)"
+    }
     case TSIntersectionType(lhs, rhs) => s"(${convert(lhs)}) & (${convert(rhs)})"
     case TSTypeParameter(name, _) => name // constraints should be translated where the type parameters were created rather than be used
     case TSTupleType(lst) => s"(${lst.foldLeft("")((p, t) => s"$p${convert(t)}, ")})"
@@ -41,37 +51,40 @@ object Converter {
   private def convertRecord(typeName: String, members: Map[String, TSMemberType],
     typeVars: List[TSTypeParameter], parents: List[TSType]) = {
     val allRecs = members.toList.map((m) => m._2.modifier match {
-      case Public => {
-        m._2.base match { // methods
-          case f @ TSFunctionType(_, _, typeVars) if (!typeVars.isEmpty) =>
-            s"  method ${m._1}[${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}]: ${convert(f)}" // TODO: add constraints
-          case overload @ TSIgnoredOverload(base, _) =>
-            if (!base.typeVars.isEmpty)
-              s"  method ${m._1}[${base.typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}]: ${convert(overload)}" // TODO: add constraints
-            else s"${m._1}: ${convert(overload)}"
-          case _ => s"${m._1}: ${convert(m._2)}" // other type members
-        }
-      }
+      case Public => s"${m._1}: ${convert(m._2)}"
+      // case Public => {
+      //   m._2.base match { // methods
+      //     case f @ TSFunctionType(_, _, typeVars) if (!typeVars.isEmpty) =>
+      //       s"  method ${m._1}[${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}]: ${convert(f)}" // TODO: add constraints
+      //     case overload @ TSIgnoredOverload(base, _) =>
+      //       if (!base.typeVars.isEmpty)
+      //         s"  method ${m._1}[${base.typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}]: ${convert(overload)}" // TODO: add constraints
+      //       else s"${m._1}: ${convert(overload)}"
+      //     case _ => s"${m._1}: ${convert(m._2)}" // other type members
+      //   }
+      // }
       case _ => "" // TODO: deal with private/protected members
     })
 
     val body = { // members without independent type parameters, translate them directly
-      val lst = allRecs.filter((s) => !s.startsWith("  ") && !s.isEmpty())
-      if (lst.isEmpty) "{}"
-      else s"{ ${lst.reduceLeft((bd, m) => s"$bd; $m")} }"
-    }
-    val methods = { // members with independent type parameters, use methods instead
-      val lst = allRecs.filter(_.startsWith("  "))
+      val lst = allRecs.filter((s) => !s.isEmpty())
       if (lst.isEmpty) ""
-      else "\n" + lst.reduceLeft((bd, m) => s"$bd\n$m")
+      else s"(${lst.reduceLeft((bd, m) => s"$bd, $m")})"
     }
+    // val methods = { // members with independent type parameters, use methods instead
+    //   val lst = allRecs.filter(_.startsWith("  "))
+    //   if (lst.isEmpty) ""
+    //   else "\n" + lst.reduceLeft((bd, m) => s"$bd\n$m")
+    // }
     
-    if (typeName === "trait ") body // anonymous interfaces
+    if (typeName.equals("trait ")) body // anonymous interfaces
     else { // named interfaces and classes
-      val bodyWithParents = parents.foldLeft(body)((b, p) => s"$b & ${convert(p)}")
-      if (typeVars.isEmpty) s"$typeName: $bodyWithParents$methods"
+      val bodyWithParents =
+        if (parents.isEmpty) body
+        else parents.foldLeft(s"$body: ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
+      if (typeVars.isEmpty) s"$typeName$bodyWithParents"
       else
-        s"$typeName[${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}]: $bodyWithParents$methods" // TODO: add constraints
+        s"$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$bodyWithParents" // TODO: add constraints
     }
   }
 }
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index e3a7165a40..bce71ef8c5 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,42 +1,97 @@
-def first: (MutArray[string]) -> (string)
-def getZero3: unit -> (MutArray[number])
-def first2: (MutArray[(number) -> (number)]) -> ((number) -> (number))
-def doEs: (MutArray[int]) -> (MutArray[int])
-class C: {}
-trait I: { i: number }
-def doCs: (MutArray[C]) -> (MutArray[C])
-def doIs: (MutArray[I]) -> (MutArray[I])
-def inter[U, T]: (MutArray[(U) & (T)]) -> (MutArray[(U) & (T)])
-def clean: (MutArray[(string, number, )]) -> (MutArray[(string, number, )])
-def translate[T, U]: (MutArray[T]) -> (MutArray[U])
-def uu: (MutArray[((number) | (false)) | (true)]) -> (MutArray[((number) | (false)) | (true)])
-class Temp[T]: { x: T }
-def ta: (MutArray[Temp[(false) | (true)]]) -> (MutArray[Temp[(false) | (true)]])
-def tat[T]: (MutArray[Temp[T]]) -> (MutArray[Temp[T]])
-//│ Defined class C
-//│ Defined trait I
-//│ Defined class Temp[+T]
-//│ first: MutArray[string] -> string
-//│      = <missing implementation>
-//│ getZero3: unit -> MutArray[number]
-//│         = <missing implementation>
-//│ first2: MutArray[number -> number] -> number -> number
-//│       = <missing implementation>
-//│ doEs: MutArray[int] -> MutArray[int]
-//│     = <missing implementation>
-//│ doCs: MutArray[C] -> MutArray[C]
-//│     = <missing implementation>
-//│ doIs: MutArray[I] -> MutArray[I]
-//│     = <missing implementation>
-//│ inter: MutArray['a] -> MutArray['a]
-//│      = <missing implementation>
-//│ clean: MutArray[(string, number,)] -> MutArray[(string, number,)]
-//│      = <missing implementation>
-//│ translate: MutArray['a] -> MutArray['b]
-//│          = <missing implementation>
-//│ uu: MutArray[false | number | true] -> MutArray[false | number | true]
-//│   = <missing implementation>
-//│ ta: MutArray[Temp[bool]] -> MutArray[Temp[bool]]
-//│   = <missing implementation>
-//│ tat: MutArray[Temp['a]] -> MutArray[Temp['a]]
-//│    = <missing implementation>
+:NewParser
+:ParseOnly
+fun first(_: MutArray[string]): string
+fun getZero3(): MutArray[number]
+fun first2(_: MutArray[(_: number): number]): (_: number): number
+fun doEs(_: MutArray[int]): MutArray[int]
+class C
+trait I(i: number)
+fun doCs(_: MutArray[C]): MutArray[C]
+fun doIs(_: MutArray[I]): MutArray[I]
+fun inter(_: MutArray[(U) & (T)]): MutArray[(U) & (T)]
+fun clean(_: MutArray[(string, number, )]): MutArray[(string, number, )]
+fun translate(_: MutArray[T]): MutArray[U]
+fun uu(_: MutArray[(number) | (bool)]): MutArray[(number) | (bool)]
+class Temp<T>(x: T)
+fun ta(_: MutArray[Temp[bool]]): MutArray[Temp[bool]]
+fun tat(_: MutArray[Temp[T]]): MutArray[Temp[T]]
+//│ |#fun| |first|(|_|#:| |MutArray|[|string|]|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|[|number|]|↵|#fun| |first2|(|_|#:| |MutArray|[|(|_|#:| |number|)|#:| |number|]|)|#:| |(|_|#:| |number|)|#:| |number|↵|#fun| |doEs|(|_|#:| |MutArray|[|int|]|)|#:| |MutArray|[|int|]|↵|#class| |C|↵|#trait| |I|(|i|#:| |number|)|↵|#fun| |doCs|(|_|#:| |MutArray|[|C|]|)|#:| |MutArray|[|C|]|↵|#fun| |doIs|(|_|#:| |MutArray|[|I|]|)|#:| |MutArray|[|I|]|↵|#fun| |inter|(|_|#:| |MutArray|[|(|U|)| |&| |(|T|)|]|)|#:| |MutArray|[|(|U|)| |&| |(|T|)|]|↵|#fun| |clean|(|_|#:| |MutArray|[|(|string|,| |number|,| |)|]|)|#:| |MutArray|[|(|string|,| |number|,| |)|]|↵|#fun| |translate|(|_|#:| |MutArray|[|T|]|)|#:| |MutArray|[|U|]|↵|#fun| |uu|(|_|#:| |MutArray|[|(|number|)| ||| |(|bool|)|]|)|#:| |MutArray|[|(|number|)| ||| |(|bool|)|]|↵|#class| |Temp|‹|T|›|(|x|#:| |T|)|↵|#fun| |ta|(|_|#:| |MutArray|[|Temp|[|bool|]|]|)|#:| |MutArray|[|Temp|[|bool|]|]|↵|#fun| |tat|(|_|#:| |MutArray|[|Temp|[|T|]|]|)|#:| |MutArray|[|Temp|[|T|]|]|
+//│ ╔══[ERROR] not a recognized type: (MutArray)[string]
+//│ ║  l.3: 	fun first(_: MutArray[string]): string
+//│ ╙──     	             ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[number]
+//│ ║  l.4: 	fun getZero3(): MutArray[number]
+//│ ╙──     	                ^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
+//│ ╙──     	                                  ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
+//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
+//│ ╙──     	                                                         ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
+//│ ╙──     	                                              ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
+//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
+//│ ╙──     	                                              ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)['(' _: number, ')' (number,)]
+//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
+//│ ╙──     	              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[int]
+//│ ║  l.6: 	fun doEs(_: MutArray[int]): MutArray[int]
+//│ ╙──     	                            ^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[int]
+//│ ║  l.6: 	fun doEs(_: MutArray[int]): MutArray[int]
+//│ ╙──     	            ^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[C]
+//│ ║  l.9: 	fun doCs(_: MutArray[C]): MutArray[C]
+//│ ╙──     	                          ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[C]
+//│ ║  l.9: 	fun doCs(_: MutArray[C]): MutArray[C]
+//│ ╙──     	            ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[I]
+//│ ║  l.10: 	fun doIs(_: MutArray[I]): MutArray[I]
+//│ ╙──      	                          ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[I]
+//│ ║  l.10: 	fun doIs(_: MutArray[I]): MutArray[I]
+//│ ╙──      	            ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[& (U,) (T,)]
+//│ ║  l.11: 	fun inter(_: MutArray[(U) & (T)]): MutArray[(U) & (T)]
+//│ ╙──      	                                   ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[& (U,) (T,)]
+//│ ║  l.11: 	fun inter(_: MutArray[(U) & (T)]): MutArray[(U) & (T)]
+//│ ╙──      	             ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)['(' string, number, ')']
+//│ ║  l.12: 	fun clean(_: MutArray[(string, number, )]): MutArray[(string, number, )]
+//│ ╙──      	                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)['(' string, number, ')']
+//│ ║  l.12: 	fun clean(_: MutArray[(string, number, )]): MutArray[(string, number, )]
+//│ ╙──      	             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[U]
+//│ ║  l.13: 	fun translate(_: MutArray[T]): MutArray[U]
+//│ ╙──      	                               ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[T]
+//│ ║  l.13: 	fun translate(_: MutArray[T]): MutArray[U]
+//│ ╙──      	                 ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[| (number,) (bool,)]
+//│ ║  l.14: 	fun uu(_: MutArray[(number) | (bool)]): MutArray[(number) | (bool)]
+//│ ╙──      	                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[| (number,) (bool,)]
+//│ ║  l.14: 	fun uu(_: MutArray[(number) | (bool)]): MutArray[(number) | (bool)]
+//│ ╙──      	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[bool]]
+//│ ║  l.16: 	fun ta(_: MutArray[Temp[bool]]): MutArray[Temp[bool]]
+//│ ╙──      	                                 ^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[bool]]
+//│ ║  l.16: 	fun ta(_: MutArray[Temp[bool]]): MutArray[Temp[bool]]
+//│ ╙──      	          ^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[T]]
+//│ ║  l.17: 	fun tat(_: MutArray[Temp[T]]): MutArray[Temp[T]]
+//│ ╙──      	                               ^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[T]]
+//│ ║  l.17: 	fun tat(_: MutArray[Temp[T]]): MutArray[Temp[T]]
+//│ ╙──      	           ^^^^^^^^^^^^^^^^^
+//│ Parsed: {fun first: [] -> anything -> string; fun getZero3: [] -> () -> anything; fun first2: [] -> anything -> anything; fun doEs: [] -> anything -> anything; class C() {}; trait I(i: number,): {}; fun doCs: [] -> anything -> anything; fun doIs: [] -> anything -> anything; fun inter: [] -> anything -> anything; fun clean: [] -> anything -> anything; fun translate: [] -> anything -> anything; fun uu: [] -> anything -> anything; class Temp[T](x: T,) {}; fun ta: [] -> anything -> anything; fun tat: [] -> anything -> anything}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 4dbb443afc..6b344655a3 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,58 +1,24 @@
-def hello: unit -> (unit)
-def add: (number) -> ((number) -> (number))
-def sub: (number) -> ((number) -> (number))
-def foo: unit -> (number)
-def id: (anything) -> (anything)
-def odd: (number) -> ((false) | (true))
-def isnull: (anything) -> ((false) | (true))
-def bar: unit -> (anything)
-def nu: (null) -> (null)
-def un: (undefined) -> (undefined)
-def fail: unit -> (nothing)
-def create: unit -> ({})
-def pa: (number) -> (number)
-def wtf: (anything) -> (unit)
-class Foooooo: { ooooooo: number }
-def inn: (Foooooo) -> (unit)
-def out: unit -> (Foooooo)
-trait Barrrrrrrrr: { rrrrrrr: number }
-def inn2: (Barrrrrrrrr) -> (unit)
-def out2: unit -> (Barrrrrrrrr)
-//│ Defined class Foooooo
-//│ Defined trait Barrrrrrrrr
-//│ hello: unit -> unit
-//│      = <missing implementation>
-//│ add: number -> number -> number
-//│    = <missing implementation>
-//│ sub: number -> number -> number
-//│    = <missing implementation>
-//│ foo: unit -> number
-//│    = <missing implementation>
-//│ id: anything -> anything
-//│   = <missing implementation>
-//│ odd: number -> bool
-//│    = <missing implementation>
-//│ isnull: anything -> bool
-//│       = <missing implementation>
-//│ bar: unit -> anything
-//│    = <missing implementation>
-//│ nu: null -> null
-//│   = <missing implementation>
-//│ un: undefined -> undefined
-//│   = <missing implementation>
-//│ fail: unit -> nothing
-//│     = <missing implementation>
-//│ create: unit -> anything
-//│       = <missing implementation>
-//│ pa: number -> number
-//│   = <missing implementation>
-//│ wtf: anything -> unit
-//│    = <missing implementation>
-//│ inn: Foooooo -> unit
-//│    = <missing implementation>
-//│ out: unit -> Foooooo
-//│    = <missing implementation>
-//│ inn2: Barrrrrrrrr -> unit
-//│     = <missing implementation>
-//│ out2: unit -> Barrrrrrrrr
-//│     = <missing implementation>
+:NewParser
+:ParseOnly
+fun hello(): unit
+fun add(_: number, _: number): number
+fun sub(_: number, _: number): number
+fun foo(): number
+fun id(_: anything): anything
+fun odd(_: number): bool
+fun isnull(_: anything): bool
+fun bar(): anything
+fun nu(_: null): null
+fun un(_: undefined): undefined
+fun fail(): nothing
+fun create(): object
+fun pa(_: number): number
+fun wtf(_: anything): unit
+class Foooooo(ooooooo: number)
+fun inn(_: Foooooo): unit
+fun out(): Foooooo
+trait Barrrrrrrrr(rrrrrrr: number)
+fun inn2(_: Barrrrrrrrr): unit
+fun out2(): Barrrrrrrrr
+//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |sub|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|_|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|_|#:| |number|)|#:| |bool|↵|#fun| |isnull|(|_|#:| |anything|)|#:| |bool|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|_|#:| |null|)|#:| |null|↵|#fun| |un|(|_|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|_|#:| |number|)|#:| |number|↵|#fun| |wtf|(|_|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#fun| |inn|(|_|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#fun| |inn2|(|_|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (_: number, _: number,) -> number; fun sub: [] -> (_: number, _: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (_: anything,) -> anything; fun odd: [] -> (_: number,) -> bool; fun isnull: [] -> (_: anything,) -> bool; fun bar: [] -> () -> anything; fun nu: [] -> (_: null,) -> null; fun un: [] -> (_: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (_: number,) -> number; fun wtf: [] -> (_: anything,) -> unit; class Foooooo(ooooooo: number,) {}; fun inn: [] -> (_: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> (_: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index f0bfd5bde4..a99ebbe7ce 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,10 +1,51 @@
-class Student: { name: string; isFriend: (Student) -> ((false) | (true)); addScore: (string) -> ((number) -> (unit)); getID: unit -> (number) }
-class Foo[T]: { bar: (T) -> (unit) }
-class EZ: { inc: (number) -> (number) }
-class Outer: {}
-class TTT[T]: { ttt: (T) -> (T); ttt2: (T) -> (T) }
-//│ Defined class Student
-//│ Defined class Foo[-T]
-//│ Defined class EZ
-//│ Defined class Outer
-//│ Defined class TTT[=T]
+:NewParser
+:ParseOnly
+class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
+class Foo<T>(bar: (_: T): unit)
+class EZ(inc: (_: number): number)
+class Outer
+class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
+//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |(|_|#:| |Student|)|#:| |bool|,| |addScore|#:| |(|_|#:| |string|,| |_|#:| |number|)|#:| |unit|,| |getID|#:| |(||)|#:| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#class| |EZ|(|inc|#:| |(|_|#:| |number|)|#:| |number|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |(|_|#:| |T|)|#:| |T|,| |ttt2|#:| |(|_|#:| |T|)|#:| |T|)|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
+//│ ╙──     	                                                  ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
+//│ ╙──     	                                                                                          ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
+//│ ╙──     	                                                                                                           ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
+//│ ╙──     	                                                                                                         ^^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
+//│ ╙──     	                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
+//│ ╙──     	                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.4: 	class Foo<T>(bar: (_: T): unit)
+//│ ╙──     	                        ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.4: 	class Foo<T>(bar: (_: T): unit)
+//│ ╙──     	                  ^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	class EZ(inc: (_: number): number)
+//│ ╙──     	                         ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	class EZ(inc: (_: number): number)
+//│ ╙──     	              ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
+//│ ╙──     	                        ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
+//│ ╙──     	                                         ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
+//│ ╙──     	                                   ^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
+//│ ╙──     	                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ Parsed: {class Student(name: string, isFriend: '(' _: Student, ')' (bool, addScore: '(' _: string, _: number, ')' (unit, getID: '('  ')' (number,),),),) {}; class Foo[T](bar: '(' _: T, ')' (unit,),) {}; class EZ(inc: '(' _: number, ')' (number,),) {}; class Outer() {}; class TTT[T](ttt: '(' _: T, ')' (T, ttt2: '(' _: T, ')' (T,),),) {}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index 61f20a8cda..57dcd7a5d2 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,9 +1,7 @@
-def pass: (int) -> ((false) | (true))
-def stop: unit -> (int)
-def g: (int) -> (int)
-//│ pass: int -> bool
-//│     = <missing implementation>
-//│ stop: unit -> int
-//│     = <missing implementation>
-//│ g: int -> int
-//│  = <missing implementation>
+:NewParser
+:ParseOnly
+fun pass(_: int): bool
+fun stop(): int
+fun g(_: int): int
+//│ |#fun| |pass|(|_|#:| |int|)|#:| |bool|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|_|#:| |int|)|#:| |int|
+//│ Parsed: {fun pass: [] -> (_: int,) -> bool; fun stop: [] -> () -> int; fun g: [] -> (_: int,) -> int}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 4868aad590..16d91c9ba2 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -1,30 +1,69 @@
-class A: { foo: unit -> (unit) }
-class B: {} & A
-class C[T]: { set: (T) -> (unit); get: unit -> (T) }
-class D: {} & C[number]
-trait Wu: { x: (false) | (true) }
-class WuWu: { y: (false) | (true) } & Wu
-trait WuWuWu: { z: (false) | (true) } & WuWu
-trait Never: { w: unit -> (nothing) } & WuWuWu
-class VG[T]: { x: T }
-class Home[T]: { y: T } & VG[string]
-trait O[I]: { xx: (I) -> (I) }
-class OR[R]: { xx: (R) -> (R) } & O[R]
-class Five'ROTK: { wu: string }
-class Five'Y: {} & Five'ROTK
-class Y: {} & Five'ROTK
-//│ Defined class A
-//│ Defined class B
-//│ Defined class C[=T]
-//│ Defined class D
-//│ Defined trait Wu
-//│ Defined class WuWu
-//│ Defined trait WuWuWu
-//│ Defined trait Never
-//│ Defined class VG[+T]
-//│ Defined class Home[+T]
-//│ Defined trait O[=I]
-//│ Defined class OR[=R]
-//│ Defined class Five'ROTK
-//│ Defined class Five'Y
-//│ Defined class Y
+:NewParser
+:ParseOnly
+class A(foo: (): unit)
+class B: A
+class C<T>(set: (_: T): unit, get: (): T)
+class D: C[number]
+trait Wu(x: bool)
+class WuWu(y: bool): Wu
+trait WuWuWu(z: bool): WuWu
+trait Never(w: (): nothing): WuWuWu
+class VG<T>(x: T)
+class Home<T>(y: T): VG[string]
+trait O<I>(xx: (_: I): I)
+class OR<R>(xx: (_: R): R): O[R]
+namespace Five {
+  class Five'ROTK(wu: string)
+  class Five'Y: Five'ROTK
+}
+class Y: Five'ROTK
+//│ |#class| |A|(|foo|#:| |(||)|#:| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |(|_|#:| |T|)|#:| |unit|,| |get|#:| |(||)|#:| |T|)|↵|#class| |D|#:| |C|[|number|]|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |(||)|#:| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|[|string|]|↵|#trait| |O|‹|I|›|(|xx|#:| |(|_|#:| |I|)|#:| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |(|_|#:| |R|)|#:| |R|)|#:| |O|[|R|]|↵|namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	class A(foo: (): unit)
+//│ ╙──     	               ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	class A(foo: (): unit)
+//│ ╙──     	             ^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
+//│ ╙──     	                      ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
+//│ ╙──     	                                     ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
+//│ ╙──     	                                   ^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
+//│ ╙──     	                ^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.10: 	trait Never(w: (): nothing): WuWuWu
+//│ ╙──      	                 ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.10: 	trait Never(w: (): nothing): WuWuWu
+//│ ╙──      	               ^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.13: 	trait O<I>(xx: (_: I): I)
+//│ ╙──      	                     ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.13: 	trait O<I>(xx: (_: I): I)
+//│ ╙──      	               ^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O[R]
+//│ ╙──      	                      ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O[R]
+//│ ╙──      	                ^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.15: 	namespace Five {
+//│ ╙──      	^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
+//│ ║  l.15: 	namespace Five {
+//│ ║        	               ^
+//│ ║  l.16: 	  class Five'ROTK(wu: string)
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.17: 	  class Five'Y: Five'ROTK
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.18: 	}
+//│ ╙──      	^
+//│ Parsed: {class A(foo: '('  ')' (unit,),) {}; class B(): A {}; class C[T](set: '(' _: T, ')' (unit, get: '('  ')' (T,),),) {}; class D(): (C)[number] {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: '('  ')' (nothing,),): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): (VG)[string] {}; trait O[I](xx: '(' _: I, ')' (I,),): {}; class OR[R](xx: '(' _: R, ')' (R,),): (O)[R] {}; namespace (Five,)}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index 217d49e40d..4c8b023931 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,9 +1,49 @@
-def h1: ((number) -> (number)) -> ((number) -> (number))
-def h2: (string) -> (unit -> (string))
-def h3: ((number) -> (number)) -> (((number) -> (number)) -> ((number) -> (number)))
-//│ h1: (number -> number) -> number -> number
-//│   = <missing implementation>
-//│ h2: string -> unit -> string
-//│   = <missing implementation>
-//│ h3: (number -> number) -> (number -> number) -> number -> number
-//│   = <missing implementation>
+:NewParser
+:ParseOnly
+fun h1(_: (_: number): number, _: number): number
+fun h2(_: string): (): string
+fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ |#fun| |h1|(|_|#:| |(|_|#:| |number|)|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |h2|(|_|#:| |string|)|#:| |(||)|#:| |string|↵|#fun| |h3|(|_|#:| |(|_|#:| |number|)|#:| |number|,| |_|#:| |(|_|#:| |number|)|#:| |number|)|#:| |(|_|#:| |number|)|#:| |number|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	fun h1(_: (_: number): number, _: number): number
+//│ ╙──     	                     ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	fun h1(_: (_: number): number, _: number): number
+//│ ╙──     	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
+//│ ║  l.3: 	fun h1(_: (_: number): number, _: number): number
+//│ ╙──     	          ^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.4: 	fun h2(_: string): (): string
+//│ ╙──     	                     ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.4: 	fun h2(_: string): (): string
+//│ ╙──     	                   ^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '('  ')'
+//│ ║  l.4: 	fun h2(_: string): (): string
+//│ ╙──     	                   ^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	                     ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	                                             ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	                                  ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	                                                                   ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	                                                        ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	                                                        ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
+//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
+//│ ╙──     	          ^^^^^^^^^^^
+//│ Parsed: {fun h1: [] -> anything -> number; fun h2: [] -> (_: string,) -> anything; fun h3: [] -> anything -> anything}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index c476a64b73..88f84360be 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -1,26 +1,91 @@
-trait IFoo: { a: string; b: (number) -> (number); c: unit -> ((false) | (true)); d: (string) -> (unit) }
-trait II[T]: { test: (T) -> (number) }
-def create: unit -> ({ v: number })
-def get: ({ t: string }) -> (string)
-trait IEvent: { callback: (unit) -> ((number) -> (unit)) }
-trait SearchFunc: { __call: (string) -> ((string) -> ((false) | (true))) }
-trait StringArray: { __index: (number) -> (string) }
-trait Counter: { __call: (number) -> (string); interval: number; reset: unit -> (unit) }
-trait Simple: { a: number; b: ((false) | (true)) -> (string) }
-trait Simple2[T]: { abc: T }
-trait Next: {} & Simple
-trait TTT[T]: { ttt: (T) -> (T) }
-//│ Defined trait IFoo
-//│ Defined trait II[-T]
-//│ Defined trait IEvent
-//│ Defined trait SearchFunc
-//│ Defined trait StringArray
-//│ Defined trait Counter
-//│ Defined trait Simple
-//│ Defined trait Simple2[+T]
-//│ Defined trait Next
-//│ Defined trait TTT[=T]
-//│ create: unit -> {v: number}
-//│       = <missing implementation>
-//│ get: {t: string} -> string
-//│    = <missing implementation>
+:NewParser
+:ParseOnly
+trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
+trait II<T>(test: (_: T): number)
+fun create(): (v: number)
+fun get(_: (t: string)): string
+trait IEvent(callback: (_: unit): (_: number): unit)
+trait SearchFunc(__call: (_: string, _: string): bool)
+trait StringArray(__index: (_: number): string)
+trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
+trait Simple(a: number, b: (_: bool): string)
+trait Simple2<T>(abc: T)
+trait Next: Simple
+trait TTT<T>(ttt: (_: T): T)
+//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |(|_|#:| |number|)|#:| |number|,| |c|#:| |(||)|#:| |bool|,| |d|#:| |(|_|#:| |string|)|#:| |unit|)|↵|#trait| |II|‹|T|›|(|test|#:| |(|_|#:| |T|)|#:| |number|)|↵|#fun| |create|(||)|#:| |(|v|#:| |number|)|↵|#fun| |get|(|_|#:| |(|t|#:| |string|)|)|#:| |string|↵|#trait| |IEvent|(|callback|#:| |(|_|#:| |unit|)|#:| |(|_|#:| |number|)|#:| |unit|)|↵|#trait| |SearchFunc|(|__call|#:| |(|_|#:| |string|,| |_|#:| |string|)|#:| |bool|)|↵|#trait| |StringArray|(|__index|#:| |(|_|#:| |number|)|#:| |string|)|↵|#trait| |Counter|(|__call|#:| |(|_|#:| |number|)|#:| |string|,| |interval|#:| |number|,| |reset|#:| |(||)|#:| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |(|_|#:| |bool|)|#:| |string|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |(|_|#:| |T|)|#:| |T|)|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
+//│ ╙──     	                                    ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
+//│ ╙──     	                                                   ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
+//│ ╙──     	                                                                         ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
+//│ ╙──     	                                                              ^^^^^^^^^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
+//│ ╙──     	                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
+//│ ╙──     	                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.4: 	trait II<T>(test: (_: T): number)
+//│ ╙──     	                        ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.4: 	trait II<T>(test: (_: T): number)
+//│ ╙──     	                  ^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' v: number, ')'
+//│ ║  l.5: 	fun create(): (v: number)
+//│ ╙──     	              ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' t: string, ')'
+//│ ║  l.6: 	fun get(_: (t: string)): string
+//│ ╙──     	           ^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.7: 	trait IEvent(callback: (_: unit): (_: number): unit)
+//│ ╙──     	                                ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.7: 	trait IEvent(callback: (_: unit): (_: number): unit)
+//│ ╙──     	                                             ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.7: 	trait IEvent(callback: (_: unit): (_: number): unit)
+//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.8: 	trait SearchFunc(__call: (_: string, _: string): bool)
+//│ ╙──     	                                               ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.8: 	trait SearchFunc(__call: (_: string, _: string): bool)
+//│ ╙──     	                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.9: 	trait StringArray(__index: (_: number): string)
+//│ ╙──     	                                      ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.9: 	trait StringArray(__index: (_: number): string)
+//│ ╙──     	                           ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
+//│ ╙──      	                                 ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
+//│ ╙──      	                                                                      ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
+//│ ╙──      	                                                                    ^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
+//│ ╙──      	                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.11: 	trait Simple(a: number, b: (_: bool): string)
+//│ ╙──      	                                    ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.11: 	trait Simple(a: number, b: (_: bool): string)
+//│ ╙──      	                           ^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.14: 	trait TTT<T>(ttt: (_: T): T)
+//│ ╙──      	                        ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.14: 	trait TTT<T>(ttt: (_: T): T)
+//│ ╙──      	                  ^^^^^^^^^
+//│ Parsed: {trait IFoo(a: string, b: '(' _: number, ')' (number, c: '('  ')' (bool, d: '(' _: string, ')' (unit,),),),): {}; trait II[T](test: '(' _: T, ')' (number,),): {}; fun create: [] -> () -> anything; fun get: [] -> anything -> string; trait IEvent(callback: '(' _: unit, ')' ('(' _: number, ')' (unit,),),): {}; trait SearchFunc(__call: '(' _: string, _: string, ')' (bool,),): {}; trait StringArray(__index: '(' _: number, ')' (string,),): {}; trait Counter(__call: '(' _: number, ')' (string, interval: number, reset: '('  ')' (unit,),),): {}; trait Simple(a: number, b: '(' _: bool, ')' (string,),): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: '(' _: T, ')' (T,),): {}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 50873e53fa..4b09d12729 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,35 +1,44 @@
-def extend[T, U]: (T) -> ((U) -> ((T) & (U)))
-def foo[T, U]: ((T) & (U)) -> (unit)
-def over: (((number) -> (string)) & (({}) -> (string))) -> (string)
-trait IA: { x: number }
-trait IB: { y: number }
-def iii: ((IA) & (IB)) -> ((IA) & (IB))
-def uu[U, V, T, P]: (((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))) -> (((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)))
-def iiii[U, T, V]: (((U) & (T)) & (V)) -> (((U) & (T)) & (V))
-def arr[U, T]: ((MutArray[U]) & (MutArray[T])) -> ((MutArray[U]) & (MutArray[T]))
-def tt[U, T, V]: (((U, T, )) & ((V, V, ))) -> (((U, T, )) & ((V, V, )))
-class A: {}
-class B: {}
-def inter: ((A) & (B)) -> ((A) & (B))
-//│ Defined trait IA
-//│ Defined trait IB
-//│ Defined class A
-//│ Defined class B
-//│ extend: 'a -> 'b -> ('a & 'b)
-//│       = <missing implementation>
-//│ foo: anything -> unit
-//│    = <missing implementation>
-//│ over: (anything -> string) -> string
-//│     = <missing implementation>
-//│ iii: (IA & IB) -> (IA & IB)
-//│    = <missing implementation>
-//│ uu: ('a & 'b | 'c & 'b) -> ('a & 'b | 'c & 'b)
-//│   = <missing implementation>
-//│ iiii: 'a -> 'a
-//│     = <missing implementation>
-//│ arr: MutArray[in 'a | 'b out 'a & 'b] -> MutArray[in 'a | 'b out 'a & 'b]
-//│    = <missing implementation>
-//│ tt: ('a & 'b, 'b & 'c,) -> ('a & 'b, 'b & 'c,)
-//│   = <missing implementation>
-//│ inter: nothing -> nothing
-//│      = <missing implementation>
+:NewParser
+:ParseOnly
+fun extend(_: T, _: U): (T) & (U)
+fun foo(_: (T) & (U)): unit
+fun over(_: ((_: number): string) & ((_: object): string)): string
+trait IA(x: number)
+trait IB(y: number)
+fun iii(_: (IA) & (IB)): (IA) & (IB)
+fun uu(_: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
+fun iiii(_: ((U) & (T)) & (V)): ((U) & (T)) & (V)
+fun arr(_: (MutArray[U]) & (MutArray[T])): (MutArray[U]) & (MutArray[T])
+fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
+class A
+class B
+fun inter(_: (A) & (B)): (A) & (B)
+//│ |#fun| |extend|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|(|_|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|_|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|)|#:| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#fun| |iii|(|_|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|(|_|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|(|_|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|(|_|#:| |(|MutArray|[|U|]|)| |&| |(|MutArray|[|T|]|)|)|#:| |(|MutArray|[|U|]|)| |&| |(|MutArray|[|T|]|)|↵|#fun| |tt|(|_|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#fun| |inter|(|_|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
+//│ ╙──     	                        ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
+//│ ╙──     	             ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
+//│ ╙──     	                                                ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
+//│ ╙──     	                                     ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
+//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
+//│ ╙──     	             ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[U]
+//│ ║  l.11: 	fun arr(_: (MutArray[U]) & (MutArray[T])): (MutArray[U]) & (MutArray[T])
+//│ ╙──      	                                            ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[U]
+//│ ║  l.11: 	fun arr(_: (MutArray[U]) & (MutArray[T])): (MutArray[U]) & (MutArray[T])
+//│ ╙──      	            ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' U, T, ')'
+//│ ║  l.12: 	fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
+//│ ╙──      	                                     ^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' U, T, ')'
+//│ ║  l.12: 	fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
+//│ ╙──      	           ^^^^^^^^
+//│ Parsed: {fun extend: [] -> (_: T, _: U,) -> ((T,) & (U,)); fun foo: [] -> (_: (T,) & (U,),) -> unit; fun over: [] -> anything -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> (_: (IA,) & (IB,),) -> ((IA,) & (IB,)); fun uu: [] -> (_: ((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (_: ((U,) & (T,),) & (V,),) -> (((U,) & (T,),) & (V,)); fun arr: [] -> anything -> anything; fun tt: [] -> anything -> anything; class A() {}; class B() {}; fun inter: [] -> (_: (A,) & (B,),) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index 9025e914dc..5d4c46fc1f 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,32 +1,32 @@
-def multi1: (number) -> (number)
-def multi3: unit -> (unit)
-class Foo: {} & Base
-trait AnotherBase: { y: string }
-def N'f: unit -> (unit)
-def N'g: unit -> (unit)
-def N'h: unit -> (unit)
-def multi2: (string) -> (string)
-def multi4: unit -> (unit)
-trait Base: { a: number }
-class AnotherFoo: {} & AnotherBase
-def multi5: unit -> (unit)
-//│ Defined class Foo
-//│ Defined trait AnotherBase
-//│ Defined trait Base
-//│ Defined class AnotherFoo
-//│ multi1: number -> number
-//│       = <missing implementation>
-//│ multi3: unit -> unit
-//│       = <missing implementation>
-//│ N'f: unit -> unit
-//│    = <missing implementation>
-//│ N'g: unit -> unit
-//│    = <missing implementation>
-//│ N'h: unit -> unit
-//│    = <missing implementation>
-//│ multi2: string -> string
-//│       = <missing implementation>
-//│ multi4: unit -> unit
-//│       = <missing implementation>
-//│ multi5: unit -> unit
-//│       = <missing implementation>
+:NewParser
+:ParseOnly
+fun multi1(_: number): number
+fun multi3(): unit
+class Foo: Base
+trait AnotherBase(y: string)
+namespace N {
+  fun f(): unit
+  fun g(): unit
+  fun h(): unit
+}
+fun multi2(_: string): string
+fun multi4(): unit
+trait Base(a: number)
+class AnotherFoo: AnotherBase
+fun multi5(): unit
+//│ |#fun| |multi1|(|_|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|namespace| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|_|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#fun| |multi5|(||)|#:| |unit|
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.7: 	namespace N {
+//│ ╙──     	^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
+//│ ║  l.7: 	namespace N {
+//│ ║       	            ^
+//│ ║  l.8: 	  fun f(): unit
+//│ ║       	^^^^^^^^^^^^^^^
+//│ ║  l.9: 	  fun g(): unit
+//│ ║       	^^^^^^^^^^^^^^^
+//│ ║  l.10: 	  fun h(): unit
+//│ ║        	^^^^^^^^^^^^^^^
+//│ ║  l.11: 	}
+//│ ╙──      	^
+//│ Parsed: {fun multi1: [] -> (_: number,) -> number; fun multi3: [] -> () -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace (N,)}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index ac23adfa06..103c887ab0 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,31 +1,50 @@
-def N1'f: (anything) -> (number)
-def N1'ff: (anything) -> (number)
-class N1'C: { f: unit -> (unit) }
-trait N1'I: { f: unit -> (number) }
-def N1'N2'fff: ((false) | (true)) -> (number)
-def N1'N2'gg: (N1'C) -> (N1'C)
-class N1'N2'BBB: {} & N1'C
-def AA'f: (anything) -> (string)
-class AA'C: { f: unit -> (unit) }
-trait AA'I: { f: unit -> (number) }
-def f1: (N1'C) -> (N1'C)
-def f2: (AA'C) -> (AA'C)
-//│ Defined class N1'C
-//│ Defined trait N1'I
-//│ Defined class N1'N2'BBB
-//│ Defined class AA'C
-//│ Defined trait AA'I
-//│ N1'f: anything -> number
-//│     = <missing implementation>
-//│ N1'ff: anything -> number
-//│      = <missing implementation>
-//│ N1'N2'fff: bool -> number
-//│          = <missing implementation>
-//│ N1'N2'gg: N1'C -> N1'C
-//│         = <missing implementation>
-//│ AA'f: anything -> string
-//│     = <missing implementation>
-//│ f1: N1'C -> N1'C
-//│   = <missing implementation>
-//│ f2: AA'C -> AA'C
-//│   = <missing implementation>
+:NewParser
+:ParseOnly
+namespace N1 {
+  fun f(_: anything): number
+  fun ff(_: anything): number
+  class N1'C(f: (): unit)
+  trait N1'I(f: (): number)
+  namespace N2 {
+    fun fff(_: bool): number
+    fun gg(_: N1'C): N1'C
+    class N1'N2'BBB: N1'C
+  }
+}
+namespace AA {
+  fun f(_: anything): string
+  class AA'C(f: (): unit)
+  trait AA'I(f: (): number)
+  namespace N2 {
+  }
+}
+fun f1(_: N1'C): N1'C
+fun f2(_: AA'C): AA'C
+//│ |namespace| |N1| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |number|↵|#fun| |ff|(|_|#:| |anything|)|#:| |number|↵|#class| |N1'C|(|f|#:| |(||)|#:| |unit|)|↵|#trait| |N1'I|(|f|#:| |(||)|#:| |number|)|↵|namespace| |N2| |{|→|#fun| |fff|(|_|#:| |bool|)|#:| |number|↵|#fun| |gg|(|_|#:| |N1'C|)|#:| |N1'C|↵|#class| |N1'N2'BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|namespace| |AA| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |string|↵|#class| |AA'C|(|f|#:| |(||)|#:| |unit|)|↵|#trait| |AA'I|(|f|#:| |(||)|#:| |number|)|↵|namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|_|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|_|#:| |AA'C|)|#:| |AA'C|
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	namespace N1 {
+//│ ╙──     	^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
+//│ ║  l.3: 	namespace N1 {
+//│ ║       	             ^
+//│ ║  l.4: 	  fun f(_: anything): number
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.5: 	  fun ff(_: anything): number
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.6: 	  class N1'C(f: (): unit)
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.7: 	  trait N1'I(f: (): number)
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.8: 	  namespace N2 {
+//│ ║       	^^^^^^^^^^^^^^^^
+//│ ║  l.9: 	    fun fff(_: bool): number
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.10: 	    fun gg(_: N1'C): N1'C
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.11: 	    class N1'N2'BBB: N1'C
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.12: 	  }
+//│ ║        	^^^
+//│ ║  l.13: 	}
+//│ ╙──      	^
+//│ Parsed: {namespace (N1,)}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 11aa03f0f0..a5303330f6 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,42 +1,43 @@
-def buildName: (string) -> (((string) | (undefined)) -> (string))
-def buildName2: (string) -> (((string) | (undefined)) -> (string))
-def buildName3: (string) -> ((MutArray[string]) -> (string))
-def buildName4: (string) -> ((MutArray[anything]) -> (string))
-trait SquareConfig: { color: (string) | (undefined); width: (number) | (undefined) }
-def did: (number) -> ((((number) -> (number)) | (undefined)) -> (number))
-def getOrElse: ((MutArray[{}]) | (undefined)) -> ({})
-class ABC: {}
-def testABC: ((ABC) | (undefined)) -> (unit)
-def testSquareConfig: ((SquareConfig) | (undefined)) -> (unit)
-def err: (((number, string, )) | (undefined)) -> (unit)
-def toStr: ((((number) | (false)) | (true)) | (undefined)) -> (string)
-def boo[T, U]: (((T) & (U)) | (undefined)) -> (unit)
-class B[T]: { b: T }
-def boom: ((B[nothing]) | (undefined)) -> (anything)
-//│ Defined trait SquareConfig
-//│ Defined class ABC
-//│ Defined class B[+T]
-//│ buildName: string -> (string | undefined) -> string
-//│          = <missing implementation>
-//│ buildName2: string -> (string | undefined) -> string
-//│           = <missing implementation>
-//│ buildName3: string -> MutArray[string] -> string
-//│           = <missing implementation>
-//│ buildName4: string -> MutArray[anything] -> string
-//│           = <missing implementation>
-//│ did: number -> (number -> number | undefined) -> number
-//│    = <missing implementation>
-//│ getOrElse: (MutArray[anything] | undefined) -> anything
-//│          = <missing implementation>
-//│ testABC: (ABC | undefined) -> unit
-//│        = <missing implementation>
-//│ testSquareConfig: (undefined | SquareConfig) -> unit
-//│                 = <missing implementation>
-//│ err: ((number, string,) | undefined) -> unit
-//│    = <missing implementation>
-//│ toStr: (false | number | true | undefined) -> string
-//│      = <missing implementation>
-//│ boo: anything -> unit
-//│    = <missing implementation>
-//│ boom: (B[nothing] | undefined) -> anything
-//│     = <missing implementation>
+:NewParser
+:ParseOnly
+fun buildName(_: string, _: (string) | (undefined)): string
+fun buildName2(_: string, _: (string) | (undefined)): string
+fun buildName3(_: string, _: MutArray[string]): string
+fun buildName4(_: string, _: MutArray[anything]): string
+trait SquareConfig(color: (string) | (undefined), width: (number) | (undefined))
+fun did(_: number, _: ((_: number): number) | (undefined)): number
+fun getOrElse(_: (MutArray[object]) | (undefined)): object
+class ABC
+fun testABC(_: (ABC) | (undefined)): unit
+fun testSquareConfig(_: (SquareConfig) | (undefined)): unit
+fun err(_: ((number, string, )) | (undefined)): unit
+fun toStr(_: ((number) | (bool)) | (undefined)): string
+fun boo(_: ((T) & (U)) | (undefined)): unit
+class B<T>(b: T)
+fun boom(_: (B[nothing]) | (undefined)): anything
+//│ |#fun| |buildName|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|_|#:| |string|,| |_|#:| |MutArray|[|string|]|)|#:| |string|↵|#fun| |buildName4|(|_|#:| |string|,| |_|#:| |MutArray|[|anything|]|)|#:| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#fun| |did|(|_|#:| |number|,| |_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|_|#:| |(|MutArray|[|object|]|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|↵|#fun| |testABC|(|_|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|_|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|_|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|_|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|(|_|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#fun| |boom|(|_|#:| |(|B|[|nothing|]|)| ||| |(|undefined|)|)|#:| |anything|
+//│ ╔══[ERROR] not a recognized type: (MutArray)[string]
+//│ ║  l.5: 	fun buildName3(_: string, _: MutArray[string]): string
+//│ ╙──     	                             ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[anything]
+//│ ║  l.6: 	fun buildName4(_: string, _: MutArray[anything]): string
+//│ ╙──     	                             ^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
+//│ ╙──     	                                  ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
+//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
+//│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
+//│ ╙──     	                       ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[object]
+//│ ║  l.9: 	fun getOrElse(_: (MutArray[object]) | (undefined)): object
+//│ ╙──     	                  ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' number, string, ')'
+//│ ║  l.13: 	fun err(_: ((number, string, )) | (undefined)): unit
+//│ ╙──      	            ^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (B)[nothing]
+//│ ║  l.17: 	fun boom(_: (B[nothing]) | (undefined)): anything
+//│ ╙──      	             ^^^^^^^^^^
+//│ Parsed: {fun buildName: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName2: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName3: [] -> anything -> string; fun buildName4: [] -> anything -> string; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> anything -> number; fun getOrElse: [] -> anything -> object; class ABC() {}; fun testABC: [] -> (_: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (_: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> anything -> unit; fun toStr: [] -> (_: ((number,) | (bool,),) | (undefined,),) -> string; fun boo: [] -> (_: ((T,) & (U,),) | (undefined,),) -> unit; class B[T](b: T,) {}; fun boom: [] -> anything -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 974ddac99a..2e2fa7eb8a 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,47 +1,57 @@
-def f: ((number) -> (string)) & ((string) -> (string))
-class M: { foo: ((number) -> (string)) & ((string) -> (string)) }
-def app: (((string) -> (unit)) -> ((number) -> (unit))) & (((string) -> (unit)) -> ((string) -> (unit)))
-def create: ((number) -> (unit -> ((false) | (true)))) & (((false) | (true)) -> (unit -> ((false) | (true))))
-def g0: ((MutArray[string]) -> (string)) & ((MutArray[{}]) -> (string))
-def db: ((number) -> (MutArray[number])) & (({}) -> (MutArray[number]))
-class N: {}
-def id: ((M) -> (unit)) & ((N) -> (unit))
-def tst: (({ z: number }) -> ({ y: string })) & (({ z: (false) | (true) }) -> ({ y: string }))
-def op: ((number) -> (((number) | (undefined)) -> (unit))) & ((number) -> ((((false) | (true)) | (undefined)) -> (unit)))
-def swap: (((number, string, )) -> ((number, string, ))) & (((string, number, )) -> ((number, string, )))
-def u: ((((number) | (false)) | (true)) -> (string)) & (({}) -> (string))
-def doSome[T, U]: (anything) -> (unit) /* warning: the overload of function doSome is not supported yet. */
-def XX'f[T]: (T) -> ((anything) -> (string)) /* warning: the overload of function f is not supported yet. */
-class WWW: {}
-  method F[T]: (T) -> (anything) /* warning: the overload of function F is not supported yet. */
-def baz: unit -> (anything) /* warning: the overload of function baz is not supported yet. */
-//│ Defined class M
-//│ Defined class N
-//│ Defined class WWW
-//│ Declared WWW.F: WWW -> anything -> anything
-//│ f: (number | string) -> string
-//│  = <missing implementation>
-//│ app: (string -> unit) -> (number | string) -> unit
-//│    = <missing implementation>
-//│ create: (false | number | true) -> unit -> bool
-//│       = <missing implementation>
-//│ g0: MutArray[in string] -> string
-//│   = <missing implementation>
-//│ db: anything -> MutArray[number]
-//│   = <missing implementation>
-//│ id: (M | N) -> unit
-//│   = <missing implementation>
-//│ tst: {z: false | number | true} -> {y: string}
-//│    = <missing implementation>
-//│ op: number -> (false | number | true | undefined) -> unit
-//│   = <missing implementation>
-//│ swap: (number | string, number | string,) -> (number, string,)
-//│     = <missing implementation>
-//│ u: anything -> string
-//│  = <missing implementation>
-//│ doSome: anything -> unit
-//│       = <missing implementation>
-//│ XX'f: anything -> anything -> string
-//│     = <missing implementation>
-//│ baz: unit -> anything
-//│    = <missing implementation>
+:NewParser
+:ParseOnly
+ fun f((_: number): string) & ((_: string): string)
+class M(foo: ((_: number): string) & ((_: string): string))
+ fun app((_: (_: string): unit, _: number): unit) & ((_: (_: string): unit, _: string): unit)
+ fun create((_: number): (): bool) & ((_: bool): (): bool)
+ fun g0((_: MutArray[string]): string) & ((_: MutArray[object]): string)
+ fun db((_: number): MutArray[number]) & ((_: object): MutArray[number])
+class N
+ fun id((_: M): unit) & ((_: N): unit)
+ fun tst((_: (z: number)): (y: string)) & ((_: (z: bool)): (y: string))
+ fun op((_: number, _: (number) | (undefined)): unit) & ((_: number, _: (bool) | (undefined)): unit)
+ fun swap((_: (number, string, )): (number, string, )) & ((_: (string, number, )): (number, string, ))
+ fun u((_: (number) | (bool)): string) & ((_: object): string)
+fun doSome(_: anything): unit /* warning: the overload of function doSome is not supported yet. */
+namespace XX {
+  fun f(_: T, _: anything): string /* warning: the overload of function f is not supported yet. */
+}
+class WWW(F: (_: T): anything /* warning: the overload of function F is not supported yet. */)
+fun baz(): anything /* warning: the overload of function baz is not supported yet. */
+//│ | |#fun| |f|(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|↵|#class| |M|(|foo|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|)|→|#fun| |app|(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |number|)|#:| |unit|)| |&| |(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |string|)|#:| |unit|)|↵|#fun| |create|(|(|_|#:| |number|)|#:| |(||)|#:| |bool|)| |&| |(|(|_|#:| |bool|)|#:| |(||)|#:| |bool|)|↵|#fun| |g0|(|(|_|#:| |MutArray|[|string|]|)|#:| |string|)| |&| |(|(|_|#:| |MutArray|[|object|]|)|#:| |string|)|↵|#fun| |db|(|(|_|#:| |number|)|#:| |MutArray|[|number|]|)| |&| |(|(|_|#:| |object|)|#:| |MutArray|[|number|]|)|←|↵|#class| |N|→|#fun| |id|(|(|_|#:| |M|)|#:| |unit|)| |&| |(|(|_|#:| |N|)|#:| |unit|)|↵|#fun| |tst|(|(|_|#:| |(|z|#:| |number|)|)|#:| |(|y|#:| |string|)|)| |&| |(|(|_|#:| |(|z|#:| |bool|)|)|#:| |(|y|#:| |string|)|)|↵|#fun| |op|(|(|_|#:| |number|,| |_|#:| |(|number|)| ||| |(|undefined|)|)|#:| |unit|)| |&| |(|(|_|#:| |number|,| |_|#:| |(|bool|)| ||| |(|undefined|)|)|#:| |unit|)|↵|#fun| |swap|(|(|_|#:| |(|number|,| |string|,| |)|)|#:| |(|number|,| |string|,| |)|)| |&| |(|(|_|#:| |(|string|,| |number|,| |)|)|#:| |(|number|,| |string|,| |)|)|↵|#fun| |u|(|(|_|#:| |(|number|)| ||| |(|bool|)|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|←|↵|#fun| |doSome|(|_|#:| |anything|)|#:| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|namespace| |XX| |{|→|#fun| |f|(|_|#:| |T|,| |_|#:| |anything|)|#:| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |(|_|#:| |T|)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#fun| |baz|(||)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
+//│ ╙──     	                  ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
+//│ ╙──     	       ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Expected function parameter list; found operator instead
+//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
+//│ ╙──     	                            ^
+//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found parenthesis section instead
+//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
+//│ ╙──     	                              ^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
+//│ ╙──     	                         ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
+//│ ╙──     	              ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
+//│ ╙──     	                                                 ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
+//│ ╙──     	                                      ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Expected end of input; found indented block instead
+//│ ║  l.5: 	 fun app((_: (_: string): unit, _: number): unit) & ((_: (_: string): unit, _: string): unit)
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.6: 	 fun create((_: number): (): bool) & ((_: bool): (): bool)
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.7: 	 fun g0((_: MutArray[string]): string) & ((_: MutArray[object]): string)
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.8: 	 fun db((_: number): MutArray[number]) & ((_: object): MutArray[number])
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.9: 	class N
+//│ ╙──     	^
+//│ Parsed: {fun f = '(' _: number, ')' (string,), => undefined; class M(foo: & ('(' _: number, ')' (string,),) ('(' _: string, ')' (string,),),) {}}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index be0c3f71ce..b1fa0d1f41 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,40 +1,78 @@
-def key: ((string, (false) | (true), )) -> (string)
-def value: ((string, (false) | (true), )) -> ((false) | (true))
-def third: ((number, number, number, )) -> (number)
-def vec2: (number) -> ((number) -> ((number, number, )))
-def twoFunctions: (((number) -> (number), (number) -> (number), )) -> ((number) -> (number))
-def tupleIt: (string) -> ((unit -> (string), ))
-def s: ((false) | (true)) -> (((string) | (number), ((number) | (false)) | (true), ))
-def s2: (((false) | (true), (string) | (number), )) -> ((string) | (number))
-def ex[T, U]: (T) -> ((U) -> ((T, U, (T) & (U), )))
-def foo[T, U]: (((T) & (U), )) -> (unit)
-def conv: ({ y: number }) -> (({ y: number }, { z: string }, ))
-class A: { x: number }
-class B: {}
-def swap: ((A, B, )) -> ((B, A, ))
-//│ Defined class A
-//│ Defined class B
-//│ key: (string, bool,) -> string
-//│    = <missing implementation>
-//│ value: (string, bool,) -> bool
-//│      = <missing implementation>
-//│ third: (number, number, number,) -> number
-//│      = <missing implementation>
-//│ vec2: number -> number -> (number, number,)
-//│     = <missing implementation>
-//│ twoFunctions: (number -> number, number -> number,) -> number -> number
-//│             = <missing implementation>
-//│ tupleIt: string -> (unit -> string,)
-//│        = <missing implementation>
-//│ s: bool -> (number | string, false | number | true,)
-//│  = <missing implementation>
-//│ s2: (bool, number | string,) -> (number | string)
-//│   = <missing implementation>
-//│ ex: 'a -> 'b -> ('a, 'b, 'a & 'b,)
-//│   = <missing implementation>
-//│ foo: anything -> unit
-//│    = <missing implementation>
-//│ conv: {y: number} -> ({y: number}, {z: string},)
-//│     = <missing implementation>
-//│ swap: (A, B,) -> (B, A,)
-//│     = <missing implementation>
+:NewParser
+:ParseOnly
+fun key(_: (string, bool, )): string
+fun value(_: (string, bool, )): bool
+fun third(_: (number, number, number, )): number
+fun vec2(_: number, _: number): (number, number, )
+fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
+fun tupleIt(_: string): ((): string, )
+fun s(_: bool): ((string) | (number), (number) | (bool), )
+fun s2(_: (bool, (string) | (number), )): (string) | (number)
+fun ex(_: T, _: U): (T, U, (T) & (U), )
+fun foo(_: ((T) & (U), )): unit
+fun conv(_: (y: number)): ((y: number), (z: string), )
+class A(x: number)
+class B
+fun swap(_: (A, B, )): (B, A, )
+//│ |#fun| |key|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |string|↵|#fun| |value|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |bool|↵|#fun| |third|(|_|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|_|#:| |number|,| |_|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|_|#:| |(|(|_|#:| |number|)|#:| |number|,| |(|_|#:| |number|)|#:| |number|,| |)|,| |_|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|_|#:| |string|)|#:| |(|(||)|#:| |string|,| |)|↵|#fun| |s|(|_|#:| |bool|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|(|_|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|(|_|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|_|#:| |(|y|#:| |number|)|)|#:| |(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#fun| |swap|(|_|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
+//│ ╔══[ERROR] not a recognized type: '(' string, bool, ')'
+//│ ║  l.3: 	fun key(_: (string, bool, )): string
+//│ ╙──     	           ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' string, bool, ')'
+//│ ║  l.4: 	fun value(_: (string, bool, )): bool
+//│ ╙──     	             ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' number, number, number, ')'
+//│ ║  l.5: 	fun third(_: (number, number, number, )): number
+//│ ╙──     	             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' number, number, ')'
+//│ ║  l.6: 	fun vec2(_: number, _: number): (number, number, )
+//│ ╙──     	                                ^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
+//│ ╙──     	                                ^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
+//│ ╙──     	                                                     ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
+//│ ╙──     	                                          ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
+//│ ╙──     	                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' '(' _: number, ')' (number, '(' _: number, ')' (number,),), ')'
+//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
+//│ ╙──     	                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.8: 	fun tupleIt(_: string): ((): string, )
+//│ ╙──     	                           ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.8: 	fun tupleIt(_: string): ((): string, )
+//│ ╙──     	                         ^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' '('  ')' (string,), ')'
+//│ ║  l.8: 	fun tupleIt(_: string): ((): string, )
+//│ ╙──     	                        ^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' | (string,) (number,), | (number,) (bool,), ')'
+//│ ║  l.9: 	fun s(_: bool): ((string) | (number), (number) | (bool), )
+//│ ╙──     	                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' bool, | (string,) (number,), ')'
+//│ ║  l.10: 	fun s2(_: (bool, (string) | (number), )): (string) | (number)
+//│ ╙──      	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' T, U, & (T,) (U,), ')'
+//│ ║  l.11: 	fun ex(_: T, _: U): (T, U, (T) & (U), )
+//│ ╙──      	                    ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' & (T,) (U,), ')'
+//│ ║  l.12: 	fun foo(_: ((T) & (U), )): unit
+//│ ╙──      	           ^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' '(' y: number, ')', '(' z: string, ')', ')'
+//│ ║  l.13: 	fun conv(_: (y: number)): ((y: number), (z: string), )
+//│ ╙──      	                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' y: number, ')'
+//│ ║  l.13: 	fun conv(_: (y: number)): ((y: number), (z: string), )
+//│ ╙──      	            ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' B, A, ')'
+//│ ║  l.16: 	fun swap(_: (A, B, )): (B, A, )
+//│ ╙──      	                       ^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' A, B, ')'
+//│ ║  l.16: 	fun swap(_: (A, B, )): (B, A, )
+//│ ╙──      	            ^^^^^^^^
+//│ Parsed: {fun key: [] -> anything -> string; fun value: [] -> anything -> bool; fun third: [] -> anything -> number; fun vec2: [] -> (_: number, _: number,) -> anything; fun twoFunctions: [] -> anything -> number; fun tupleIt: [] -> (_: string,) -> anything; fun s: [] -> (_: bool,) -> anything; fun s2: [] -> anything -> ((string,) | (number,)); fun ex: [] -> (_: T, _: U,) -> anything; fun foo: [] -> anything -> unit; fun conv: [] -> anything -> anything; class A(x: number,) {}; class B() {}; fun swap: [] -> anything -> anything}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index 4521d17195..62728d7cd6 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,38 +1,65 @@
-def inc[T]: (T) -> (number)
-class CC[T]: { print: (T) -> (unit) }
-def con[U, T]: (T) -> (U)
-class Printer[T]: { print: (T) -> (unit) }
-def setStringPrinter: (Printer[string]) -> (unit)
-def getStringPrinter: unit -> (Printer[string])
-def foo[T]: (Printer[T]) -> ((T) -> (T))
-def foo2[T]: (Printer[T]) -> ((T) -> (T))
-class F[T]: { x: T }
-  method GG[U]: (U) -> (T)
-trait I[T]: { x: T }
-  method GG[U]: (U) -> (T)
-class FFF[T]: { fff: (T) -> (unit) }
-def fff: (FFF[string]) -> ((string) -> (unit))
-def getFFF: unit -> (FFF[number])
-//│ Defined class CC[-T]
-//│ Defined class Printer[-T]
-//│ Defined class F[+T]
-//│ Declared F.GG: F['T] -> anything -> 'T
-//│ Defined trait I[+T]
-//│ Declared I.GG: I['T] -> anything -> 'T
-//│ Defined class FFF[-T]
-//│ inc: anything -> number
-//│    = <missing implementation>
-//│ con: anything -> nothing
-//│    = <missing implementation>
-//│ setStringPrinter: Printer[string] -> unit
-//│                 = <missing implementation>
-//│ getStringPrinter: unit -> Printer[string]
-//│                 = <missing implementation>
-//│ foo: Printer['a] -> 'a -> 'a
-//│    = <missing implementation>
-//│ foo2: Printer['a] -> 'a -> 'a
-//│     = <missing implementation>
-//│ fff: FFF[string] -> string -> unit
-//│    = <missing implementation>
-//│ getFFF: unit -> FFF[number]
-//│       = <missing implementation>
+:NewParser
+:ParseOnly
+fun inc(_: T): number
+class CC<T>(print: (_: T): unit)
+fun con(_: T): U
+class Printer<T>(print: (_: T): unit)
+fun setStringPrinter(_: Printer[string]): unit
+fun getStringPrinter(): Printer[string]
+fun foo(_: Printer[T], _: T): T
+fun foo2(_: Printer[T], _: T): T
+class F<T>(x: T, GG: (_: U): T)
+trait I<T>(x: T, GG: (_: U): T)
+class FFF<T>(fff: (_: T): unit)
+fun fff(_: FFF[string], _: string): unit
+fun getFFF(): FFF[number]
+//│ |#fun| |inc|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |con|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |setStringPrinter|(|_|#:| |Printer|[|string|]|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|[|string|]|↵|#fun| |foo|(|_|#:| |Printer|[|T|]|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|(|_|#:| |Printer|[|T|]|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |fff|(|_|#:| |FFF|[|string|]|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|[|number|]|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.4: 	class CC<T>(print: (_: T): unit)
+//│ ╙──     	                         ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.4: 	class CC<T>(print: (_: T): unit)
+//│ ╙──     	                   ^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.6: 	class Printer<T>(print: (_: T): unit)
+//│ ╙──     	                              ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.6: 	class Printer<T>(print: (_: T): unit)
+//│ ╙──     	                        ^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (Printer)[string]
+//│ ║  l.7: 	fun setStringPrinter(_: Printer[string]): unit
+//│ ╙──     	                        ^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (Printer)[string]
+//│ ║  l.8: 	fun getStringPrinter(): Printer[string]
+//│ ╙──     	                        ^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (Printer)[T]
+//│ ║  l.9: 	fun foo(_: Printer[T], _: T): T
+//│ ╙──     	           ^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (Printer)[T]
+//│ ║  l.10: 	fun foo2(_: Printer[T], _: T): T
+//│ ╙──      	            ^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.11: 	class F<T>(x: T, GG: (_: U): T)
+//│ ╙──      	                           ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.11: 	class F<T>(x: T, GG: (_: U): T)
+//│ ╙──      	                     ^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.12: 	trait I<T>(x: T, GG: (_: U): T)
+//│ ╙──      	                           ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.12: 	trait I<T>(x: T, GG: (_: U): T)
+//│ ╙──      	                     ^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.13: 	class FFF<T>(fff: (_: T): unit)
+//│ ╙──      	                        ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.13: 	class FFF<T>(fff: (_: T): unit)
+//│ ╙──      	                  ^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (FFF)[string]
+//│ ║  l.14: 	fun fff(_: FFF[string], _: string): unit
+//│ ╙──      	           ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (FFF)[number]
+//│ ║  l.15: 	fun getFFF(): FFF[number]
+//│ ╙──      	              ^^^^^^^^^^^
+//│ Parsed: {fun inc: [] -> (_: T,) -> number; class CC[T](print: '(' _: T, ')' (unit,),) {}; fun con: [] -> (_: T,) -> U; class Printer[T](print: '(' _: T, ')' (unit,),) {}; fun setStringPrinter: [] -> anything -> unit; fun getStringPrinter: [] -> () -> anything; fun foo: [] -> anything -> T; fun foo2: [] -> anything -> T; class F[T](x: T, GG: '(' _: U, ')' (T,),) {}; trait I[T](x: T, GG: '(' _: U, ')' (T,),): {}; class FFF[T](fff: '(' _: T, ')' (unit,),) {}; fun fff: [] -> anything -> unit; fun getFFF: [] -> () -> anything}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index aa07c25cf3..63669018d5 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,21 +1,32 @@
-def getString: ((((string) | (number)) | (false)) | (true)) -> (string)
-def test: ((false) | (true)) -> ((string) | (number))
-def run: (((number) -> (number)) | ((number) -> (string))) -> (anything)
-def get: ((MutArray[number]) | (MutArray[string])) -> (unit)
-def get2: (((string, string, )) | ((number, string, ))) -> (string)
-def typeVar[T, U]: ((T) | (U)) -> ((T) | (U))
-def uuuu: ((((string) | (number)) | (false)) | (true)) -> ((((string) | (number)) | (false)) | (true))
-//│ getString: (false | number | string | true) -> string
-//│          = <missing implementation>
-//│ test: bool -> (number | string)
-//│     = <missing implementation>
-//│ run: (number -> (number | string)) -> anything
-//│    = <missing implementation>
-//│ get: MutArray[out number | string] -> unit
-//│    = <missing implementation>
-//│ get2: (number | string, string,) -> string
-//│     = <missing implementation>
-//│ typeVar: 'a -> 'a
-//│        = <missing implementation>
-//│ uuuu: (false | number | string | true) -> (false | number | string | true)
-//│     = <missing implementation>
+:NewParser
+:ParseOnly
+fun getString(_: ((string) | (number)) | (bool)): string
+fun test(_: bool): (string) | (number)
+fun run(_: ((_: number): number) | ((_: number): string)): anything
+fun get(_: (MutArray[number]) | (MutArray[string])): unit
+fun get2(_: ((string, string, )) | ((number, string, ))): string
+fun typeVar(_: (T) | (U)): (T) | (U)
+fun uuuu(_: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
+//│ |#fun| |getString|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|_|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|(|_|#:| |number|)|#:| |string|)|)|#:| |anything|↵|#fun| |get|(|_|#:| |(|MutArray|[|number|]|)| ||| |(|MutArray|[|string|]|)|)|#:| |unit|↵|#fun| |get2|(|_|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|(|_|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
+//│ ╙──     	                       ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
+//│ ╙──     	            ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
+//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
+//│ ╙──     	                                               ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
+//│ ╙──     	                                    ^^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
+//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
+//│ ╙──     	            ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: (MutArray)[number]
+//│ ║  l.6: 	fun get(_: (MutArray[number]) | (MutArray[string])): unit
+//│ ╙──     	            ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' string, string, ')'
+//│ ║  l.7: 	fun get2(_: ((string, string, )) | ((number, string, ))): string
+//│ ╙──     	             ^^^^^^^^^^^^^^^^^^
+//│ Parsed: {fun getString: [] -> (_: ((string,) | (number,),) | (bool,),) -> string; fun test: [] -> (_: bool,) -> ((string,) | (number,)); fun run: [] -> anything -> anything; fun get: [] -> anything -> unit; fun get2: [] -> anything -> string; fun typeVar: [] -> (_: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (_: ((string,) | (number,),) | (bool,),) -> (((string,) | (number,),) | (bool,))}

From f349b5f84c8b6f681592e8985d389650eec597e6 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 09:35:38 +0800
Subject: [PATCH 02/40] Fix type parameter substitution

---
 .../main/scala/ts2mls/types/Converter.scala   |   4 +-
 ts2mls/js/src/test/diff/Array.d.mls           | 140 ++++++------------
 ts2mls/js/src/test/diff/Heritage.d.mls        |  14 +-
 ts2mls/js/src/test/diff/Intersection.d.mls    |  16 +-
 ts2mls/js/src/test/diff/Optional.d.mls        |  34 ++---
 ts2mls/js/src/test/diff/Overload.d.mls        |  10 +-
 ts2mls/js/src/test/diff/TypeParameter.d.mls   |  50 +++----
 ts2mls/js/src/test/diff/Union.d.mls           |  10 +-
 8 files changed, 117 insertions(+), 161 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 8c2c7e6b8d..18c12fa24b 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -39,12 +39,12 @@ object Converter {
     case TSIntersectionType(lhs, rhs) => s"(${convert(lhs)}) & (${convert(rhs)})"
     case TSTypeParameter(name, _) => name // constraints should be translated where the type parameters were created rather than be used
     case TSTupleType(lst) => s"(${lst.foldLeft("")((p, t) => s"$p${convert(t)}, ")})"
-    case TSArrayType(element) => s"MutArray[${convert(element)}]"
+    case TSArrayType(element) => s"MutArray<${convert(element)}>"
     case TSEnumType => "int"
     case TSMemberType(base, _) => convert(base) // TODO: support private/protected members
     case TSInterfaceType(name, members, typeVars, parents) => convertRecord(s"trait $name", members, typeVars, parents)
     case TSClassType(name, members, _, typeVars, parents) => convertRecord(s"class $name", members, typeVars, parents) // TODO: support static members
-    case TSSubstitutionType(base, applied) => s"${base}[${applied.map((app) => convert(app)).reduceLeft((res, s) => s"$res, $s")}]"
+    case TSSubstitutionType(base, applied) => s"${base}<${applied.map((app) => convert(app)).reduceLeft((res, s) => s"$res, $s")}>"
     case overload @ TSIgnoredOverload(base, _) => s"${convert(base)} ${overload.warning}"
   }
 
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index bce71ef8c5..b6a927e4ae 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,97 +1,53 @@
 :NewParser
 :ParseOnly
-fun first(_: MutArray[string]): string
-fun getZero3(): MutArray[number]
-fun first2(_: MutArray[(_: number): number]): (_: number): number
-fun doEs(_: MutArray[int]): MutArray[int]
+fun first(_: MutArray<string>): string
+fun getZero3(): MutArray<number>
+fun first2(_: MutArray<(_: number): number>): (_: number): number
+fun doEs(_: MutArray<int>): MutArray<int>
 class C
 trait I(i: number)
-fun doCs(_: MutArray[C]): MutArray[C]
-fun doIs(_: MutArray[I]): MutArray[I]
-fun inter(_: MutArray[(U) & (T)]): MutArray[(U) & (T)]
-fun clean(_: MutArray[(string, number, )]): MutArray[(string, number, )]
-fun translate(_: MutArray[T]): MutArray[U]
-fun uu(_: MutArray[(number) | (bool)]): MutArray[(number) | (bool)]
+fun doCs(_: MutArray<C>): MutArray<C>
+fun doIs(_: MutArray<I>): MutArray<I>
+fun inter(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
+fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
+fun translate(_: MutArray<T>): MutArray<U>
+fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
 class Temp<T>(x: T)
-fun ta(_: MutArray[Temp[bool]]): MutArray[Temp[bool]]
-fun tat(_: MutArray[Temp[T]]): MutArray[Temp[T]]
-//│ |#fun| |first|(|_|#:| |MutArray|[|string|]|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|[|number|]|↵|#fun| |first2|(|_|#:| |MutArray|[|(|_|#:| |number|)|#:| |number|]|)|#:| |(|_|#:| |number|)|#:| |number|↵|#fun| |doEs|(|_|#:| |MutArray|[|int|]|)|#:| |MutArray|[|int|]|↵|#class| |C|↵|#trait| |I|(|i|#:| |number|)|↵|#fun| |doCs|(|_|#:| |MutArray|[|C|]|)|#:| |MutArray|[|C|]|↵|#fun| |doIs|(|_|#:| |MutArray|[|I|]|)|#:| |MutArray|[|I|]|↵|#fun| |inter|(|_|#:| |MutArray|[|(|U|)| |&| |(|T|)|]|)|#:| |MutArray|[|(|U|)| |&| |(|T|)|]|↵|#fun| |clean|(|_|#:| |MutArray|[|(|string|,| |number|,| |)|]|)|#:| |MutArray|[|(|string|,| |number|,| |)|]|↵|#fun| |translate|(|_|#:| |MutArray|[|T|]|)|#:| |MutArray|[|U|]|↵|#fun| |uu|(|_|#:| |MutArray|[|(|number|)| ||| |(|bool|)|]|)|#:| |MutArray|[|(|number|)| ||| |(|bool|)|]|↵|#class| |Temp|‹|T|›|(|x|#:| |T|)|↵|#fun| |ta|(|_|#:| |MutArray|[|Temp|[|bool|]|]|)|#:| |MutArray|[|Temp|[|bool|]|]|↵|#fun| |tat|(|_|#:| |MutArray|[|Temp|[|T|]|]|)|#:| |MutArray|[|Temp|[|T|]|]|
-//│ ╔══[ERROR] not a recognized type: (MutArray)[string]
-//│ ║  l.3: 	fun first(_: MutArray[string]): string
-//│ ╙──     	             ^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[number]
-//│ ║  l.4: 	fun getZero3(): MutArray[number]
-//│ ╙──     	                ^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
-//│ ╙──     	                                  ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
-//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
-//│ ╙──     	                                                         ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
-//│ ╙──     	                                              ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
-//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
-//│ ╙──     	                                              ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)['(' _: number, ')' (number,)]
-//│ ║  l.5: 	fun first2(_: MutArray[(_: number): number]): (_: number): number
-//│ ╙──     	              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[int]
-//│ ║  l.6: 	fun doEs(_: MutArray[int]): MutArray[int]
-//│ ╙──     	                            ^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[int]
-//│ ║  l.6: 	fun doEs(_: MutArray[int]): MutArray[int]
-//│ ╙──     	            ^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[C]
-//│ ║  l.9: 	fun doCs(_: MutArray[C]): MutArray[C]
-//│ ╙──     	                          ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[C]
-//│ ║  l.9: 	fun doCs(_: MutArray[C]): MutArray[C]
-//│ ╙──     	            ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[I]
-//│ ║  l.10: 	fun doIs(_: MutArray[I]): MutArray[I]
-//│ ╙──      	                          ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[I]
-//│ ║  l.10: 	fun doIs(_: MutArray[I]): MutArray[I]
-//│ ╙──      	            ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[& (U,) (T,)]
-//│ ║  l.11: 	fun inter(_: MutArray[(U) & (T)]): MutArray[(U) & (T)]
-//│ ╙──      	                                   ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[& (U,) (T,)]
-//│ ║  l.11: 	fun inter(_: MutArray[(U) & (T)]): MutArray[(U) & (T)]
-//│ ╙──      	             ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)['(' string, number, ')']
-//│ ║  l.12: 	fun clean(_: MutArray[(string, number, )]): MutArray[(string, number, )]
-//│ ╙──      	                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)['(' string, number, ')']
-//│ ║  l.12: 	fun clean(_: MutArray[(string, number, )]): MutArray[(string, number, )]
-//│ ╙──      	             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[U]
-//│ ║  l.13: 	fun translate(_: MutArray[T]): MutArray[U]
-//│ ╙──      	                               ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[T]
-//│ ║  l.13: 	fun translate(_: MutArray[T]): MutArray[U]
-//│ ╙──      	                 ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[| (number,) (bool,)]
-//│ ║  l.14: 	fun uu(_: MutArray[(number) | (bool)]): MutArray[(number) | (bool)]
-//│ ╙──      	                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[| (number,) (bool,)]
-//│ ║  l.14: 	fun uu(_: MutArray[(number) | (bool)]): MutArray[(number) | (bool)]
-//│ ╙──      	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[bool]]
-//│ ║  l.16: 	fun ta(_: MutArray[Temp[bool]]): MutArray[Temp[bool]]
-//│ ╙──      	                                 ^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[bool]]
-//│ ║  l.16: 	fun ta(_: MutArray[Temp[bool]]): MutArray[Temp[bool]]
-//│ ╙──      	          ^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[T]]
-//│ ║  l.17: 	fun tat(_: MutArray[Temp[T]]): MutArray[Temp[T]]
-//│ ╙──      	                               ^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[(Temp)[T]]
-//│ ║  l.17: 	fun tat(_: MutArray[Temp[T]]): MutArray[Temp[T]]
-//│ ╙──      	           ^^^^^^^^^^^^^^^^^
-//│ Parsed: {fun first: [] -> anything -> string; fun getZero3: [] -> () -> anything; fun first2: [] -> anything -> anything; fun doEs: [] -> anything -> anything; class C() {}; trait I(i: number,): {}; fun doCs: [] -> anything -> anything; fun doIs: [] -> anything -> anything; fun inter: [] -> anything -> anything; fun clean: [] -> anything -> anything; fun translate: [] -> anything -> anything; fun uu: [] -> anything -> anything; class Temp[T](x: T,) {}; fun ta: [] -> anything -> anything; fun tat: [] -> anything -> anything}
+fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
+fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.11: 	fun inter(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
+//│ ║        	                                ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.11: 	fun inter(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
+//│ ╙──      	                     ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.12: 	fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
+//│ ║        	                                         ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.12: 	fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
+//│ ╙──      	                     ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.14: 	fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
+//│ ║        	                                     ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.14: 	fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
+//│ ╙──      	                  ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.16: 	fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
+//│ ║        	                              ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.16: 	fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
+//│ ╙──      	                       ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.17: 	fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
+//│ ║        	                            ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.17: 	fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
+//│ ╙──      	                        ^
+//│ ╔══[PARSE ERROR] Unmatched opening angle bracket
+//│ ║  l.17: 	fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
+//│ ║        	                                            ^
+//│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator
+//│ |T|>>|Temp|
+//│ Parsed: {>> (T,) (Temp,)}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 16d91c9ba2..ab2611083c 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -3,21 +3,21 @@
 class A(foo: (): unit)
 class B: A
 class C<T>(set: (_: T): unit, get: (): T)
-class D: C[number]
+class D: C<number>
 trait Wu(x: bool)
 class WuWu(y: bool): Wu
 trait WuWuWu(z: bool): WuWu
 trait Never(w: (): nothing): WuWuWu
 class VG<T>(x: T)
-class Home<T>(y: T): VG[string]
+class Home<T>(y: T): VG<string>
 trait O<I>(xx: (_: I): I)
-class OR<R>(xx: (_: R): R): O[R]
+class OR<R>(xx: (_: R): R): O<R>
 namespace Five {
   class Five'ROTK(wu: string)
   class Five'Y: Five'ROTK
 }
 class Y: Five'ROTK
-//│ |#class| |A|(|foo|#:| |(||)|#:| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |(|_|#:| |T|)|#:| |unit|,| |get|#:| |(||)|#:| |T|)|↵|#class| |D|#:| |C|[|number|]|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |(||)|#:| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|[|string|]|↵|#trait| |O|‹|I|›|(|xx|#:| |(|_|#:| |I|)|#:| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |(|_|#:| |R|)|#:| |R|)|#:| |O|[|R|]|↵|namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
+//│ |#class| |A|(|foo|#:| |(||)|#:| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |(|_|#:| |T|)|#:| |unit|,| |get|#:| |(||)|#:| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |(||)|#:| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |(|_|#:| |I|)|#:| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |(|_|#:| |R|)|#:| |R|)|#:| |O|‹|R|›|↵|namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.3: 	class A(foo: (): unit)
 //│ ╙──     	               ^
@@ -49,10 +49,10 @@ class Y: Five'ROTK
 //│ ║  l.13: 	trait O<I>(xx: (_: I): I)
 //│ ╙──      	               ^^^^^^^^^
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O[R]
+//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O<R>
 //│ ╙──      	                      ^
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O[R]
+//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O<R>
 //│ ╙──      	                ^^^^^^^^^
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
 //│ ║  l.15: 	namespace Five {
@@ -66,4 +66,4 @@ class Y: Five'ROTK
 //│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.18: 	}
 //│ ╙──      	^
-//│ Parsed: {class A(foo: '('  ')' (unit,),) {}; class B(): A {}; class C[T](set: '(' _: T, ')' (unit, get: '('  ')' (T,),),) {}; class D(): (C)[number] {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: '('  ')' (nothing,),): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): (VG)[string] {}; trait O[I](xx: '(' _: I, ')' (I,),): {}; class OR[R](xx: '(' _: R, ')' (R,),): (O)[R] {}; namespace (Five,)}
+//│ Parsed: {class A(foo: '('  ')' (unit,),) {}; class B(): A {}; class C[T](set: '(' _: T, ')' (unit, get: '('  ')' (T,),),) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: '('  ')' (nothing,),): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: '(' _: I, ')' (I,),): {}; class OR[R](xx: '(' _: R, ')' (R,),): O‹R› {}; namespace (Five,)}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 4b09d12729..3dad334035 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -8,12 +8,12 @@ trait IB(y: number)
 fun iii(_: (IA) & (IB)): (IA) & (IB)
 fun uu(_: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
 fun iiii(_: ((U) & (T)) & (V)): ((U) & (T)) & (V)
-fun arr(_: (MutArray[U]) & (MutArray[T])): (MutArray[U]) & (MutArray[T])
+fun arr(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
 fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
 class A
 class B
 fun inter(_: (A) & (B)): (A) & (B)
-//│ |#fun| |extend|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|(|_|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|_|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|)|#:| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#fun| |iii|(|_|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|(|_|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|(|_|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|(|_|#:| |(|MutArray|[|U|]|)| |&| |(|MutArray|[|T|]|)|)|#:| |(|MutArray|[|U|]|)| |&| |(|MutArray|[|T|]|)|↵|#fun| |tt|(|_|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#fun| |inter|(|_|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
+//│ |#fun| |extend|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|(|_|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|_|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|)|#:| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#fun| |iii|(|_|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|(|_|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|(|_|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|(|_|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|(|_|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#fun| |inter|(|_|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
 //│ ╙──     	                        ^
@@ -29,12 +29,12 @@ fun inter(_: (A) & (B)): (A) & (B)
 //│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
 //│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
 //│ ╙──     	             ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[U]
-//│ ║  l.11: 	fun arr(_: (MutArray[U]) & (MutArray[T])): (MutArray[U]) & (MutArray[T])
-//│ ╙──      	                                            ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[U]
-//│ ║  l.11: 	fun arr(_: (MutArray[U]) & (MutArray[T])): (MutArray[U]) & (MutArray[T])
-//│ ╙──      	            ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: MutArray‹U›
+//│ ║  l.11: 	fun arr(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
+//│ ╙──      	                                            ^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: MutArray‹U›
+//│ ║  l.11: 	fun arr(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
+//│ ╙──      	            ^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' U, T, ')'
 //│ ║  l.12: 	fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
 //│ ╙──      	                                     ^^^^^^^^
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index a5303330f6..5ce9540a68 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -2,11 +2,11 @@
 :ParseOnly
 fun buildName(_: string, _: (string) | (undefined)): string
 fun buildName2(_: string, _: (string) | (undefined)): string
-fun buildName3(_: string, _: MutArray[string]): string
-fun buildName4(_: string, _: MutArray[anything]): string
+fun buildName3(_: string, _: MutArray<string>): string
+fun buildName4(_: string, _: MutArray<anything>): string
 trait SquareConfig(color: (string) | (undefined), width: (number) | (undefined))
 fun did(_: number, _: ((_: number): number) | (undefined)): number
-fun getOrElse(_: (MutArray[object]) | (undefined)): object
+fun getOrElse(_: (MutArray<object>) | (undefined)): object
 class ABC
 fun testABC(_: (ABC) | (undefined)): unit
 fun testSquareConfig(_: (SquareConfig) | (undefined)): unit
@@ -14,14 +14,14 @@ fun err(_: ((number, string, )) | (undefined)): unit
 fun toStr(_: ((number) | (bool)) | (undefined)): string
 fun boo(_: ((T) & (U)) | (undefined)): unit
 class B<T>(b: T)
-fun boom(_: (B[nothing]) | (undefined)): anything
-//│ |#fun| |buildName|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|_|#:| |string|,| |_|#:| |MutArray|[|string|]|)|#:| |string|↵|#fun| |buildName4|(|_|#:| |string|,| |_|#:| |MutArray|[|anything|]|)|#:| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#fun| |did|(|_|#:| |number|,| |_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|_|#:| |(|MutArray|[|object|]|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|↵|#fun| |testABC|(|_|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|_|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|_|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|_|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|(|_|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#fun| |boom|(|_|#:| |(|B|[|nothing|]|)| ||| |(|undefined|)|)|#:| |anything|
-//│ ╔══[ERROR] not a recognized type: (MutArray)[string]
-//│ ║  l.5: 	fun buildName3(_: string, _: MutArray[string]): string
-//│ ╙──     	                             ^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[anything]
-//│ ║  l.6: 	fun buildName4(_: string, _: MutArray[anything]): string
-//│ ╙──     	                             ^^^^^^^^^^^^^^^^^^
+fun boom(_: (B<nothing>) | (undefined)): anything
+//│ |#fun| |buildName|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|_|#:| |string|,| |_|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|_|#:| |string|,| |_|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#fun| |did|(|_|#:| |number|,| |_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|_|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|↵|#fun| |testABC|(|_|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|_|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|_|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|_|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|(|_|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#fun| |boom|(|_|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
+//│ ╔══[ERROR] not a recognized type: MutArray‹string›
+//│ ║  l.5: 	fun buildName3(_: string, _: MutArray<string>): string
+//│ ╙──     	                             ^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: MutArray‹anything›
+//│ ║  l.6: 	fun buildName4(_: string, _: MutArray<anything>): string
+//│ ╙──     	                             ^^^^^^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
 //│ ╙──     	                                  ^
@@ -31,13 +31,13 @@ fun boom(_: (B[nothing]) | (undefined)): anything
 //│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
 //│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
 //│ ╙──     	                       ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[object]
-//│ ║  l.9: 	fun getOrElse(_: (MutArray[object]) | (undefined)): object
-//│ ╙──     	                  ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: MutArray‹object›
+//│ ║  l.9: 	fun getOrElse(_: (MutArray<object>) | (undefined)): object
+//│ ╙──     	                  ^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' number, string, ')'
 //│ ║  l.13: 	fun err(_: ((number, string, )) | (undefined)): unit
 //│ ╙──      	            ^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (B)[nothing]
-//│ ║  l.17: 	fun boom(_: (B[nothing]) | (undefined)): anything
-//│ ╙──      	             ^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: B‹nothing›
+//│ ║  l.17: 	fun boom(_: (B<nothing>) | (undefined)): anything
+//│ ╙──      	             ^^^^^^^^^
 //│ Parsed: {fun buildName: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName2: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName3: [] -> anything -> string; fun buildName4: [] -> anything -> string; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> anything -> number; fun getOrElse: [] -> anything -> object; class ABC() {}; fun testABC: [] -> (_: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (_: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> anything -> unit; fun toStr: [] -> (_: ((number,) | (bool,),) | (undefined,),) -> string; fun boo: [] -> (_: ((T,) & (U,),) | (undefined,),) -> unit; class B[T](b: T,) {}; fun boom: [] -> anything -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 2e2fa7eb8a..496a323d46 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -4,8 +4,8 @@
 class M(foo: ((_: number): string) & ((_: string): string))
  fun app((_: (_: string): unit, _: number): unit) & ((_: (_: string): unit, _: string): unit)
  fun create((_: number): (): bool) & ((_: bool): (): bool)
- fun g0((_: MutArray[string]): string) & ((_: MutArray[object]): string)
- fun db((_: number): MutArray[number]) & ((_: object): MutArray[number])
+ fun g0((_: MutArray<string>): string) & ((_: MutArray<object>): string)
+ fun db((_: number): MutArray<number>) & ((_: object): MutArray<number>)
 class N
  fun id((_: M): unit) & ((_: N): unit)
  fun tst((_: (z: number)): (y: string)) & ((_: (z: bool)): (y: string))
@@ -18,7 +18,7 @@ namespace XX {
 }
 class WWW(F: (_: T): anything /* warning: the overload of function F is not supported yet. */)
 fun baz(): anything /* warning: the overload of function baz is not supported yet. */
-//│ | |#fun| |f|(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|↵|#class| |M|(|foo|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|)|→|#fun| |app|(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |number|)|#:| |unit|)| |&| |(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |string|)|#:| |unit|)|↵|#fun| |create|(|(|_|#:| |number|)|#:| |(||)|#:| |bool|)| |&| |(|(|_|#:| |bool|)|#:| |(||)|#:| |bool|)|↵|#fun| |g0|(|(|_|#:| |MutArray|[|string|]|)|#:| |string|)| |&| |(|(|_|#:| |MutArray|[|object|]|)|#:| |string|)|↵|#fun| |db|(|(|_|#:| |number|)|#:| |MutArray|[|number|]|)| |&| |(|(|_|#:| |object|)|#:| |MutArray|[|number|]|)|←|↵|#class| |N|→|#fun| |id|(|(|_|#:| |M|)|#:| |unit|)| |&| |(|(|_|#:| |N|)|#:| |unit|)|↵|#fun| |tst|(|(|_|#:| |(|z|#:| |number|)|)|#:| |(|y|#:| |string|)|)| |&| |(|(|_|#:| |(|z|#:| |bool|)|)|#:| |(|y|#:| |string|)|)|↵|#fun| |op|(|(|_|#:| |number|,| |_|#:| |(|number|)| ||| |(|undefined|)|)|#:| |unit|)| |&| |(|(|_|#:| |number|,| |_|#:| |(|bool|)| ||| |(|undefined|)|)|#:| |unit|)|↵|#fun| |swap|(|(|_|#:| |(|number|,| |string|,| |)|)|#:| |(|number|,| |string|,| |)|)| |&| |(|(|_|#:| |(|string|,| |number|,| |)|)|#:| |(|number|,| |string|,| |)|)|↵|#fun| |u|(|(|_|#:| |(|number|)| ||| |(|bool|)|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|←|↵|#fun| |doSome|(|_|#:| |anything|)|#:| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|namespace| |XX| |{|→|#fun| |f|(|_|#:| |T|,| |_|#:| |anything|)|#:| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |(|_|#:| |T|)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#fun| |baz|(||)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+//│ | |#fun| |f|(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|↵|#class| |M|(|foo|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|)|→|#fun| |app|(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |number|)|#:| |unit|)| |&| |(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |string|)|#:| |unit|)|↵|#fun| |create|(|(|_|#:| |number|)|#:| |(||)|#:| |bool|)| |&| |(|(|_|#:| |bool|)|#:| |(||)|#:| |bool|)|↵|#fun| |g0|(|(|_|#:| |MutArray|‹|string|›|)|#:| |string|)| |&| |(|(|_|#:| |MutArray|‹|object|›|)|#:| |string|)|↵|#fun| |db|(|(|_|#:| |number|)|#:| |MutArray|‹|number|›|)| |&| |(|(|_|#:| |object|)|#:| |MutArray|‹|number|›|)|←|↵|#class| |N|→|#fun| |id|(|(|_|#:| |M|)|#:| |unit|)| |&| |(|(|_|#:| |N|)|#:| |unit|)|↵|#fun| |tst|(|(|_|#:| |(|z|#:| |number|)|)|#:| |(|y|#:| |string|)|)| |&| |(|(|_|#:| |(|z|#:| |bool|)|)|#:| |(|y|#:| |string|)|)|↵|#fun| |op|(|(|_|#:| |number|,| |_|#:| |(|number|)| ||| |(|undefined|)|)|#:| |unit|)| |&| |(|(|_|#:| |number|,| |_|#:| |(|bool|)| ||| |(|undefined|)|)|#:| |unit|)|↵|#fun| |swap|(|(|_|#:| |(|number|,| |string|,| |)|)|#:| |(|number|,| |string|,| |)|)| |&| |(|(|_|#:| |(|string|,| |number|,| |)|)|#:| |(|number|,| |string|,| |)|)|↵|#fun| |u|(|(|_|#:| |(|number|)| ||| |(|bool|)|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|←|↵|#fun| |doSome|(|_|#:| |anything|)|#:| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|namespace| |XX| |{|→|#fun| |f|(|_|#:| |T|,| |_|#:| |anything|)|#:| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |(|_|#:| |T|)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#fun| |baz|(||)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
 //│ ╙──     	                  ^
@@ -48,9 +48,9 @@ fun baz(): anything /* warning: the overload of function baz is not supported ye
 //│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.6: 	 fun create((_: number): (): bool) & ((_: bool): (): bool)
 //│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.7: 	 fun g0((_: MutArray[string]): string) & ((_: MutArray[object]): string)
+//│ ║  l.7: 	 fun g0((_: MutArray<string>): string) & ((_: MutArray<object>): string)
 //│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.8: 	 fun db((_: number): MutArray[number]) & ((_: object): MutArray[number])
+//│ ║  l.8: 	 fun db((_: number): MutArray<number>) & ((_: object): MutArray<number>)
 //│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.9: 	class N
 //│ ╙──     	^
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index 62728d7cd6..bf20df7ce2 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -4,16 +4,16 @@ fun inc(_: T): number
 class CC<T>(print: (_: T): unit)
 fun con(_: T): U
 class Printer<T>(print: (_: T): unit)
-fun setStringPrinter(_: Printer[string]): unit
-fun getStringPrinter(): Printer[string]
-fun foo(_: Printer[T], _: T): T
-fun foo2(_: Printer[T], _: T): T
+fun setStringPrinter(_: Printer<string>): unit
+fun getStringPrinter(): Printer<string>
+fun foo(_: Printer<T>, _: T): T
+fun foo2(_: Printer<T>, _: T): T
 class F<T>(x: T, GG: (_: U): T)
 trait I<T>(x: T, GG: (_: U): T)
 class FFF<T>(fff: (_: T): unit)
-fun fff(_: FFF[string], _: string): unit
-fun getFFF(): FFF[number]
-//│ |#fun| |inc|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |con|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |setStringPrinter|(|_|#:| |Printer|[|string|]|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|[|string|]|↵|#fun| |foo|(|_|#:| |Printer|[|T|]|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|(|_|#:| |Printer|[|T|]|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |fff|(|_|#:| |FFF|[|string|]|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|[|number|]|
+fun fff(_: FFF<string>, _: string): unit
+fun getFFF(): FFF<number>
+//│ |#fun| |inc|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |con|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |setStringPrinter|(|_|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |fff|(|_|#:| |FFF|‹|string|›|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.4: 	class CC<T>(print: (_: T): unit)
 //│ ╙──     	                         ^
@@ -26,18 +26,18 @@ fun getFFF(): FFF[number]
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
 //│ ║  l.6: 	class Printer<T>(print: (_: T): unit)
 //│ ╙──     	                        ^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (Printer)[string]
-//│ ║  l.7: 	fun setStringPrinter(_: Printer[string]): unit
-//│ ╙──     	                        ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (Printer)[string]
-//│ ║  l.8: 	fun getStringPrinter(): Printer[string]
-//│ ╙──     	                        ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (Printer)[T]
-//│ ║  l.9: 	fun foo(_: Printer[T], _: T): T
-//│ ╙──     	           ^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (Printer)[T]
-//│ ║  l.10: 	fun foo2(_: Printer[T], _: T): T
-//│ ╙──      	            ^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: Printer‹string›
+//│ ║  l.7: 	fun setStringPrinter(_: Printer<string>): unit
+//│ ╙──     	                        ^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: Printer‹string›
+//│ ║  l.8: 	fun getStringPrinter(): Printer<string>
+//│ ╙──     	                        ^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: Printer‹T›
+//│ ║  l.9: 	fun foo(_: Printer<T>, _: T): T
+//│ ╙──     	           ^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: Printer‹T›
+//│ ║  l.10: 	fun foo2(_: Printer<T>, _: T): T
+//│ ╙──      	            ^^^^^^^^^
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.11: 	class F<T>(x: T, GG: (_: U): T)
 //│ ╙──      	                           ^
@@ -56,10 +56,10 @@ fun getFFF(): FFF[number]
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
 //│ ║  l.13: 	class FFF<T>(fff: (_: T): unit)
 //│ ╙──      	                  ^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (FFF)[string]
-//│ ║  l.14: 	fun fff(_: FFF[string], _: string): unit
-//│ ╙──      	           ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (FFF)[number]
-//│ ║  l.15: 	fun getFFF(): FFF[number]
-//│ ╙──      	              ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: FFF‹string›
+//│ ║  l.14: 	fun fff(_: FFF<string>, _: string): unit
+//│ ╙──      	           ^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: FFF‹number›
+//│ ║  l.15: 	fun getFFF(): FFF<number>
+//│ ╙──      	              ^^^^^^^^^^
 //│ Parsed: {fun inc: [] -> (_: T,) -> number; class CC[T](print: '(' _: T, ')' (unit,),) {}; fun con: [] -> (_: T,) -> U; class Printer[T](print: '(' _: T, ')' (unit,),) {}; fun setStringPrinter: [] -> anything -> unit; fun getStringPrinter: [] -> () -> anything; fun foo: [] -> anything -> T; fun foo2: [] -> anything -> T; class F[T](x: T, GG: '(' _: U, ')' (T,),) {}; trait I[T](x: T, GG: '(' _: U, ')' (T,),): {}; class FFF[T](fff: '(' _: T, ')' (unit,),) {}; fun fff: [] -> anything -> unit; fun getFFF: [] -> () -> anything}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 63669018d5..1928269d6a 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -3,11 +3,11 @@
 fun getString(_: ((string) | (number)) | (bool)): string
 fun test(_: bool): (string) | (number)
 fun run(_: ((_: number): number) | ((_: number): string)): anything
-fun get(_: (MutArray[number]) | (MutArray[string])): unit
+fun get(_: (MutArray<number>) | (MutArray<string>)): unit
 fun get2(_: ((string, string, )) | ((number, string, ))): string
 fun typeVar(_: (T) | (U)): (T) | (U)
 fun uuuu(_: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
-//│ |#fun| |getString|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|_|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|(|_|#:| |number|)|#:| |string|)|)|#:| |anything|↵|#fun| |get|(|_|#:| |(|MutArray|[|number|]|)| ||| |(|MutArray|[|string|]|)|)|#:| |unit|↵|#fun| |get2|(|_|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|(|_|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
+//│ |#fun| |getString|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|_|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|(|_|#:| |number|)|#:| |string|)|)|#:| |anything|↵|#fun| |get|(|_|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|_|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|(|_|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
 //│ ╙──     	                       ^
@@ -23,9 +23,9 @@ fun uuuu(_: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
 //│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
 //│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
 //│ ╙──     	            ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: (MutArray)[number]
-//│ ║  l.6: 	fun get(_: (MutArray[number]) | (MutArray[string])): unit
-//│ ╙──     	            ^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: MutArray‹number›
+//│ ║  l.6: 	fun get(_: (MutArray<number>) | (MutArray<string>)): unit
+//│ ╙──     	            ^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' string, string, ')'
 //│ ║  l.7: 	fun get2(_: ((string, string, )) | ((number, string, ))): string
 //│ ╙──     	             ^^^^^^^^^^^^^^^^^^

From 5acdc5c7eb9cf81284663d8bddd6c2f6c6a02ddb Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 09:48:12 +0800
Subject: [PATCH 03/40] Fix function convert

---
 .../src/main/scala/ts2mls/TSNamespace.scala   |   6 +-
 .../main/scala/ts2mls/types/Converter.scala   |   8 +-
 ts2mls/js/src/test/diff/Array.d.mls           |  58 +++-------
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  |  40 +++----
 ts2mls/js/src/test/diff/ClassMember.d.mls     |  54 ++--------
 ts2mls/js/src/test/diff/Enum.d.mls            |  10 +-
 ts2mls/js/src/test/diff/Heritage.d.mls        |  50 ++-------
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   |  52 +--------
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 100 +++---------------
 ts2mls/js/src/test/diff/Intersection.d.mls    |  51 +++------
 ts2mls/js/src/test/diff/MultiFiles.d.mls      |  32 +++---
 ts2mls/js/src/test/diff/Namespace.d.mls       |  44 ++++----
 ts2mls/js/src/test/diff/Optional.d.mls        |  57 +++++-----
 ts2mls/js/src/test/diff/Overload.d.mls        | 100 +++++++++---------
 ts2mls/js/src/test/diff/Tuple.d.mls           |  96 +++++------------
 ts2mls/js/src/test/diff/TypeParameter.d.mls   |  84 +++++----------
 ts2mls/js/src/test/diff/Union.d.mls           |  41 +++----
 17 files changed, 271 insertions(+), 612 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index ccd6315367..ca6735a931 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -46,9 +46,9 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
         // val fullName = getFullPath(name)
         mem match {
           case inter: TSIntersectionType => // overloaded functions
-            writer.writeln(s"${indent} fun ${name}${Converter.convert(inter)}")
+            writer.writeln(s"${indent}let ${name}: ${Converter.convert(inter)}")
           case f: TSFunctionType =>
-            writer.writeln(s"${indent}fun ${name}${Converter.convert(f)}")
+            writer.writeln(s"${indent}let ${name}: ${Converter.convert(f)}")
           // {
           //   val typeParams = f.typeVars.map((t) => t.name)
           //   if (typeParams.isEmpty)
@@ -57,7 +57,7 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
           //     writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(f)}")
           // }
           case overload @ TSIgnoredOverload(base, _) =>
-            writer.writeln(s"${indent}fun ${name}${Converter.convert(overload)}")
+            writer.writeln(s"${indent}let ${name}: ${Converter.convert(overload)}")
           // {
           //   val typeParams = base.typeVars.map((t) => t.name)
           //     if (typeParams.isEmpty)
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 18c12fa24b..4721ac9405 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -23,11 +23,9 @@ object Converter {
     case TSReferenceType(name) => name
     case TSFunctionType(params, res, _) =>
       // since functions can be defined by both `def` and `method`, it only returns the type of functions
-      if (params.length == 0) s"(): ${convert(res)}"
-      else {
-        val list = params.map((p) => s"_: ${convert(p)}").reduceLeft((r, p) => s"$r, $p")
-        s"($list): ${convert(res)}"
-      }
+      if (params.length == 0) s"${primitiveName("void")} => ${convert(res)}"
+      else
+        params.foldRight(convert(res))((p, f) => s"${convert(p)} => $f")
     case TSUnionType(lhs, rhs) => {
       val lres = convert(lhs)
       val rres = convert(rhs)
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index b6a927e4ae..377b900dd4 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,53 +1,23 @@
 :NewParser
 :ParseOnly
-fun first(_: MutArray<string>): string
-fun getZero3(): MutArray<number>
-fun first2(_: MutArray<(_: number): number>): (_: number): number
-fun doEs(_: MutArray<int>): MutArray<int>
+let first: MutArray<string> => string
+let getZero3: unit => MutArray<number>
+let first2: MutArray<number => number> => number => number
+let doEs: MutArray<int> => MutArray<int>
 class C
 trait I(i: number)
-fun doCs(_: MutArray<C>): MutArray<C>
-fun doIs(_: MutArray<I>): MutArray<I>
-fun inter(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
-fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
-fun translate(_: MutArray<T>): MutArray<U>
-fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
+let doCs: MutArray<C> => MutArray<C>
+let doIs: MutArray<I> => MutArray<I>
+let inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
+let clean: MutArray<(string, number, )> => MutArray<(string, number, )>
+let translate: MutArray<T> => MutArray<U>
+let uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
 class Temp<T>(x: T)
-fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
-fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.11: 	fun inter(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
-//│ ║        	                                ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.11: 	fun inter(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
-//│ ╙──      	                     ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.12: 	fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
-//│ ║        	                                         ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.12: 	fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
-//│ ╙──      	                     ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.14: 	fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
-//│ ║        	                                     ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.14: 	fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
-//│ ╙──      	                  ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.16: 	fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
-//│ ║        	                              ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.16: 	fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
-//│ ╙──      	                       ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.17: 	fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
-//│ ║        	                            ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.17: 	fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
-//│ ╙──      	                        ^
+let ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
+let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
 //│ ╔══[PARSE ERROR] Unmatched opening angle bracket
-//│ ║  l.17: 	fun tat(_: MutArray<Temp<T>>): MutArray<Temp<T>>
-//│ ║        	                                            ^
+//│ ║  l.17: 	let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
+//│ ║        	                                           ^
 //│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator
 //│ |T|>>|Temp|
 //│ Parsed: {>> (T,) (Temp,)}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 6b344655a3..c992b4a057 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
-fun hello(): unit
-fun add(_: number, _: number): number
-fun sub(_: number, _: number): number
-fun foo(): number
-fun id(_: anything): anything
-fun odd(_: number): bool
-fun isnull(_: anything): bool
-fun bar(): anything
-fun nu(_: null): null
-fun un(_: undefined): undefined
-fun fail(): nothing
-fun create(): object
-fun pa(_: number): number
-fun wtf(_: anything): unit
+let hello: unit => unit
+let add: number => number => number
+let sub: number => number => number
+let foo: unit => number
+let id: anything => anything
+let odd: number => bool
+let isnull: anything => bool
+let bar: unit => anything
+let nu: null => null
+let un: undefined => undefined
+let fail: unit => nothing
+let create: unit => object
+let pa: number => number
+let wtf: anything => unit
 class Foooooo(ooooooo: number)
-fun inn(_: Foooooo): unit
-fun out(): Foooooo
+let inn: Foooooo => unit
+let out: unit => Foooooo
 trait Barrrrrrrrr(rrrrrrr: number)
-fun inn2(_: Barrrrrrrrr): unit
-fun out2(): Barrrrrrrrr
-//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |sub|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|_|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|_|#:| |number|)|#:| |bool|↵|#fun| |isnull|(|_|#:| |anything|)|#:| |bool|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|_|#:| |null|)|#:| |null|↵|#fun| |un|(|_|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|_|#:| |number|)|#:| |number|↵|#fun| |wtf|(|_|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#fun| |inn|(|_|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#fun| |inn2|(|_|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (_: number, _: number,) -> number; fun sub: [] -> (_: number, _: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (_: anything,) -> anything; fun odd: [] -> (_: number,) -> bool; fun isnull: [] -> (_: anything,) -> bool; fun bar: [] -> () -> anything; fun nu: [] -> (_: null,) -> null; fun un: [] -> (_: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (_: number,) -> number; fun wtf: [] -> (_: anything,) -> unit; class Foooooo(ooooooo: number,) {}; fun inn: [] -> (_: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> (_: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
+let inn2: Barrrrrrrrr => unit
+let out2: unit => Barrrrrrrrr
+//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |number| |=>| |number| |=>| |number|↵|#let| |sub|#:| |number| |=>| |number| |=>| |number|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |anything| |=>| |anything|↵|#let| |odd|#:| |number| |=>| |bool|↵|#let| |isnull|#:| |anything| |=>| |bool|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |null| |=>| |null|↵|#let| |un|#:| |undefined| |=>| |undefined|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |number| |=>| |number|↵|#let| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#let| |inn|#:| |Foooooo| |=>| |unit|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#let| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo(ooooooo: number,) {}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index a99ebbe7ce..61149ba4a7 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,51 +1,9 @@
 :NewParser
 :ParseOnly
-class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
-class Foo<T>(bar: (_: T): unit)
-class EZ(inc: (_: number): number)
+class Student(name: string, isFriend: Student => bool, addScore: string => number => unit, getID: unit => number)
+class Foo<T>(bar: T => unit)
+class EZ(inc: number => number)
 class Outer
-class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
-//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |(|_|#:| |Student|)|#:| |bool|,| |addScore|#:| |(|_|#:| |string|,| |_|#:| |number|)|#:| |unit|,| |getID|#:| |(||)|#:| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#class| |EZ|(|inc|#:| |(|_|#:| |number|)|#:| |number|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |(|_|#:| |T|)|#:| |T|,| |ttt2|#:| |(|_|#:| |T|)|#:| |T|)|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
-//│ ╙──     	                                                  ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
-//│ ╙──     	                                                                                          ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
-//│ ╙──     	                                                                                                           ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
-//│ ╙──     	                                                                                                         ^^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
-//│ ╙──     	                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	class Student(name: string, isFriend: (_: Student): bool, addScore: (_: string, _: number): unit, getID: (): number)
-//│ ╙──     	                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.4: 	class Foo<T>(bar: (_: T): unit)
-//│ ╙──     	                        ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.4: 	class Foo<T>(bar: (_: T): unit)
-//│ ╙──     	                  ^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	class EZ(inc: (_: number): number)
-//│ ╙──     	                         ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	class EZ(inc: (_: number): number)
-//│ ╙──     	              ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
-//│ ╙──     	                        ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
-//│ ╙──     	                                         ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
-//│ ╙──     	                                   ^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.7: 	class TTT<T>(ttt: (_: T): T, ttt2: (_: T): T)
-//│ ╙──     	                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ Parsed: {class Student(name: string, isFriend: '(' _: Student, ')' (bool, addScore: '(' _: string, _: number, ')' (unit, getID: '('  ')' (number,),),),) {}; class Foo[T](bar: '(' _: T, ')' (unit,),) {}; class EZ(inc: '(' _: number, ')' (number,),) {}; class Outer() {}; class TTT[T](ttt: '(' _: T, ')' (T, ttt2: '(' _: T, ')' (T,),),) {}}
+class TTT<T>(ttt: T => T, ttt2: T => T)
+//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |Student| |=>| |bool|,| |addScore|#:| |string| |=>| |number| |=>| |unit|,| |getID|#:| |unit| |=>| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |T| |=>| |unit|)|↵|#class| |EZ|(|inc|#:| |number| |=>| |number|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|,| |ttt2|#:| |T| |=>| |T|)|
+//│ Parsed: {class Student(name: string, isFriend: Student, => bool, addScore: string, => number, => unit, getID: unit, => number,) {}; class Foo[T](bar: T, => unit,) {}; class EZ(inc: number, => number,) {}; class Outer() {}; class TTT[T](ttt: T, => T, ttt2: T, => T,) {}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index 57dcd7a5d2..a9ce8f67b9 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun pass(_: int): bool
-fun stop(): int
-fun g(_: int): int
-//│ |#fun| |pass|(|_|#:| |int|)|#:| |bool|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|_|#:| |int|)|#:| |int|
-//│ Parsed: {fun pass: [] -> (_: int,) -> bool; fun stop: [] -> () -> int; fun g: [] -> (_: int,) -> int}
+let pass: int => bool
+let stop: unit => int
+let g: int => int
+//│ |#let| |pass|#:| |int| |=>| |bool|↵|#let| |stop|#:| |unit| |=>| |int|↵|#let| |g|#:| |int| |=>| |int|
+//│ Parsed: {fun pass: [] -> int -> bool; fun stop: [] -> unit -> int; fun g: [] -> int -> int}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index ab2611083c..8371bc2bf4 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -1,59 +1,23 @@
 :NewParser
 :ParseOnly
-class A(foo: (): unit)
+class A(foo: unit => unit)
 class B: A
-class C<T>(set: (_: T): unit, get: (): T)
+class C<T>(set: T => unit, get: unit => T)
 class D: C<number>
 trait Wu(x: bool)
 class WuWu(y: bool): Wu
 trait WuWuWu(z: bool): WuWu
-trait Never(w: (): nothing): WuWuWu
+trait Never(w: unit => nothing): WuWuWu
 class VG<T>(x: T)
 class Home<T>(y: T): VG<string>
-trait O<I>(xx: (_: I): I)
-class OR<R>(xx: (_: R): R): O<R>
+trait O<I>(xx: I => I)
+class OR<R>(xx: R => R): O<R>
 namespace Five {
   class Five'ROTK(wu: string)
   class Five'Y: Five'ROTK
 }
 class Y: Five'ROTK
-//│ |#class| |A|(|foo|#:| |(||)|#:| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |(|_|#:| |T|)|#:| |unit|,| |get|#:| |(||)|#:| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |(||)|#:| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |(|_|#:| |I|)|#:| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |(|_|#:| |R|)|#:| |R|)|#:| |O|‹|R|›|↵|namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	class A(foo: (): unit)
-//│ ╙──     	               ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	class A(foo: (): unit)
-//│ ╙──     	             ^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
-//│ ╙──     	                      ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
-//│ ╙──     	                                     ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
-//│ ╙──     	                                   ^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	class C<T>(set: (_: T): unit, get: (): T)
-//│ ╙──     	                ^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.10: 	trait Never(w: (): nothing): WuWuWu
-//│ ╙──      	                 ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.10: 	trait Never(w: (): nothing): WuWuWu
-//│ ╙──      	               ^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.13: 	trait O<I>(xx: (_: I): I)
-//│ ╙──      	                     ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.13: 	trait O<I>(xx: (_: I): I)
-//│ ╙──      	               ^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O<R>
-//│ ╙──      	                      ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.14: 	class OR<R>(xx: (_: R): R): O<R>
-//│ ╙──      	                ^^^^^^^^^
+//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
 //│ ║  l.15: 	namespace Five {
 //│ ╙──      	^^^^^^^^^^^^^^
@@ -66,4 +30,4 @@ class Y: Five'ROTK
 //│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.18: 	}
 //│ ╙──      	^
-//│ Parsed: {class A(foo: '('  ')' (unit,),) {}; class B(): A {}; class C[T](set: '(' _: T, ')' (unit, get: '('  ')' (T,),),) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: '('  ')' (nothing,),): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: '(' _: I, ')' (I,),): {}; class OR[R](xx: '(' _: R, ')' (R,),): O‹R› {}; namespace (Five,)}
+//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace (Five,)}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index 4c8b023931..083fbcb028 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,49 +1,7 @@
 :NewParser
 :ParseOnly
-fun h1(_: (_: number): number, _: number): number
-fun h2(_: string): (): string
-fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ |#fun| |h1|(|_|#:| |(|_|#:| |number|)|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |h2|(|_|#:| |string|)|#:| |(||)|#:| |string|↵|#fun| |h3|(|_|#:| |(|_|#:| |number|)|#:| |number|,| |_|#:| |(|_|#:| |number|)|#:| |number|)|#:| |(|_|#:| |number|)|#:| |number|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	fun h1(_: (_: number): number, _: number): number
-//│ ╙──     	                     ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	fun h1(_: (_: number): number, _: number): number
-//│ ╙──     	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
-//│ ║  l.3: 	fun h1(_: (_: number): number, _: number): number
-//│ ╙──     	          ^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.4: 	fun h2(_: string): (): string
-//│ ╙──     	                     ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.4: 	fun h2(_: string): (): string
-//│ ╙──     	                   ^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '('  ')'
-//│ ║  l.4: 	fun h2(_: string): (): string
-//│ ╙──     	                   ^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	                     ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	                                             ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	                                  ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	                                                                   ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	                                                        ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	                                                        ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
-//│ ║  l.5: 	fun h3(_: (_: number): number, _: (_: number): number): (_: number): number
-//│ ╙──     	          ^^^^^^^^^^^
-//│ Parsed: {fun h1: [] -> anything -> number; fun h2: [] -> (_: string,) -> anything; fun h3: [] -> anything -> anything}
+let h1: number => number => number => number
+let h2: string => unit => string
+let h3: number => number => number => number => number => number
+//│ |#let| |h1|#:| |number| |=>| |number| |=>| |number| |=>| |number|↵|#let| |h2|#:| |string| |=>| |unit| |=>| |string|↵|#let| |h3|#:| |number| |=>| |number| |=>| |number| |=>| |number| |=>| |number| |=>| |number|
+//│ Parsed: {fun h1: [] -> number -> number -> number -> number; fun h2: [] -> string -> unit -> string; fun h3: [] -> number -> number -> number -> number -> number -> number}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 88f84360be..2d30271797 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -1,91 +1,19 @@
 :NewParser
 :ParseOnly
-trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
-trait II<T>(test: (_: T): number)
-fun create(): (v: number)
-fun get(_: (t: string)): string
-trait IEvent(callback: (_: unit): (_: number): unit)
-trait SearchFunc(__call: (_: string, _: string): bool)
-trait StringArray(__index: (_: number): string)
-trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
-trait Simple(a: number, b: (_: bool): string)
+trait IFoo(a: string, b: number => number, c: unit => bool, d: string => unit)
+trait II<T>(test: T => number)
+let create: unit => (v: number)
+let get: (t: string) => string
+trait IEvent(callback: unit => number => unit)
+trait SearchFunc(__call: string => string => bool)
+trait StringArray(__index: number => string)
+trait Counter(__call: number => string, interval: number, reset: unit => unit)
+trait Simple(a: number, b: bool => string)
 trait Simple2<T>(abc: T)
 trait Next: Simple
-trait TTT<T>(ttt: (_: T): T)
-//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |(|_|#:| |number|)|#:| |number|,| |c|#:| |(||)|#:| |bool|,| |d|#:| |(|_|#:| |string|)|#:| |unit|)|↵|#trait| |II|‹|T|›|(|test|#:| |(|_|#:| |T|)|#:| |number|)|↵|#fun| |create|(||)|#:| |(|v|#:| |number|)|↵|#fun| |get|(|_|#:| |(|t|#:| |string|)|)|#:| |string|↵|#trait| |IEvent|(|callback|#:| |(|_|#:| |unit|)|#:| |(|_|#:| |number|)|#:| |unit|)|↵|#trait| |SearchFunc|(|__call|#:| |(|_|#:| |string|,| |_|#:| |string|)|#:| |bool|)|↵|#trait| |StringArray|(|__index|#:| |(|_|#:| |number|)|#:| |string|)|↵|#trait| |Counter|(|__call|#:| |(|_|#:| |number|)|#:| |string|,| |interval|#:| |number|,| |reset|#:| |(||)|#:| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |(|_|#:| |bool|)|#:| |string|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |(|_|#:| |T|)|#:| |T|)|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
-//│ ╙──     	                                    ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
-//│ ╙──     	                                                   ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
-//│ ╙──     	                                                                         ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
-//│ ╙──     	                                                              ^^^^^^^^^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
-//│ ╙──     	                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	trait IFoo(a: string, b: (_: number): number, c: (): bool, d: (_: string): unit)
-//│ ╙──     	                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.4: 	trait II<T>(test: (_: T): number)
-//│ ╙──     	                        ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.4: 	trait II<T>(test: (_: T): number)
-//│ ╙──     	                  ^^^^^^^^^^^^^^
+trait TTT<T>(ttt: T => T)
+//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |number| |=>| |number|,| |c|#:| |unit| |=>| |bool|,| |d|#:| |string| |=>| |unit|)|↵|#trait| |II|‹|T|›|(|test|#:| |T| |=>| |number|)|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|)|↵|#let| |get|#:| |(|t|#:| |string|)| |=>| |string|↵|#trait| |IEvent|(|callback|#:| |unit| |=>| |number| |=>| |unit|)|↵|#trait| |SearchFunc|(|__call|#:| |string| |=>| |string| |=>| |bool|)|↵|#trait| |StringArray|(|__index|#:| |number| |=>| |string|)|↵|#trait| |Counter|(|__call|#:| |number| |=>| |string|,| |interval|#:| |number|,| |reset|#:| |unit| |=>| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |bool| |=>| |string|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|)|
 //│ ╔══[ERROR] not a recognized type: '(' v: number, ')'
-//│ ║  l.5: 	fun create(): (v: number)
-//│ ╙──     	              ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' t: string, ')'
-//│ ║  l.6: 	fun get(_: (t: string)): string
-//│ ╙──     	           ^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.7: 	trait IEvent(callback: (_: unit): (_: number): unit)
-//│ ╙──     	                                ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.7: 	trait IEvent(callback: (_: unit): (_: number): unit)
-//│ ╙──     	                                             ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.7: 	trait IEvent(callback: (_: unit): (_: number): unit)
-//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.8: 	trait SearchFunc(__call: (_: string, _: string): bool)
-//│ ╙──     	                                               ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.8: 	trait SearchFunc(__call: (_: string, _: string): bool)
-//│ ╙──     	                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.9: 	trait StringArray(__index: (_: number): string)
-//│ ╙──     	                                      ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.9: 	trait StringArray(__index: (_: number): string)
-//│ ╙──     	                           ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
-//│ ╙──      	                                 ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
-//│ ╙──      	                                                                      ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
-//│ ╙──      	                                                                    ^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.10: 	trait Counter(__call: (_: number): string, interval: number, reset: (): unit)
-//│ ╙──      	                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.11: 	trait Simple(a: number, b: (_: bool): string)
-//│ ╙──      	                                    ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.11: 	trait Simple(a: number, b: (_: bool): string)
-//│ ╙──      	                           ^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.14: 	trait TTT<T>(ttt: (_: T): T)
-//│ ╙──      	                        ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.14: 	trait TTT<T>(ttt: (_: T): T)
-//│ ╙──      	                  ^^^^^^^^^
-//│ Parsed: {trait IFoo(a: string, b: '(' _: number, ')' (number, c: '('  ')' (bool, d: '(' _: string, ')' (unit,),),),): {}; trait II[T](test: '(' _: T, ')' (number,),): {}; fun create: [] -> () -> anything; fun get: [] -> anything -> string; trait IEvent(callback: '(' _: unit, ')' ('(' _: number, ')' (unit,),),): {}; trait SearchFunc(__call: '(' _: string, _: string, ')' (bool,),): {}; trait StringArray(__index: '(' _: number, ')' (string,),): {}; trait Counter(__call: '(' _: number, ')' (string, interval: number, reset: '('  ')' (unit,),),): {}; trait Simple(a: number, b: '(' _: bool, ')' (string,),): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: '(' _: T, ')' (T,),): {}}
+//│ ║  l.5: 	let create: unit => (v: number)
+//│ ╙──     	                    ^^^^^^^^^^^
+//│ Parsed: {trait IFoo(a: string, b: number, => number, c: unit, => bool, d: string, => unit,): {}; trait II[T](test: T, => number,): {}; fun create: [] -> anything; fun get: [] -> (t: string,) -> string; trait IEvent(callback: unit, => number, => unit,): {}; trait SearchFunc(__call: string, => string, => bool,): {}; trait StringArray(__index: number, => string,): {}; trait Counter(__call: number, => string, interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => string,): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => T,): {}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 3dad334035..375c06c5ca 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,44 +1,23 @@
 :NewParser
 :ParseOnly
-fun extend(_: T, _: U): (T) & (U)
-fun foo(_: (T) & (U)): unit
-fun over(_: ((_: number): string) & ((_: object): string)): string
+let extend: T => U => (T) & (U)
+let foo: (T) & (U) => unit
+let over: (number => string) & (object => string) => string
 trait IA(x: number)
 trait IB(y: number)
-fun iii(_: (IA) & (IB)): (IA) & (IB)
-fun uu(_: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
-fun iiii(_: ((U) & (T)) & (V)): ((U) & (T)) & (V)
-fun arr(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
-fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
+let iii: (IA) & (IB) => (IA) & (IB)
+let uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
+let iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
+let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
+let tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
 class A
 class B
-fun inter(_: (A) & (B)): (A) & (B)
-//│ |#fun| |extend|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|(|_|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|_|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|)|#:| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#fun| |iii|(|_|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|(|_|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|(|_|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|(|_|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|(|_|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#fun| |inter|(|_|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
-//│ ╙──     	                        ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
-//│ ╙──     	             ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
-//│ ╙──     	                                                ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
-//│ ╙──     	                                     ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
-//│ ║  l.5: 	fun over(_: ((_: number): string) & ((_: object): string)): string
-//│ ╙──     	             ^^^^^^^^^^^
+let inter: (A) & (B) => (A) & (B)
+//│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
 //│ ╔══[ERROR] not a recognized type: MutArray‹U›
-//│ ║  l.11: 	fun arr(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
-//│ ╙──      	                                            ^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: MutArray‹U›
-//│ ║  l.11: 	fun arr(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
-//│ ╙──      	            ^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' U, T, ')'
-//│ ║  l.12: 	fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
-//│ ╙──      	                                     ^^^^^^^^
+//│ ║  l.11: 	let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
+//│ ╙──      	          ^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' U, T, ')'
-//│ ║  l.12: 	fun tt(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
-//│ ╙──      	           ^^^^^^^^
-//│ Parsed: {fun extend: [] -> (_: T, _: U,) -> ((T,) & (U,)); fun foo: [] -> (_: (T,) & (U,),) -> unit; fun over: [] -> anything -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> (_: (IA,) & (IB,),) -> ((IA,) & (IB,)); fun uu: [] -> (_: ((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (_: ((U,) & (T,),) & (V,),) -> (((U,) & (T,),) & (V,)); fun arr: [] -> anything -> anything; fun tt: [] -> anything -> anything; class A() {}; class B() {}; fun inter: [] -> (_: (A,) & (B,),) -> ((A,) & (B,))}
+//│ ║  l.12: 	let tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
+//│ ╙──      	         ^^^^^^^^
+//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> anything; fun tt: [] -> anything; class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index 5d4c46fc1f..c4f77b3ee1 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,32 +1,32 @@
 :NewParser
 :ParseOnly
-fun multi1(_: number): number
-fun multi3(): unit
+let multi1: number => number
+let multi3: unit => unit
 class Foo: Base
 trait AnotherBase(y: string)
 namespace N {
-  fun f(): unit
-  fun g(): unit
-  fun h(): unit
+  let f: unit => unit
+  let g: unit => unit
+  let h: unit => unit
 }
-fun multi2(_: string): string
-fun multi4(): unit
+let multi2: string => string
+let multi4: unit => unit
 trait Base(a: number)
 class AnotherFoo: AnotherBase
-fun multi5(): unit
-//│ |#fun| |multi1|(|_|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|namespace| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|_|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#fun| |multi5|(||)|#:| |unit|
+let multi5: unit => unit
+//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
 //│ ║  l.7: 	namespace N {
 //│ ╙──     	^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
 //│ ║  l.7: 	namespace N {
 //│ ║       	            ^
-//│ ║  l.8: 	  fun f(): unit
-//│ ║       	^^^^^^^^^^^^^^^
-//│ ║  l.9: 	  fun g(): unit
-//│ ║       	^^^^^^^^^^^^^^^
-//│ ║  l.10: 	  fun h(): unit
-//│ ║        	^^^^^^^^^^^^^^^
+//│ ║  l.8: 	  let f: unit => unit
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.9: 	  let g: unit => unit
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.10: 	  let h: unit => unit
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.11: 	}
 //│ ╙──      	^
-//│ Parsed: {fun multi1: [] -> (_: number,) -> number; fun multi3: [] -> () -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace (N,)}
+//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace (N,)}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 103c887ab0..32624189e2 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,46 +1,46 @@
 :NewParser
 :ParseOnly
 namespace N1 {
-  fun f(_: anything): number
-  fun ff(_: anything): number
-  class N1'C(f: (): unit)
-  trait N1'I(f: (): number)
+  let f: anything => number
+  let ff: anything => number
+  class N1'C(f: unit => unit)
+  trait N1'I(f: unit => number)
   namespace N2 {
-    fun fff(_: bool): number
-    fun gg(_: N1'C): N1'C
+    let fff: bool => number
+    let gg: N1'C => N1'C
     class N1'N2'BBB: N1'C
   }
 }
 namespace AA {
-  fun f(_: anything): string
-  class AA'C(f: (): unit)
-  trait AA'I(f: (): number)
+  let f: anything => string
+  class AA'C(f: unit => unit)
+  trait AA'I(f: unit => number)
   namespace N2 {
   }
 }
-fun f1(_: N1'C): N1'C
-fun f2(_: AA'C): AA'C
-//│ |namespace| |N1| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |number|↵|#fun| |ff|(|_|#:| |anything|)|#:| |number|↵|#class| |N1'C|(|f|#:| |(||)|#:| |unit|)|↵|#trait| |N1'I|(|f|#:| |(||)|#:| |number|)|↵|namespace| |N2| |{|→|#fun| |fff|(|_|#:| |bool|)|#:| |number|↵|#fun| |gg|(|_|#:| |N1'C|)|#:| |N1'C|↵|#class| |N1'N2'BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|namespace| |AA| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |string|↵|#class| |AA'C|(|f|#:| |(||)|#:| |unit|)|↵|#trait| |AA'I|(|f|#:| |(||)|#:| |number|)|↵|namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|_|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|_|#:| |AA'C|)|#:| |AA'C|
+let f1: N1'C => N1'C
+let f2: AA'C => AA'C
+//│ |namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |N1'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |N1'I|(|f|#:| |unit| |=>| |number|)|↵|namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |N1'N2'BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |AA'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |AA'I|(|f|#:| |unit| |=>| |number|)|↵|namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
 //│ ║  l.3: 	namespace N1 {
 //│ ╙──     	^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
 //│ ║  l.3: 	namespace N1 {
 //│ ║       	             ^
-//│ ║  l.4: 	  fun f(_: anything): number
+//│ ║  l.4: 	  let f: anything => number
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.5: 	  let ff: anything => number
 //│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.5: 	  fun ff(_: anything): number
+//│ ║  l.6: 	  class N1'C(f: unit => unit)
 //│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.6: 	  class N1'C(f: (): unit)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.7: 	  trait N1'I(f: (): number)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.7: 	  trait N1'I(f: unit => number)
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.8: 	  namespace N2 {
 //│ ║       	^^^^^^^^^^^^^^^^
-//│ ║  l.9: 	    fun fff(_: bool): number
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.10: 	    fun gg(_: N1'C): N1'C
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.9: 	    let fff: bool => number
+//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.10: 	    let gg: N1'C => N1'C
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.11: 	    class N1'N2'BBB: N1'C
 //│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.12: 	  }
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 5ce9540a68..666e9bebf7 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,43 +1,34 @@
 :NewParser
 :ParseOnly
-fun buildName(_: string, _: (string) | (undefined)): string
-fun buildName2(_: string, _: (string) | (undefined)): string
-fun buildName3(_: string, _: MutArray<string>): string
-fun buildName4(_: string, _: MutArray<anything>): string
+let buildName: string => (string) | (undefined) => string
+let buildName2: string => (string) | (undefined) => string
+let buildName3: string => MutArray<string> => string
+let buildName4: string => MutArray<anything> => string
 trait SquareConfig(color: (string) | (undefined), width: (number) | (undefined))
-fun did(_: number, _: ((_: number): number) | (undefined)): number
-fun getOrElse(_: (MutArray<object>) | (undefined)): object
+let did: number => (number => number) | (undefined) => number
+let getOrElse: (MutArray<object>) | (undefined) => object
 class ABC
-fun testABC(_: (ABC) | (undefined)): unit
-fun testSquareConfig(_: (SquareConfig) | (undefined)): unit
-fun err(_: ((number, string, )) | (undefined)): unit
-fun toStr(_: ((number) | (bool)) | (undefined)): string
-fun boo(_: ((T) & (U)) | (undefined)): unit
+let testABC: (ABC) | (undefined) => unit
+let testSquareConfig: (SquareConfig) | (undefined) => unit
+let err: ((number, string, )) | (undefined) => unit
+let toStr: ((number) | (bool)) | (undefined) => string
+let boo: ((T) & (U)) | (undefined) => unit
 class B<T>(b: T)
-fun boom(_: (B<nothing>) | (undefined)): anything
-//│ |#fun| |buildName|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|_|#:| |string|,| |_|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|_|#:| |string|,| |_|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#fun| |did|(|_|#:| |number|,| |_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|_|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|↵|#fun| |testABC|(|_|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|_|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|_|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|_|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|(|_|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#fun| |boom|(|_|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
+let boom: (B<nothing>) | (undefined) => anything
+//│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
 //│ ╔══[ERROR] not a recognized type: MutArray‹string›
-//│ ║  l.5: 	fun buildName3(_: string, _: MutArray<string>): string
-//│ ╙──     	                             ^^^^^^^^^^^^^^^
+//│ ║  l.5: 	let buildName3: string => MutArray<string> => string
+//│ ╙──     	                          ^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: MutArray‹anything›
-//│ ║  l.6: 	fun buildName4(_: string, _: MutArray<anything>): string
-//│ ╙──     	                             ^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
-//│ ╙──     	                                  ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
-//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
-//│ ║  l.8: 	fun did(_: number, _: ((_: number): number) | (undefined)): number
-//│ ╙──     	                       ^^^^^^^^^^^
+//│ ║  l.6: 	let buildName4: string => MutArray<anything> => string
+//│ ╙──     	                          ^^^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: MutArray‹object›
-//│ ║  l.9: 	fun getOrElse(_: (MutArray<object>) | (undefined)): object
-//│ ╙──     	                  ^^^^^^^^^^^^^^^
+//│ ║  l.9: 	let getOrElse: (MutArray<object>) | (undefined) => object
+//│ ╙──     	                ^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' number, string, ')'
-//│ ║  l.13: 	fun err(_: ((number, string, )) | (undefined)): unit
-//│ ╙──      	            ^^^^^^^^^^^^^^^^^^
+//│ ║  l.13: 	let err: ((number, string, )) | (undefined) => unit
+//│ ╙──      	          ^^^^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: B‹nothing›
-//│ ║  l.17: 	fun boom(_: (B<nothing>) | (undefined)): anything
-//│ ╙──      	             ^^^^^^^^^
-//│ Parsed: {fun buildName: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName2: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName3: [] -> anything -> string; fun buildName4: [] -> anything -> string; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> anything -> number; fun getOrElse: [] -> anything -> object; class ABC() {}; fun testABC: [] -> (_: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (_: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> anything -> unit; fun toStr: [] -> (_: ((number,) | (bool,),) | (undefined,),) -> string; fun boo: [] -> (_: ((T,) & (U,),) | (undefined,),) -> unit; class B[T](b: T,) {}; fun boom: [] -> anything -> anything}
+//│ ║  l.17: 	let boom: (B<nothing>) | (undefined) => anything
+//│ ╙──      	           ^^^^^^^^^
+//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> anything; fun buildName4: [] -> anything; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> anything; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> anything; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 496a323d46..cdce4a0dfa 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,57 +1,57 @@
 :NewParser
 :ParseOnly
- fun f((_: number): string) & ((_: string): string)
-class M(foo: ((_: number): string) & ((_: string): string))
- fun app((_: (_: string): unit, _: number): unit) & ((_: (_: string): unit, _: string): unit)
- fun create((_: number): (): bool) & ((_: bool): (): bool)
- fun g0((_: MutArray<string>): string) & ((_: MutArray<object>): string)
- fun db((_: number): MutArray<number>) & ((_: object): MutArray<number>)
+let f: (number => string) & (string => string)
+class M(foo: (number => string) & (string => string))
+let app: (string => unit => number => unit) & (string => unit => string => unit)
+let create: (number => unit => bool) & (bool => unit => bool)
+let g0: (MutArray<string> => string) & (MutArray<object> => string)
+let db: (number => MutArray<number>) & (object => MutArray<number>)
 class N
- fun id((_: M): unit) & ((_: N): unit)
- fun tst((_: (z: number)): (y: string)) & ((_: (z: bool)): (y: string))
- fun op((_: number, _: (number) | (undefined)): unit) & ((_: number, _: (bool) | (undefined)): unit)
- fun swap((_: (number, string, )): (number, string, )) & ((_: (string, number, )): (number, string, ))
- fun u((_: (number) | (bool)): string) & ((_: object): string)
-fun doSome(_: anything): unit /* warning: the overload of function doSome is not supported yet. */
+let id: (M => unit) & (N => unit)
+let tst: ((z: number) => (y: string)) & ((z: bool) => (y: string))
+let op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
+let swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
+let u: ((number) | (bool) => string) & (object => string)
+let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 namespace XX {
-  fun f(_: T, _: anything): string /* warning: the overload of function f is not supported yet. */
+  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
 }
-class WWW(F: (_: T): anything /* warning: the overload of function F is not supported yet. */)
-fun baz(): anything /* warning: the overload of function baz is not supported yet. */
-//│ | |#fun| |f|(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|↵|#class| |M|(|foo|#:| |(|(|_|#:| |number|)|#:| |string|)| |&| |(|(|_|#:| |string|)|#:| |string|)|)|→|#fun| |app|(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |number|)|#:| |unit|)| |&| |(|(|_|#:| |(|_|#:| |string|)|#:| |unit|,| |_|#:| |string|)|#:| |unit|)|↵|#fun| |create|(|(|_|#:| |number|)|#:| |(||)|#:| |bool|)| |&| |(|(|_|#:| |bool|)|#:| |(||)|#:| |bool|)|↵|#fun| |g0|(|(|_|#:| |MutArray|‹|string|›|)|#:| |string|)| |&| |(|(|_|#:| |MutArray|‹|object|›|)|#:| |string|)|↵|#fun| |db|(|(|_|#:| |number|)|#:| |MutArray|‹|number|›|)| |&| |(|(|_|#:| |object|)|#:| |MutArray|‹|number|›|)|←|↵|#class| |N|→|#fun| |id|(|(|_|#:| |M|)|#:| |unit|)| |&| |(|(|_|#:| |N|)|#:| |unit|)|↵|#fun| |tst|(|(|_|#:| |(|z|#:| |number|)|)|#:| |(|y|#:| |string|)|)| |&| |(|(|_|#:| |(|z|#:| |bool|)|)|#:| |(|y|#:| |string|)|)|↵|#fun| |op|(|(|_|#:| |number|,| |_|#:| |(|number|)| ||| |(|undefined|)|)|#:| |unit|)| |&| |(|(|_|#:| |number|,| |_|#:| |(|bool|)| ||| |(|undefined|)|)|#:| |unit|)|↵|#fun| |swap|(|(|_|#:| |(|number|,| |string|,| |)|)|#:| |(|number|,| |string|,| |)|)| |&| |(|(|_|#:| |(|string|,| |number|,| |)|)|#:| |(|number|,| |string|,| |)|)|↵|#fun| |u|(|(|_|#:| |(|number|)| ||| |(|bool|)|)|#:| |string|)| |&| |(|(|_|#:| |object|)|#:| |string|)|←|↵|#fun| |doSome|(|_|#:| |anything|)|#:| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|namespace| |XX| |{|→|#fun| |f|(|_|#:| |T|,| |_|#:| |anything|)|#:| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |(|_|#:| |T|)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#fun| |baz|(||)|#:| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+class WWW(F: T => anything /* warning: the overload of function F is not supported yet. */)
+let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
+//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(|foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|)|↵|#let| |app|#:| |(|string| |=>| |unit| |=>| |number| |=>| |unit|)| |&| |(|string| |=>| |unit| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|)| |=>| |(|y|#:| |string|)|)| |&| |(|(|z|#:| |bool|)| |=>| |(|y|#:| |string|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+//│ ╔══[ERROR] not a recognized type: MutArray‹string›
+//│ ║  l.7: 	let g0: (MutArray<string> => string) & (MutArray<object> => string)
+//│ ╙──     	         ^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: MutArray‹number›
+//│ ║  l.8: 	let db: (number => MutArray<number>) & (object => MutArray<number>)
+//│ ╙──     	                   ^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' y: string, ')'
+//│ ║  l.11: 	let tst: ((z: number) => (y: string)) & ((z: bool) => (y: string))
+//│ ╙──      	                         ^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' number, string, ')'
+//│ ║  l.13: 	let swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
+//│ ╙──      	                                 ^^^^^^^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
-//│ ╙──     	                  ^
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ╙──      	                                       ^
+//│ ╔══[PARSE ERROR] Unexpected operator in expression position
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ╙──      	                                                                                               ^^
+//│ ╔══[PARSE ERROR] Unexpected newline in expression position
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║        	                                                                                                 ^
+//│ ║  l.16: 	namespace XX {
+//│ ╙──      	
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
-//│ ╙──     	       ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Expected function parameter list; found operator instead
-//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
-//│ ╙──     	                            ^
-//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found parenthesis section instead
-//│ ║  l.3: 	 fun f((_: number): string) & ((_: string): string)
-//│ ╙──     	                              ^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
-//│ ╙──     	                         ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
-//│ ╙──     	              ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
-//│ ╙──     	                                                 ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.4: 	class M(foo: ((_: number): string) & ((_: string): string))
-//│ ╙──     	                                      ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Expected end of input; found indented block instead
-//│ ║  l.5: 	 fun app((_: (_: string): unit, _: number): unit) & ((_: (_: string): unit, _: string): unit)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.6: 	 fun create((_: number): (): bool) & ((_: bool): (): bool)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.7: 	 fun g0((_: MutArray<string>): string) & ((_: MutArray<object>): string)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.8: 	 fun db((_: number): MutArray<number>) & ((_: object): MutArray<number>)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.9: 	class N
-//│ ╙──     	^
-//│ Parsed: {fun f = '(' _: number, ')' (string,), => undefined; class M(foo: & ('(' _: number, ')' (string,),) ('(' _: string, ')' (string,),),) {}}
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║        	                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.16: 	namespace XX {
+//│ ╙──      	^^^^^^^^^^^^
+//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
+//│ ║  l.16: 	namespace XX {
+//│ ║        	             ^
+//│ ║  l.17: 	  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.18: 	}
+//│ ╙──      	^
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> anything; fun db: [] -> anything; class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> anything; fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> anything; fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (namespace[(XX,)],)],)],)],)],)],)],)],)],)]}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index b1fa0d1f41..b5a9a73944 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,78 +1,36 @@
 :NewParser
 :ParseOnly
-fun key(_: (string, bool, )): string
-fun value(_: (string, bool, )): bool
-fun third(_: (number, number, number, )): number
-fun vec2(_: number, _: number): (number, number, )
-fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
-fun tupleIt(_: string): ((): string, )
-fun s(_: bool): ((string) | (number), (number) | (bool), )
-fun s2(_: (bool, (string) | (number), )): (string) | (number)
-fun ex(_: T, _: U): (T, U, (T) & (U), )
-fun foo(_: ((T) & (U), )): unit
-fun conv(_: (y: number)): ((y: number), (z: string), )
+let key: (string, bool, ) => string
+let value: (string, bool, ) => bool
+let third: (number, number, number, ) => number
+let vec2: number => number => (number, number, )
+let twoFunctions: (number => number, number => number, ) => number => number
+let tupleIt: string => (unit => string, )
+let s: bool => ((string) | (number), (number) | (bool), )
+let s2: (bool, (string) | (number), ) => (string) | (number)
+let ex: T => U => (T, U, (T) & (U), )
+let foo: ((T) & (U), ) => unit
+let conv: (y: number) => ((y: number), (z: string), )
 class A(x: number)
 class B
-fun swap(_: (A, B, )): (B, A, )
-//│ |#fun| |key|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |string|↵|#fun| |value|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |bool|↵|#fun| |third|(|_|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|_|#:| |number|,| |_|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|_|#:| |(|(|_|#:| |number|)|#:| |number|,| |(|_|#:| |number|)|#:| |number|,| |)|,| |_|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|_|#:| |string|)|#:| |(|(||)|#:| |string|,| |)|↵|#fun| |s|(|_|#:| |bool|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|(|_|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|(|_|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|_|#:| |(|y|#:| |number|)|)|#:| |(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#fun| |swap|(|_|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
-//│ ╔══[ERROR] not a recognized type: '(' string, bool, ')'
-//│ ║  l.3: 	fun key(_: (string, bool, )): string
-//│ ╙──     	           ^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' string, bool, ')'
-//│ ║  l.4: 	fun value(_: (string, bool, )): bool
-//│ ╙──     	             ^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' number, number, number, ')'
-//│ ║  l.5: 	fun third(_: (number, number, number, )): number
-//│ ╙──     	             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+let swap: (A, B, ) => (B, A, )
+//│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|)| |=>| |(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
 //│ ╔══[ERROR] not a recognized type: '(' number, number, ')'
-//│ ║  l.6: 	fun vec2(_: number, _: number): (number, number, )
-//│ ╙──     	                                ^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
-//│ ╙──     	                                ^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
-//│ ╙──     	                                                     ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
-//│ ╙──     	                                          ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
-//│ ╙──     	                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' '(' _: number, ')' (number, '(' _: number, ')' (number,),), ')'
-//│ ║  l.7: 	fun twoFunctions(_: ((_: number): number, (_: number): number, ), _: number): number
-//│ ╙──     	                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.8: 	fun tupleIt(_: string): ((): string, )
-//│ ╙──     	                           ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.8: 	fun tupleIt(_: string): ((): string, )
-//│ ╙──     	                         ^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' '('  ')' (string,), ')'
-//│ ║  l.8: 	fun tupleIt(_: string): ((): string, )
-//│ ╙──     	                        ^^^^^^^^^^^^^^
+//│ ║  l.6: 	let vec2: number => number => (number, number, )
+//│ ╙──     	                              ^^^^^^^^^^^^^^^^^^
+//│ ╔══[ERROR] not a recognized type: '(' unit, => string, ')'
+//│ ║  l.8: 	let tupleIt: string => (unit => string, )
+//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' | (string,) (number,), | (number,) (bool,), ')'
-//│ ║  l.9: 	fun s(_: bool): ((string) | (number), (number) | (bool), )
-//│ ╙──     	                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' bool, | (string,) (number,), ')'
-//│ ║  l.10: 	fun s2(_: (bool, (string) | (number), )): (string) | (number)
-//│ ╙──      	          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.9: 	let s: bool => ((string) | (number), (number) | (bool), )
+//│ ╙──     	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' T, U, & (T,) (U,), ')'
-//│ ║  l.11: 	fun ex(_: T, _: U): (T, U, (T) & (U), )
-//│ ╙──      	                    ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' & (T,) (U,), ')'
-//│ ║  l.12: 	fun foo(_: ((T) & (U), )): unit
-//│ ╙──      	           ^^^^^^^^^^^^^
+//│ ║  l.11: 	let ex: T => U => (T, U, (T) & (U), )
+//│ ╙──      	                  ^^^^^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' '(' y: number, ')', '(' z: string, ')', ')'
-//│ ║  l.13: 	fun conv(_: (y: number)): ((y: number), (z: string), )
-//│ ╙──      	                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' y: number, ')'
-//│ ║  l.13: 	fun conv(_: (y: number)): ((y: number), (z: string), )
-//│ ╙──      	            ^^^^^^^^^^^
+//│ ║  l.13: 	let conv: (y: number) => ((y: number), (z: string), )
+//│ ╙──      	                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' B, A, ')'
-//│ ║  l.16: 	fun swap(_: (A, B, )): (B, A, )
-//│ ╙──      	                       ^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' A, B, ')'
-//│ ║  l.16: 	fun swap(_: (A, B, )): (B, A, )
-//│ ╙──      	            ^^^^^^^^
-//│ Parsed: {fun key: [] -> anything -> string; fun value: [] -> anything -> bool; fun third: [] -> anything -> number; fun vec2: [] -> (_: number, _: number,) -> anything; fun twoFunctions: [] -> anything -> number; fun tupleIt: [] -> (_: string,) -> anything; fun s: [] -> (_: bool,) -> anything; fun s2: [] -> anything -> ((string,) | (number,)); fun ex: [] -> (_: T, _: U,) -> anything; fun foo: [] -> anything -> unit; fun conv: [] -> anything -> anything; class A(x: number,) {}; class B() {}; fun swap: [] -> anything -> anything}
+//│ ║  l.16: 	let swap: (A, B, ) => (B, A, )
+//│ ╙──      	                      ^^^^^^^^
+//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> anything; fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> anything; fun s: [] -> anything; fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> anything; fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> anything; class A(x: number,) {}; class B() {}; fun swap: [] -> anything}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index bf20df7ce2..47444392dd 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,65 +1,35 @@
 :NewParser
 :ParseOnly
-fun inc(_: T): number
-class CC<T>(print: (_: T): unit)
-fun con(_: T): U
-class Printer<T>(print: (_: T): unit)
-fun setStringPrinter(_: Printer<string>): unit
-fun getStringPrinter(): Printer<string>
-fun foo(_: Printer<T>, _: T): T
-fun foo2(_: Printer<T>, _: T): T
-class F<T>(x: T, GG: (_: U): T)
-trait I<T>(x: T, GG: (_: U): T)
-class FFF<T>(fff: (_: T): unit)
-fun fff(_: FFF<string>, _: string): unit
-fun getFFF(): FFF<number>
-//│ |#fun| |inc|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |con|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |setStringPrinter|(|_|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|_|#:| |U|)|#:| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |(|_|#:| |T|)|#:| |unit|)|↵|#fun| |fff|(|_|#:| |FFF|‹|string|›|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.4: 	class CC<T>(print: (_: T): unit)
-//│ ╙──     	                         ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.4: 	class CC<T>(print: (_: T): unit)
-//│ ╙──     	                   ^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.6: 	class Printer<T>(print: (_: T): unit)
-//│ ╙──     	                              ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.6: 	class Printer<T>(print: (_: T): unit)
-//│ ╙──     	                        ^^^^^^^^^^^^
+let inc: T => number
+class CC<T>(print: T => unit)
+let con: T => U
+class Printer<T>(print: T => unit)
+let setStringPrinter: Printer<string> => unit
+let getStringPrinter: unit => Printer<string>
+let foo: Printer<T> => T => T
+let foo2: Printer<T> => T => T
+class F<T>(x: T, GG: U => T)
+trait I<T>(x: T, GG: U => T)
+class FFF<T>(fff: T => unit)
+let fff: FFF<string> => string => unit
+let getFFF: unit => FFF<number>
+//│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |T| |=>| |unit|)|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
 //│ ╔══[ERROR] not a recognized type: Printer‹string›
-//│ ║  l.7: 	fun setStringPrinter(_: Printer<string>): unit
-//│ ╙──     	                        ^^^^^^^^^^^^^^
+//│ ║  l.7: 	let setStringPrinter: Printer<string> => unit
+//│ ╙──     	                      ^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: Printer‹string›
-//│ ║  l.8: 	fun getStringPrinter(): Printer<string>
-//│ ╙──     	                        ^^^^^^^^^^^^^^
+//│ ║  l.8: 	let getStringPrinter: unit => Printer<string>
+//│ ╙──     	                              ^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: Printer‹T›
-//│ ║  l.9: 	fun foo(_: Printer<T>, _: T): T
-//│ ╙──     	           ^^^^^^^^^
+//│ ║  l.9: 	let foo: Printer<T> => T => T
+//│ ╙──     	         ^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: Printer‹T›
-//│ ║  l.10: 	fun foo2(_: Printer<T>, _: T): T
-//│ ╙──      	            ^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.11: 	class F<T>(x: T, GG: (_: U): T)
-//│ ╙──      	                           ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.11: 	class F<T>(x: T, GG: (_: U): T)
-//│ ╙──      	                     ^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.12: 	trait I<T>(x: T, GG: (_: U): T)
-//│ ╙──      	                           ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.12: 	trait I<T>(x: T, GG: (_: U): T)
-//│ ╙──      	                     ^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.13: 	class FFF<T>(fff: (_: T): unit)
-//│ ╙──      	                        ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.13: 	class FFF<T>(fff: (_: T): unit)
-//│ ╙──      	                  ^^^^^^^^^^^^
+//│ ║  l.10: 	let foo2: Printer<T> => T => T
+//│ ╙──      	          ^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: FFF‹string›
-//│ ║  l.14: 	fun fff(_: FFF<string>, _: string): unit
-//│ ╙──      	           ^^^^^^^^^^
+//│ ║  l.14: 	let fff: FFF<string> => string => unit
+//│ ╙──      	         ^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: FFF‹number›
-//│ ║  l.15: 	fun getFFF(): FFF<number>
-//│ ╙──      	              ^^^^^^^^^^
-//│ Parsed: {fun inc: [] -> (_: T,) -> number; class CC[T](print: '(' _: T, ')' (unit,),) {}; fun con: [] -> (_: T,) -> U; class Printer[T](print: '(' _: T, ')' (unit,),) {}; fun setStringPrinter: [] -> anything -> unit; fun getStringPrinter: [] -> () -> anything; fun foo: [] -> anything -> T; fun foo2: [] -> anything -> T; class F[T](x: T, GG: '(' _: U, ')' (T,),) {}; trait I[T](x: T, GG: '(' _: U, ')' (T,),): {}; class FFF[T](fff: '(' _: T, ')' (unit,),) {}; fun fff: [] -> anything -> unit; fun getFFF: [] -> () -> anything}
+//│ ║  l.15: 	let getFFF: unit => FFF<number>
+//│ ╙──      	                    ^^^^^^^^^^
+//│ Parsed: {fun inc: [] -> T -> number; class CC[T](print: T, => unit,) {}; fun con: [] -> T -> U; class Printer[T](print: T, => unit,) {}; fun setStringPrinter: [] -> anything; fun getStringPrinter: [] -> anything; fun foo: [] -> anything; fun foo2: [] -> anything; class F[T](x: T, GG: U, => T,) {}; trait I[T](x: T, GG: U, => T,): {}; class FFF[T](fff: T, => unit,) {}; fun fff: [] -> anything; fun getFFF: [] -> anything}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 1928269d6a..bc62bd1ab2 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,32 +1,17 @@
 :NewParser
 :ParseOnly
-fun getString(_: ((string) | (number)) | (bool)): string
-fun test(_: bool): (string) | (number)
-fun run(_: ((_: number): number) | ((_: number): string)): anything
-fun get(_: (MutArray<number>) | (MutArray<string>)): unit
-fun get2(_: ((string, string, )) | ((number, string, ))): string
-fun typeVar(_: (T) | (U)): (T) | (U)
-fun uuuu(_: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
-//│ |#fun| |getString|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|_|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|_|#:| |(|(|_|#:| |number|)|#:| |number|)| ||| |(|(|_|#:| |number|)|#:| |string|)|)|#:| |anything|↵|#fun| |get|(|_|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|_|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|(|_|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
-//│ ╙──     	                       ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
-//│ ╙──     	            ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
-//│ ╙──     	                                               ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
-//│ ╙──     	                                    ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' _: number, ')'
-//│ ║  l.5: 	fun run(_: ((_: number): number) | ((_: number): string)): anything
-//│ ╙──     	            ^^^^^^^^^^^
+let getString: ((string) | (number)) | (bool) => string
+let test: bool => (string) | (number)
+let run: (number => number) | (number => string) => anything
+let get: (MutArray<number>) | (MutArray<string>) => unit
+let get2: ((string, string, )) | ((number, string, )) => string
+let typeVar: (T) | (U) => (T) | (U)
+let uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
+//│ |#let| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#let| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#let| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#let| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#let| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#let| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#let| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
 //│ ╔══[ERROR] not a recognized type: MutArray‹number›
-//│ ║  l.6: 	fun get(_: (MutArray<number>) | (MutArray<string>)): unit
-//│ ╙──     	            ^^^^^^^^^^^^^^^
+//│ ║  l.6: 	let get: (MutArray<number>) | (MutArray<string>) => unit
+//│ ╙──     	          ^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: '(' string, string, ')'
-//│ ║  l.7: 	fun get2(_: ((string, string, )) | ((number, string, ))): string
-//│ ╙──     	             ^^^^^^^^^^^^^^^^^^
-//│ Parsed: {fun getString: [] -> (_: ((string,) | (number,),) | (bool,),) -> string; fun test: [] -> (_: bool,) -> ((string,) | (number,)); fun run: [] -> anything -> anything; fun get: [] -> anything -> unit; fun get2: [] -> anything -> string; fun typeVar: [] -> (_: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (_: ((string,) | (number,),) | (bool,),) -> (((string,) | (number,),) | (bool,))}
+//│ ║  l.7: 	let get2: ((string, string, )) | ((number, string, )) => string
+//│ ╙──     	           ^^^^^^^^^^^^^^^^^^
+//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> anything; fun get2: [] -> anything; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}

From 234f8dcdd910d1d4c696c66e2676ed2189d6959f Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 10:20:45 +0800
Subject: [PATCH 04/40] Fix namespaces parse

---
 shared/src/main/scala/mlscript/NewLexer.scala |  1 +
 shared/src/main/scala/mlscript/TypeDefs.scala |  4 +++
 ts2mls/js/src/test/diff/Heritage.d.mls        | 16 ++--------
 ts2mls/js/src/test/diff/MultiFiles.d.mls      | 18 ++---------
 ts2mls/js/src/test/diff/Namespace.d.mls       | 30 ++-----------------
 ts2mls/js/src/test/diff/Overload.d.mls        |  7 +++--
 6 files changed, 16 insertions(+), 60 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewLexer.scala b/shared/src/main/scala/mlscript/NewLexer.scala
index 3117a30282..7369cc02b8 100644
--- a/shared/src/main/scala/mlscript/NewLexer.scala
+++ b/shared/src/main/scala/mlscript/NewLexer.scala
@@ -233,6 +233,7 @@ object NewLexer {
     "trait",
     "interface",
     "new",
+    "namespace"
   )
   
   def printToken(tl: TokLoc): Str = tl match {
diff --git a/shared/src/main/scala/mlscript/TypeDefs.scala b/shared/src/main/scala/mlscript/TypeDefs.scala
index 78dd34b132..2db345f048 100644
--- a/shared/src/main/scala/mlscript/TypeDefs.scala
+++ b/shared/src/main/scala/mlscript/TypeDefs.scala
@@ -227,6 +227,7 @@ class TypeDefs extends NuTypeDefs { self: Typer =>
         
         val rightParents = td.kind match {
           case Als => checkCycle(td.bodyTy)(Set.single(L(td.nme)))
+          case Nms => checkCycle(td.bodyTy)(Set.single(L(td.nme)))
           case k: ObjDefKind =>
             val parentsClasses = MutSet.empty[TypeRef]
             def checkParents(ty: SimpleType): Bool = ty match {
@@ -246,6 +247,9 @@ class TypeDefs extends NuTypeDefs { self: Typer =>
                     } else
                       checkParents(tr.expand)
                   case Trt => checkParents(tr.expand)
+                  case Nms =>
+                    err(msg"cannot inherit from a namespace", prov.loco)
+                    false
                   case Als => 
                     err(msg"cannot inherit from a type alias", prov.loco)
                     false
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 8371bc2bf4..695574bb2e 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -17,17 +17,5 @@ namespace Five {
   class Five'Y: Five'ROTK
 }
 class Y: Five'ROTK
-//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.15: 	namespace Five {
-//│ ╙──      	^^^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
-//│ ║  l.15: 	namespace Five {
-//│ ║        	               ^
-//│ ║  l.16: 	  class Five'ROTK(wu: string)
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.17: 	  class Five'Y: Five'ROTK
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.18: 	}
-//│ ╙──      	^
-//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace (Five,)}
+//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
+//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace Five(): {class Five'ROTK(wu: string,) {}; class Five'Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index c4f77b3ee1..f0a5dfe0dc 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -14,19 +14,5 @@ let multi4: unit => unit
 trait Base(a: number)
 class AnotherFoo: AnotherBase
 let multi5: unit => unit
-//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.7: 	namespace N {
-//│ ╙──     	^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
-//│ ║  l.7: 	namespace N {
-//│ ║       	            ^
-//│ ║  l.8: 	  let f: unit => unit
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.9: 	  let g: unit => unit
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.10: 	  let h: unit => unit
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.11: 	}
-//│ ╙──      	^
-//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace (N,)}
+//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
+//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(a: number,): {}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 32624189e2..862337619d 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -20,31 +20,5 @@ namespace AA {
 }
 let f1: N1'C => N1'C
 let f2: AA'C => AA'C
-//│ |namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |N1'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |N1'I|(|f|#:| |unit| |=>| |number|)|↵|namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |N1'N2'BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |AA'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |AA'I|(|f|#:| |unit| |=>| |number|)|↵|namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	namespace N1 {
-//│ ╙──     	^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
-//│ ║  l.3: 	namespace N1 {
-//│ ║       	             ^
-//│ ║  l.4: 	  let f: anything => number
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.5: 	  let ff: anything => number
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.6: 	  class N1'C(f: unit => unit)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.7: 	  trait N1'I(f: unit => number)
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.8: 	  namespace N2 {
-//│ ║       	^^^^^^^^^^^^^^^^
-//│ ║  l.9: 	    let fff: bool => number
-//│ ║       	^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.10: 	    let gg: N1'C => N1'C
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.11: 	    class N1'N2'BBB: N1'C
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.12: 	  }
-//│ ║        	^^^
-//│ ║  l.13: 	}
-//│ ╙──      	^
-//│ Parsed: {namespace (N1,)}
+//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |N1'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |N1'I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |N1'N2'BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |AA'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |AA'I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class N1'C(f: unit, => unit,) {}; trait N1'I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class N1'N2'BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class AA'C(f: unit, => unit,) {}; trait AA'I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index cdce4a0dfa..9a1818f0da 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -18,7 +18,7 @@ namespace XX {
 }
 class WWW(F: T => anything /* warning: the overload of function F is not supported yet. */)
 let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(|foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|)|↵|#let| |app|#:| |(|string| |=>| |unit| |=>| |number| |=>| |unit|)| |&| |(|string| |=>| |unit| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|)| |=>| |(|y|#:| |string|)|)| |&| |(|(|z|#:| |bool|)| |=>| |(|y|#:| |string|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(|foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|)|↵|#let| |app|#:| |(|string| |=>| |unit| |=>| |number| |=>| |unit|)| |&| |(|string| |=>| |unit| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|)| |=>| |(|y|#:| |string|)|)| |&| |(|(|z|#:| |bool|)| |=>| |(|y|#:| |string|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
 //│ ╔══[ERROR] not a recognized type: MutArray‹string›
 //│ ║  l.7: 	let g0: (MutArray<string> => string) & (MutArray<object> => string)
 //│ ╙──     	         ^^^^^^^^^^^^^^^
@@ -42,6 +42,9 @@ let baz: unit => anything /* warning: the overload of function baz is not suppor
 //│ ║        	                                                                                                 ^
 //│ ║  l.16: 	namespace XX {
 //│ ╙──      	
+//│ ╔══[PARSE ERROR] Unexpected 'namespace' keyword in expression position
+//│ ║  l.16: 	namespace XX {
+//│ ╙──      	^^^^^^^^^
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
 //│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 //│ ║        	                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -54,4 +57,4 @@ let baz: unit => anything /* warning: the overload of function baz is not suppor
 //│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.18: 	}
 //│ ╙──      	^
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> anything; fun db: [] -> anything; class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> anything; fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> anything; fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (namespace[(XX,)],)],)],)],)],)],)],)],)],)]}
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> anything; fun db: [] -> anything; class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> anything; fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> anything; fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}

From cc5bc3a26d46f6b4494626af673fdcf0784a0a50 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 10:31:34 +0800
Subject: [PATCH 05/40] Fix class/trait names

---
 ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala  |  8 ++++----
 ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala |  4 ++--
 ts2mls/js/src/test/diff/Heritage.d.mls             |  8 ++++----
 ts2mls/js/src/test/diff/Namespace.d.mls            | 14 +++++++-------
 4 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index ca6735a931..8489c8d204 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -72,10 +72,10 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
 
   // generate full path with namespaces' names
   // e.g. f => Namespace1.Namespace2.f
-  def getFullPath(nm: String): String = parent match {
-    case Some(p) => p.getFullPath(s"$name'$nm")
-    case _ => nm
-  }
+  // def getFullPath(nm: String): String = parent match {
+  //   case Some(p) => p.getFullPath(s"$name'$nm")
+  //   case _ => nm
+  // }
 }
 
 object TSNamespace {
diff --git a/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala b/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
index 41516fa7ba..6c0e807e77 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
@@ -163,9 +163,9 @@ object TSSourceFile {
       }
     }
     else if (node.isClassDeclaration)
-      ns.put(name, parseMembers(ns.getFullPath(name), node, true))
+      ns.put(name, parseMembers(name, node, true))
     else if (node.isInterfaceDeclaration)
-      ns.put(name, parseMembers(ns.getFullPath(name), node, false))
+      ns.put(name, parseMembers(name, node, false))
     else if (node.isNamespace)
       parseNamespace(node)
 
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 695574bb2e..5e2275ddbb 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -13,9 +13,9 @@ class Home<T>(y: T): VG<string>
 trait O<I>(xx: I => I)
 class OR<R>(xx: R => R): O<R>
 namespace Five {
-  class Five'ROTK(wu: string)
-  class Five'Y: Five'ROTK
+  class ROTK(wu: string)
+  class Y: Five'ROTK
 }
 class Y: Five'ROTK
-//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |Five'ROTK|(|wu|#:| |string|)|↵|#class| |Five'Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
-//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace Five(): {class Five'ROTK(wu: string,) {}; class Five'Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |ROTK|(|wu|#:| |string|)|↵|#class| |Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
+//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace Five(): {class ROTK(wu: string,) {}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 862337619d..dc2cd60edb 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -3,22 +3,22 @@
 namespace N1 {
   let f: anything => number
   let ff: anything => number
-  class N1'C(f: unit => unit)
-  trait N1'I(f: unit => number)
+  class C(f: unit => unit)
+  trait I(f: unit => number)
   namespace N2 {
     let fff: bool => number
     let gg: N1'C => N1'C
-    class N1'N2'BBB: N1'C
+    class BBB: N1'C
   }
 }
 namespace AA {
   let f: anything => string
-  class AA'C(f: unit => unit)
-  trait AA'I(f: unit => number)
+  class C(f: unit => unit)
+  trait I(f: unit => number)
   namespace N2 {
   }
 }
 let f1: N1'C => N1'C
 let f2: AA'C => AA'C
-//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |N1'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |N1'I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |N1'N2'BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |AA'C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |AA'I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class N1'C(f: unit, => unit,) {}; trait N1'I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class N1'N2'BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class AA'C(f: unit, => unit,) {}; trait AA'I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
+//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}

From af5a9270b12cd4522914375e85052b1d60ce8927 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 11:14:41 +0800
Subject: [PATCH 06/40] Fix bra type

---
 shared/src/main/scala/mlscript/helpers.scala  |  1 +
 ts2mls/js/src/test/diff/InterfaceMember.d.mls |  5 +----
 ts2mls/js/src/test/diff/Intersection.d.mls    |  5 +----
 ts2mls/js/src/test/diff/Optional.d.mls        |  5 +----
 ts2mls/js/src/test/diff/Overload.d.mls        |  8 +-------
 ts2mls/js/src/test/diff/Tuple.d.mls           | 20 +------------------
 ts2mls/js/src/test/diff/Union.d.mls           |  5 +----
 7 files changed, 7 insertions(+), 42 deletions(-)

diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala
index ec005fccd1..6ea3222c8c 100644
--- a/shared/src/main/scala/mlscript/helpers.scala
+++ b/shared/src/main/scala/mlscript/helpers.scala
@@ -425,6 +425,7 @@ trait TermImpl extends StatementImpl { self: Term =>
     case Tup(fields) => Tuple(fields.map(fld => (fld._1, fld._2 match {
       case Fld(m, s, v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty)
     })))
+    case Bra(rcd, trm) if (!rcd) => trm.toType_!
     // TODO:
     // case Rcd(fields) => ???
     // case Sel(receiver, fieldName) => ???
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 2d30271797..7a7e4511a4 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -13,7 +13,4 @@ trait Simple2<T>(abc: T)
 trait Next: Simple
 trait TTT<T>(ttt: T => T)
 //│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |number| |=>| |number|,| |c|#:| |unit| |=>| |bool|,| |d|#:| |string| |=>| |unit|)|↵|#trait| |II|‹|T|›|(|test|#:| |T| |=>| |number|)|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|)|↵|#let| |get|#:| |(|t|#:| |string|)| |=>| |string|↵|#trait| |IEvent|(|callback|#:| |unit| |=>| |number| |=>| |unit|)|↵|#trait| |SearchFunc|(|__call|#:| |string| |=>| |string| |=>| |bool|)|↵|#trait| |StringArray|(|__index|#:| |number| |=>| |string|)|↵|#trait| |Counter|(|__call|#:| |number| |=>| |string|,| |interval|#:| |number|,| |reset|#:| |unit| |=>| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |bool| |=>| |string|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|)|
-//│ ╔══[ERROR] not a recognized type: '(' v: number, ')'
-//│ ║  l.5: 	let create: unit => (v: number)
-//│ ╙──     	                    ^^^^^^^^^^^
-//│ Parsed: {trait IFoo(a: string, b: number, => number, c: unit, => bool, d: string, => unit,): {}; trait II[T](test: T, => number,): {}; fun create: [] -> anything; fun get: [] -> (t: string,) -> string; trait IEvent(callback: unit, => number, => unit,): {}; trait SearchFunc(__call: string, => string, => bool,): {}; trait StringArray(__index: number, => string,): {}; trait Counter(__call: number, => string, interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => string,): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => T,): {}}
+//│ Parsed: {trait IFoo(a: string, b: number, => number, c: unit, => bool, d: string, => unit,): {}; trait II[T](test: T, => number,): {}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(callback: unit, => number, => unit,): {}; trait SearchFunc(__call: string, => string, => bool,): {}; trait StringArray(__index: number, => string,): {}; trait Counter(__call: number, => string, interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => string,): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => T,): {}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 375c06c5ca..4f7c2dc029 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -17,7 +17,4 @@ let inter: (A) & (B) => (A) & (B)
 //│ ╔══[ERROR] not a recognized type: MutArray‹U›
 //│ ║  l.11: 	let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
 //│ ╙──      	          ^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' U, T, ')'
-//│ ║  l.12: 	let tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
-//│ ╙──      	         ^^^^^^^^
-//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> anything; fun tt: [] -> anything; class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
+//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> anything; fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 666e9bebf7..6ae8ece931 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -25,10 +25,7 @@ let boom: (B<nothing>) | (undefined) => anything
 //│ ╔══[ERROR] not a recognized type: MutArray‹object›
 //│ ║  l.9: 	let getOrElse: (MutArray<object>) | (undefined) => object
 //│ ╙──     	                ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' number, string, ')'
-//│ ║  l.13: 	let err: ((number, string, )) | (undefined) => unit
-//│ ╙──      	          ^^^^^^^^^^^^^^^^^^
 //│ ╔══[ERROR] not a recognized type: B‹nothing›
 //│ ║  l.17: 	let boom: (B<nothing>) | (undefined) => anything
 //│ ╙──      	           ^^^^^^^^^
-//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> anything; fun buildName4: [] -> anything; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> anything; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> anything; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> anything}
+//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> anything; fun buildName4: [] -> anything; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> anything; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 9a1818f0da..13d069444b 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -25,12 +25,6 @@ let baz: unit => anything /* warning: the overload of function baz is not suppor
 //│ ╔══[ERROR] not a recognized type: MutArray‹number›
 //│ ║  l.8: 	let db: (number => MutArray<number>) & (object => MutArray<number>)
 //│ ╙──     	                   ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' y: string, ')'
-//│ ║  l.11: 	let tst: ((z: number) => (y: string)) & ((z: bool) => (y: string))
-//│ ╙──      	                         ^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' number, string, ')'
-//│ ║  l.13: 	let swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
-//│ ╙──      	                                 ^^^^^^^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 //│ ╙──      	                                       ^
@@ -57,4 +51,4 @@ let baz: unit => anything /* warning: the overload of function baz is not suppor
 //│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.18: 	}
 //│ ╙──      	^
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> anything; fun db: [] -> anything; class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> anything; fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> anything; fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> anything; fun db: [] -> anything; class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index b5a9a73944..753f794b68 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -15,22 +15,4 @@ class A(x: number)
 class B
 let swap: (A, B, ) => (B, A, )
 //│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|)| |=>| |(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
-//│ ╔══[ERROR] not a recognized type: '(' number, number, ')'
-//│ ║  l.6: 	let vec2: number => number => (number, number, )
-//│ ╙──     	                              ^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' unit, => string, ')'
-//│ ║  l.8: 	let tupleIt: string => (unit => string, )
-//│ ╙──     	                       ^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' | (string,) (number,), | (number,) (bool,), ')'
-//│ ║  l.9: 	let s: bool => ((string) | (number), (number) | (bool), )
-//│ ╙──     	               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' T, U, & (T,) (U,), ')'
-//│ ║  l.11: 	let ex: T => U => (T, U, (T) & (U), )
-//│ ╙──      	                  ^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' '(' y: number, ')', '(' z: string, ')', ')'
-//│ ║  l.13: 	let conv: (y: number) => ((y: number), (z: string), )
-//│ ╙──      	                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' B, A, ')'
-//│ ║  l.16: 	let swap: (A, B, ) => (B, A, )
-//│ ╙──      	                      ^^^^^^^^
-//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> anything; fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> anything; fun s: [] -> anything; fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> anything; fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> anything; class A(x: number,) {}; class B() {}; fun swap: [] -> anything}
+//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A(x: number,) {}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index bc62bd1ab2..6bda339f40 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -11,7 +11,4 @@ let uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
 //│ ╔══[ERROR] not a recognized type: MutArray‹number›
 //│ ║  l.6: 	let get: (MutArray<number>) | (MutArray<string>) => unit
 //│ ╙──     	          ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: '(' string, string, ')'
-//│ ║  l.7: 	let get2: ((string, string, )) | ((number, string, )) => string
-//│ ╙──     	           ^^^^^^^^^^^^^^^^^^
-//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> anything; fun get2: [] -> anything; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}
+//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> anything; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}

From 87b8f15f8d3e2019d5845a96f95eefa874f13b77 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 14:37:19 +0800
Subject: [PATCH 07/40] Fix type parameters application

---
 shared/src/main/scala/mlscript/helpers.scala |  6 +++++-
 ts2mls/js/src/test/diff/Intersection.d.mls   |  5 +----
 ts2mls/js/src/test/diff/Optional.d.mls       | 14 +-------------
 ts2mls/js/src/test/diff/Overload.d.mls       |  8 +-------
 ts2mls/js/src/test/diff/TypeParameter.d.mls  | 20 +-------------------
 ts2mls/js/src/test/diff/Union.d.mls          |  5 +----
 6 files changed, 10 insertions(+), 48 deletions(-)

diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala
index 6ea3222c8c..30cd4fd39c 100644
--- a/shared/src/main/scala/mlscript/helpers.scala
+++ b/shared/src/main/scala/mlscript/helpers.scala
@@ -426,10 +426,14 @@ trait TermImpl extends StatementImpl { self: Term =>
       case Fld(m, s, v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty)
     })))
     case Bra(rcd, trm) if (!rcd) => trm.toType_!
+    case TyApp(lhs, targs) => lhs.toType_! match {
+      case p: TypeName => AppliedType(p, targs)
+      case _ => throw new NotAType(this)
+    }
     // TODO:
     // case Rcd(fields) => ???
     // case Sel(receiver, fieldName) => ???
-    // case Let(isRec, name, rhs, body) => ???
+    // case Let(isRec, name, rhs, body) => 
     // case Blk(stmts) => ???
     // case Bra(rcd, trm) => ???
     // case Asc(trm, ty) => ???
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 4f7c2dc029..bbbe8eb4c5 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -14,7 +14,4 @@ class A
 class B
 let inter: (A) & (B) => (A) & (B)
 //│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
-//│ ╔══[ERROR] not a recognized type: MutArray‹U›
-//│ ║  l.11: 	let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
-//│ ╙──      	          ^^^^^^^^^^
-//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> anything; fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
+//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 6ae8ece931..9a4119d460 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -16,16 +16,4 @@ let boo: ((T) & (U)) | (undefined) => unit
 class B<T>(b: T)
 let boom: (B<nothing>) | (undefined) => anything
 //│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
-//│ ╔══[ERROR] not a recognized type: MutArray‹string›
-//│ ║  l.5: 	let buildName3: string => MutArray<string> => string
-//│ ╙──     	                          ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: MutArray‹anything›
-//│ ║  l.6: 	let buildName4: string => MutArray<anything> => string
-//│ ╙──     	                          ^^^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: MutArray‹object›
-//│ ║  l.9: 	let getOrElse: (MutArray<object>) | (undefined) => object
-//│ ╙──     	                ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: B‹nothing›
-//│ ║  l.17: 	let boom: (B<nothing>) | (undefined) => anything
-//│ ╙──      	           ^^^^^^^^^
-//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> anything; fun buildName4: [] -> anything; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> anything; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> anything}
+//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 13d069444b..7f3424c976 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -19,12 +19,6 @@ namespace XX {
 class WWW(F: T => anything /* warning: the overload of function F is not supported yet. */)
 let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
 //│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(|foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|)|↵|#let| |app|#:| |(|string| |=>| |unit| |=>| |number| |=>| |unit|)| |&| |(|string| |=>| |unit| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|)| |=>| |(|y|#:| |string|)|)| |&| |(|(|z|#:| |bool|)| |=>| |(|y|#:| |string|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
-//│ ╔══[ERROR] not a recognized type: MutArray‹string›
-//│ ║  l.7: 	let g0: (MutArray<string> => string) & (MutArray<object> => string)
-//│ ╙──     	         ^^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: MutArray‹number›
-//│ ║  l.8: 	let db: (number => MutArray<number>) & (object => MutArray<number>)
-//│ ╙──     	                   ^^^^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
 //│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 //│ ╙──      	                                       ^
@@ -51,4 +45,4 @@ let baz: unit => anything /* warning: the overload of function baz is not suppor
 //│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.18: 	}
 //│ ╙──      	^
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> anything; fun db: [] -> anything; class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index 47444392dd..b416bd291d 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -14,22 +14,4 @@ class FFF<T>(fff: T => unit)
 let fff: FFF<string> => string => unit
 let getFFF: unit => FFF<number>
 //│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |T| |=>| |unit|)|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ ╔══[ERROR] not a recognized type: Printer‹string›
-//│ ║  l.7: 	let setStringPrinter: Printer<string> => unit
-//│ ╙──     	                      ^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: Printer‹string›
-//│ ║  l.8: 	let getStringPrinter: unit => Printer<string>
-//│ ╙──     	                              ^^^^^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: Printer‹T›
-//│ ║  l.9: 	let foo: Printer<T> => T => T
-//│ ╙──     	         ^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: Printer‹T›
-//│ ║  l.10: 	let foo2: Printer<T> => T => T
-//│ ╙──      	          ^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: FFF‹string›
-//│ ║  l.14: 	let fff: FFF<string> => string => unit
-//│ ╙──      	         ^^^^^^^^^^
-//│ ╔══[ERROR] not a recognized type: FFF‹number›
-//│ ║  l.15: 	let getFFF: unit => FFF<number>
-//│ ╙──      	                    ^^^^^^^^^^
-//│ Parsed: {fun inc: [] -> T -> number; class CC[T](print: T, => unit,) {}; fun con: [] -> T -> U; class Printer[T](print: T, => unit,) {}; fun setStringPrinter: [] -> anything; fun getStringPrinter: [] -> anything; fun foo: [] -> anything; fun foo2: [] -> anything; class F[T](x: T, GG: U, => T,) {}; trait I[T](x: T, GG: U, => T,): {}; class FFF[T](fff: T, => unit,) {}; fun fff: [] -> anything; fun getFFF: [] -> anything}
+//│ Parsed: {fun inc: [] -> T -> number; class CC[T](print: T, => unit,) {}; fun con: [] -> T -> U; class Printer[T](print: T, => unit,) {}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T](x: T, GG: U, => T,) {}; trait I[T](x: T, GG: U, => T,): {}; class FFF[T](fff: T, => unit,) {}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 6bda339f40..14daeda466 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -8,7 +8,4 @@ let get2: ((string, string, )) | ((number, string, )) => string
 let typeVar: (T) | (U) => (T) | (U)
 let uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
 //│ |#let| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#let| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#let| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#let| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#let| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#let| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#let| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ ╔══[ERROR] not a recognized type: MutArray‹number›
-//│ ║  l.6: 	let get: (MutArray<number>) | (MutArray<string>) => unit
-//│ ╙──     	          ^^^^^^^^^^^^^^^
-//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> anything; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}
+//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}

From d2ee8d0e4cacf79861558345c73e64d618273ba1 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 14:45:43 +0800
Subject: [PATCH 08/40] Fix parentheses

---
 .../main/scala/ts2mls/types/Converter.scala   |   2 +-
 ts2mls/js/src/test/diff/Array.d.mls           | 102 +++++++++++++++---
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  |  26 ++---
 ts2mls/js/src/test/diff/ClassMember.d.mls     |  12 +--
 ts2mls/js/src/test/diff/Enum.d.mls            |   8 +-
 ts2mls/js/src/test/diff/Heritage.d.mls        |  10 +-
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   |  10 +-
 ts2mls/js/src/test/diff/InterfaceMember.d.mls |  22 ++--
 ts2mls/js/src/test/diff/Intersection.d.mls    |  22 ++--
 ts2mls/js/src/test/diff/MultiFiles.d.mls      |   8 +-
 ts2mls/js/src/test/diff/Namespace.d.mls       |  18 ++--
 ts2mls/js/src/test/diff/Optional.d.mls        |  28 ++---
 ts2mls/js/src/test/diff/Overload.d.mls        |  52 ++++-----
 ts2mls/js/src/test/diff/Tuple.d.mls           |  28 ++---
 ts2mls/js/src/test/diff/TypeParameter.d.mls   |  26 ++---
 ts2mls/js/src/test/diff/Union.d.mls           |  18 ++--
 16 files changed, 232 insertions(+), 160 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 4721ac9405..f39f202bdb 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -25,7 +25,7 @@ object Converter {
       // since functions can be defined by both `def` and `method`, it only returns the type of functions
       if (params.length == 0) s"${primitiveName("void")} => ${convert(res)}"
       else
-        params.foldRight(convert(res))((p, f) => s"${convert(p)} => $f")
+        params.foldRight(convert(res))((p, f) => s"(${convert(p)}) => ($f)")
     case TSUnionType(lhs, rhs) => {
       val lres = convert(lhs)
       val rres = convert(rhs)
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 377b900dd4..c4a463650e 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,23 +1,95 @@
 :NewParser
 :ParseOnly
-let first: MutArray<string> => string
+let first: (MutArray<string>) => (string)
 let getZero3: unit => MutArray<number>
-let first2: MutArray<number => number> => number => number
-let doEs: MutArray<int> => MutArray<int>
+let first2: (MutArray<(number) => (number)>) => ((number) => (number))
+let doEs: (MutArray<int>) => (MutArray<int>)
 class C
 trait I(i: number)
-let doCs: MutArray<C> => MutArray<C>
-let doIs: MutArray<I> => MutArray<I>
-let inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
-let clean: MutArray<(string, number, )> => MutArray<(string, number, )>
-let translate: MutArray<T> => MutArray<U>
-let uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
+let doCs: (MutArray<C>) => (MutArray<C>)
+let doIs: (MutArray<I>) => (MutArray<I>)
+let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
+let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
+let translate: (MutArray<T>) => (MutArray<U>)
+let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
 class Temp<T>(x: T)
-let ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
-let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
+let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
+let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.5: 	let first2: (MutArray<(number) => (number)>) => ((number) => (number))
+//│ ║       	                                           ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.5: 	let first2: (MutArray<(number) => (number)>) => ((number) => (number))
+//│ ╙──     	                     ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
+//│ ║        	                               ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
+//│ ╙──      	                    ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
+//│ ║        	                                                        ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
+//│ ╙──      	                                             ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
+//│ ║        	                                        ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
+//│ ╙──      	                    ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
+//│ ║        	                                                                          ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
+//│ ╙──      	                                                      ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
+//│ ║        	                                    ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
+//│ ╙──      	                 ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
+//│ ║        	                                                                     ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
+//│ ╙──      	                                                  ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
+//│ ║        	                             ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
+//│ ╙──      	                      ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
+//│ ║        	                                                       ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
+//│ ╙──      	                                                ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ║        	                           ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ╙──      	                       ^
+//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
+//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ║        	                                                  ^
+//│ ╟── does not correspond to opening angle bracket
+//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ╙──      	                                              ^
 //│ ╔══[PARSE ERROR] Unmatched opening angle bracket
-//│ ║  l.17: 	let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
-//│ ║        	                                           ^
+//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ║        	                                         ^
 //│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator
-//│ |T|>>|Temp|
-//│ Parsed: {>> (T,) (Temp,)}
+//│ |Temp|‹|T|>>|›|MutArray|
+//│ ╔══[PARSE ERROR] Unexpected end of angle bracket section; an expression was expected here
+//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ╙──      	                                                  ^
+//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
+//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
+//│ ╙──      	                                 ^^^^^^^^^^^^^^^^^
+//│ Parsed: {Temp‹>>[(T,), (undefined,)]› (MutArray,)}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index c992b4a057..1f6d6c2d47 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
 let hello: unit => unit
-let add: number => number => number
-let sub: number => number => number
+let add: (number) => ((number) => (number))
+let sub: (number) => ((number) => (number))
 let foo: unit => number
-let id: anything => anything
-let odd: number => bool
-let isnull: anything => bool
+let id: (anything) => (anything)
+let odd: (number) => (bool)
+let isnull: (anything) => (bool)
 let bar: unit => anything
-let nu: null => null
-let un: undefined => undefined
+let nu: (null) => (null)
+let un: (undefined) => (undefined)
 let fail: unit => nothing
 let create: unit => object
-let pa: number => number
-let wtf: anything => unit
+let pa: (number) => (number)
+let wtf: (anything) => (unit)
 class Foooooo(ooooooo: number)
-let inn: Foooooo => unit
+let inn: (Foooooo) => (unit)
 let out: unit => Foooooo
 trait Barrrrrrrrr(rrrrrrr: number)
-let inn2: Barrrrrrrrr => unit
+let inn2: (Barrrrrrrrr) => (unit)
 let out2: unit => Barrrrrrrrr
-//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |number| |=>| |number| |=>| |number|↵|#let| |sub|#:| |number| |=>| |number| |=>| |number|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |anything| |=>| |anything|↵|#let| |odd|#:| |number| |=>| |bool|↵|#let| |isnull|#:| |anything| |=>| |bool|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |null| |=>| |null|↵|#let| |un|#:| |undefined| |=>| |undefined|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |number| |=>| |number|↵|#let| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#let| |inn|#:| |Foooooo| |=>| |unit|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#let| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo(ooooooo: number,) {}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
+//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |(|number|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |sub|#:| |(|number|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |(|anything|)| |=>| |(|anything|)|↵|#let| |odd|#:| |(|number|)| |=>| |(|bool|)|↵|#let| |isnull|#:| |(|anything|)| |=>| |(|bool|)|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |(|null|)| |=>| |(|null|)|↵|#let| |un|#:| |(|undefined|)| |=>| |(|undefined|)|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |(|number|)| |=>| |(|number|)|↵|#let| |wtf|#:| |(|anything|)| |=>| |(|unit|)|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#let| |inn|#:| |(|Foooooo|)| |=>| |(|unit|)|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#let| |inn2|#:| |(|Barrrrrrrrr|)| |=>| |(|unit|)|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> (number -> (number,),); fun sub: [] -> number -> (number -> (number,),); fun foo: [] -> unit -> number; fun id: [] -> anything -> (anything,); fun odd: [] -> number -> (bool,); fun isnull: [] -> anything -> (bool,); fun bar: [] -> unit -> anything; fun nu: [] -> null -> (null,); fun un: [] -> undefined -> (undefined,); fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> (number,); fun wtf: [] -> anything -> (unit,); class Foooooo(ooooooo: number,) {}; fun inn: [] -> Foooooo -> (unit,); fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> Barrrrrrrrr -> (unit,); fun out2: [] -> unit -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index 61149ba4a7..dc7bf89637 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,9 +1,9 @@
 :NewParser
 :ParseOnly
-class Student(name: string, isFriend: Student => bool, addScore: string => number => unit, getID: unit => number)
-class Foo<T>(bar: T => unit)
-class EZ(inc: number => number)
+class Student(name: string, isFriend: (Student) => (bool), addScore: (string) => ((number) => (unit)), getID: unit => number)
+class Foo<T>(bar: (T) => (unit))
+class EZ(inc: (number) => (number))
 class Outer
-class TTT<T>(ttt: T => T, ttt2: T => T)
-//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |Student| |=>| |bool|,| |addScore|#:| |string| |=>| |number| |=>| |unit|,| |getID|#:| |unit| |=>| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |T| |=>| |unit|)|↵|#class| |EZ|(|inc|#:| |number| |=>| |number|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|,| |ttt2|#:| |T| |=>| |T|)|
-//│ Parsed: {class Student(name: string, isFriend: Student, => bool, addScore: string, => number, => unit, getID: unit, => number,) {}; class Foo[T](bar: T, => unit,) {}; class EZ(inc: number, => number,) {}; class Outer() {}; class TTT[T](ttt: T, => T, ttt2: T, => T,) {}}
+class TTT<T>(ttt: (T) => (T), ttt2: (T) => (T))
+//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |(|Student|)| |=>| |(|bool|)|,| |addScore|#:| |(|string|)| |=>| |(|(|number|)| |=>| |(|unit|)|)|,| |getID|#:| |unit| |=>| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |(|T|)| |=>| |(|unit|)|)|↵|#class| |EZ|(|inc|#:| |(|number|)| |=>| |(|number|)|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |(|T|)| |=>| |(|T|)|,| |ttt2|#:| |(|T|)| |=>| |(|T|)|)|
+//│ Parsed: {class Student(name: string, isFriend: Student, => '(' bool, ')', addScore: string, => '(' number, => '(' unit, ')', ')', getID: unit, => number,) {}; class Foo[T](bar: T, => '(' unit, ')',) {}; class EZ(inc: number, => '(' number, ')',) {}; class Outer() {}; class TTT[T](ttt: T, => '(' T, ')', ttt2: T, => '(' T, ')',) {}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index a9ce8f67b9..0a08cd599d 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-let pass: int => bool
+let pass: (int) => (bool)
 let stop: unit => int
-let g: int => int
-//│ |#let| |pass|#:| |int| |=>| |bool|↵|#let| |stop|#:| |unit| |=>| |int|↵|#let| |g|#:| |int| |=>| |int|
-//│ Parsed: {fun pass: [] -> int -> bool; fun stop: [] -> unit -> int; fun g: [] -> int -> int}
+let g: (int) => (int)
+//│ |#let| |pass|#:| |(|int|)| |=>| |(|bool|)|↵|#let| |stop|#:| |unit| |=>| |int|↵|#let| |g|#:| |(|int|)| |=>| |(|int|)|
+//│ Parsed: {fun pass: [] -> int -> (bool,); fun stop: [] -> unit -> int; fun g: [] -> int -> (int,)}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 5e2275ddbb..086fde75e7 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -2,7 +2,7 @@
 :ParseOnly
 class A(foo: unit => unit)
 class B: A
-class C<T>(set: T => unit, get: unit => T)
+class C<T>(set: (T) => (unit), get: unit => T)
 class D: C<number>
 trait Wu(x: bool)
 class WuWu(y: bool): Wu
@@ -10,12 +10,12 @@ trait WuWuWu(z: bool): WuWu
 trait Never(w: unit => nothing): WuWuWu
 class VG<T>(x: T)
 class Home<T>(y: T): VG<string>
-trait O<I>(xx: I => I)
-class OR<R>(xx: R => R): O<R>
+trait O<I>(xx: (I) => (I))
+class OR<R>(xx: (R) => (R)): O<R>
 namespace Five {
   class ROTK(wu: string)
   class Y: Five'ROTK
 }
 class Y: Five'ROTK
-//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |ROTK|(|wu|#:| |string|)|↵|#class| |Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
-//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace Five(): {class ROTK(wu: string,) {}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |(|T|)| |=>| |(|unit|)|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |(|I|)| |=>| |(|I|)|)|↵|#class| |OR|‹|R|›|(|xx|#:| |(|R|)| |=>| |(|R|)|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |ROTK|(|wu|#:| |string|)|↵|#class| |Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
+//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => '(' unit, ')', get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => '(' I, ')',): {}; class OR[R](xx: R, => '(' R, ')',): O‹R› {}; namespace Five(): {class ROTK(wu: string,) {}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index 083fbcb028..f8d442220d 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-let h1: number => number => number => number
-let h2: string => unit => string
-let h3: number => number => number => number => number => number
-//│ |#let| |h1|#:| |number| |=>| |number| |=>| |number| |=>| |number|↵|#let| |h2|#:| |string| |=>| |unit| |=>| |string|↵|#let| |h3|#:| |number| |=>| |number| |=>| |number| |=>| |number| |=>| |number| |=>| |number|
-//│ Parsed: {fun h1: [] -> number -> number -> number -> number; fun h2: [] -> string -> unit -> string; fun h3: [] -> number -> number -> number -> number -> number -> number}
+let h1: ((number) => (number)) => ((number) => (number))
+let h2: (string) => (unit => string)
+let h3: ((number) => (number)) => (((number) => (number)) => ((number) => (number)))
+//│ |#let| |h1|#:| |(|(|number|)| |=>| |(|number|)|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |h2|#:| |(|string|)| |=>| |(|unit| |=>| |string|)|↵|#let| |h3|#:| |(|(|number|)| |=>| |(|number|)|)| |=>| |(|(|(|number|)| |=>| |(|number|)|)| |=>| |(|(|number|)| |=>| |(|number|)|)|)|
+//│ Parsed: {fun h1: [] -> (number -> (number,)) -> (number -> (number,),); fun h2: [] -> string -> (unit -> string,); fun h3: [] -> (number -> (number,)) -> ((number -> (number,)) -> (number -> (number,),),)}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 7a7e4511a4..cf0c30a365 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -1,16 +1,16 @@
 :NewParser
 :ParseOnly
-trait IFoo(a: string, b: number => number, c: unit => bool, d: string => unit)
-trait II<T>(test: T => number)
+trait IFoo(a: string, b: (number) => (number), c: unit => bool, d: (string) => (unit))
+trait II<T>(test: (T) => (number))
 let create: unit => (v: number)
-let get: (t: string) => string
-trait IEvent(callback: unit => number => unit)
-trait SearchFunc(__call: string => string => bool)
-trait StringArray(__index: number => string)
-trait Counter(__call: number => string, interval: number, reset: unit => unit)
-trait Simple(a: number, b: bool => string)
+let get: ((t: string)) => (string)
+trait IEvent(callback: (unit) => ((number) => (unit)))
+trait SearchFunc(__call: (string) => ((string) => (bool)))
+trait StringArray(__index: (number) => (string))
+trait Counter(__call: (number) => (string), interval: number, reset: unit => unit)
+trait Simple(a: number, b: (bool) => (string))
 trait Simple2<T>(abc: T)
 trait Next: Simple
-trait TTT<T>(ttt: T => T)
-//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |number| |=>| |number|,| |c|#:| |unit| |=>| |bool|,| |d|#:| |string| |=>| |unit|)|↵|#trait| |II|‹|T|›|(|test|#:| |T| |=>| |number|)|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|)|↵|#let| |get|#:| |(|t|#:| |string|)| |=>| |string|↵|#trait| |IEvent|(|callback|#:| |unit| |=>| |number| |=>| |unit|)|↵|#trait| |SearchFunc|(|__call|#:| |string| |=>| |string| |=>| |bool|)|↵|#trait| |StringArray|(|__index|#:| |number| |=>| |string|)|↵|#trait| |Counter|(|__call|#:| |number| |=>| |string|,| |interval|#:| |number|,| |reset|#:| |unit| |=>| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |bool| |=>| |string|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|)|
-//│ Parsed: {trait IFoo(a: string, b: number, => number, c: unit, => bool, d: string, => unit,): {}; trait II[T](test: T, => number,): {}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(callback: unit, => number, => unit,): {}; trait SearchFunc(__call: string, => string, => bool,): {}; trait StringArray(__index: number, => string,): {}; trait Counter(__call: number, => string, interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => string,): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => T,): {}}
+trait TTT<T>(ttt: (T) => (T))
+//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |(|number|)| |=>| |(|number|)|,| |c|#:| |unit| |=>| |bool|,| |d|#:| |(|string|)| |=>| |(|unit|)|)|↵|#trait| |II|‹|T|›|(|test|#:| |(|T|)| |=>| |(|number|)|)|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|)|↵|#let| |get|#:| |(|(|t|#:| |string|)|)| |=>| |(|string|)|↵|#trait| |IEvent|(|callback|#:| |(|unit|)| |=>| |(|(|number|)| |=>| |(|unit|)|)|)|↵|#trait| |SearchFunc|(|__call|#:| |(|string|)| |=>| |(|(|string|)| |=>| |(|bool|)|)|)|↵|#trait| |StringArray|(|__index|#:| |(|number|)| |=>| |(|string|)|)|↵|#trait| |Counter|(|__call|#:| |(|number|)| |=>| |(|string|)|,| |interval|#:| |number|,| |reset|#:| |unit| |=>| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |(|bool|)| |=>| |(|string|)|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |(|T|)| |=>| |(|T|)|)|
+//│ Parsed: {trait IFoo(a: string, b: number, => '(' number, ')', c: unit, => bool, d: string, => '(' unit, ')',): {}; trait II[T](test: T, => '(' number, ')',): {}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> (string,); trait IEvent(callback: unit, => '(' number, => '(' unit, ')', ')',): {}; trait SearchFunc(__call: string, => '(' string, => '(' bool, ')', ')',): {}; trait StringArray(__index: number, => '(' string, ')',): {}; trait Counter(__call: number, => '(' string, ')', interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => '(' string, ')',): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => '(' T, ')',): {}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index bbbe8eb4c5..06ad21c2ea 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,17 +1,17 @@
 :NewParser
 :ParseOnly
-let extend: T => U => (T) & (U)
-let foo: (T) & (U) => unit
-let over: (number => string) & (object => string) => string
+let extend: (T) => ((U) => ((T) & (U)))
+let foo: ((T) & (U)) => (unit)
+let over: (((number) => (string)) & ((object) => (string))) => (string)
 trait IA(x: number)
 trait IB(y: number)
-let iii: (IA) & (IB) => (IA) & (IB)
-let uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
-let iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
-let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
-let tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
+let iii: ((IA) & (IB)) => ((IA) & (IB))
+let uu: (((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))) => (((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)))
+let iiii: (((U) & (T)) & (V)) => (((U) & (T)) & (V))
+let arr: ((MutArray<U>) & (MutArray<T>)) => ((MutArray<U>) & (MutArray<T>))
+let tt: (((U, T, )) & ((V, V, ))) => (((U, T, )) & ((V, V, )))
 class A
 class B
-let inter: (A) & (B) => (A) & (B)
-//│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
-//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
+let inter: ((A) & (B)) => ((A) & (B))
+//│ |#let| |extend|#:| |(|T|)| |=>| |(|(|U|)| |=>| |(|(|T|)| |&| |(|U|)|)|)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|)| |=>| |(|unit|)|↵|#let| |over|#:| |(|(|(|number|)| |=>| |(|string|)|)| |&| |(|(|object|)| |=>| |(|string|)|)|)| |=>| |(|string|)|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#let| |iii|#:| |(|(|IA|)| |&| |(|IB|)|)| |=>| |(|(|IA|)| |&| |(|IB|)|)|↵|#let| |uu|#:| |(|(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)| |=>| |(|(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|↵|#let| |iiii|#:| |(|(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)| |=>| |(|(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|↵|#let| |arr|#:| |(|(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)| |=>| |(|(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|↵|#let| |tt|#:| |(|(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)| |=>| |(|(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|↵|#class| |A|↵|#class| |B|↵|#let| |inter|#:| |(|(|A|)| |&| |(|B|)|)| |=>| |(|(|A|)| |&| |(|B|)|)|
+//│ Parsed: {fun extend: [] -> T -> (U -> ((T,) & (U,),),); fun foo: [] -> ((T,) & (U,)) -> (unit,); fun over: [] -> ((number -> (string,),) & (object -> (string,),)) -> (string,); trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,),); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,),); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],),); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),),); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,),)}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index f0a5dfe0dc..0b26159ee5 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,6 +1,6 @@
 :NewParser
 :ParseOnly
-let multi1: number => number
+let multi1: (number) => (number)
 let multi3: unit => unit
 class Foo: Base
 trait AnotherBase(y: string)
@@ -9,10 +9,10 @@ namespace N {
   let g: unit => unit
   let h: unit => unit
 }
-let multi2: string => string
+let multi2: (string) => (string)
 let multi4: unit => unit
 trait Base(a: number)
 class AnotherFoo: AnotherBase
 let multi5: unit => unit
-//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
-//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(a: number,): {}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
+//│ |#let| |multi1|#:| |(|number|)| |=>| |(|number|)|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |(|string|)| |=>| |(|string|)|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
+//│ Parsed: {fun multi1: [] -> number -> (number,); fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> (string,); fun multi4: [] -> unit -> unit; trait Base(a: number,): {}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index dc2cd60edb..d91556d537 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
 namespace N1 {
-  let f: anything => number
-  let ff: anything => number
+  let f: (anything) => (number)
+  let ff: (anything) => (number)
   class C(f: unit => unit)
   trait I(f: unit => number)
   namespace N2 {
-    let fff: bool => number
-    let gg: N1'C => N1'C
+    let fff: (bool) => (number)
+    let gg: (N1'C) => (N1'C)
     class BBB: N1'C
   }
 }
 namespace AA {
-  let f: anything => string
+  let f: (anything) => (string)
   class C(f: unit => unit)
   trait I(f: unit => number)
   namespace N2 {
   }
 }
-let f1: N1'C => N1'C
-let f2: AA'C => AA'C
-//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
+let f1: (N1'C) => (N1'C)
+let f2: (AA'C) => (AA'C)
+//│ |#namespace| |N1| |{|→|#let| |f|#:| |(|anything|)| |=>| |(|number|)|↵|#let| |ff|#:| |(|anything|)| |=>| |(|number|)|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |(|bool|)| |=>| |(|number|)|↵|#let| |gg|#:| |(|N1'C|)| |=>| |(|N1'C|)|↵|#class| |BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |(|anything|)| |=>| |(|string|)|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |(|N1'C|)| |=>| |(|N1'C|)|↵|#let| |f2|#:| |(|AA'C|)| |=>| |(|AA'C|)|
+//│ Parsed: {namespace N1(): {fun f: [] -> anything -> (number,); fun ff: [] -> anything -> (number,); class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> (number,); fun gg: [] -> N1'C -> (N1'C,); class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> (string,); class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> (N1'C,); fun f2: [] -> AA'C -> (AA'C,)}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 9a4119d460..b09c51db67 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,19 +1,19 @@
 :NewParser
 :ParseOnly
-let buildName: string => (string) | (undefined) => string
-let buildName2: string => (string) | (undefined) => string
-let buildName3: string => MutArray<string> => string
-let buildName4: string => MutArray<anything> => string
+let buildName: (string) => (((string) | (undefined)) => (string))
+let buildName2: (string) => (((string) | (undefined)) => (string))
+let buildName3: (string) => ((MutArray<string>) => (string))
+let buildName4: (string) => ((MutArray<anything>) => (string))
 trait SquareConfig(color: (string) | (undefined), width: (number) | (undefined))
-let did: number => (number => number) | (undefined) => number
-let getOrElse: (MutArray<object>) | (undefined) => object
+let did: (number) => ((((number) => (number)) | (undefined)) => (number))
+let getOrElse: ((MutArray<object>) | (undefined)) => (object)
 class ABC
-let testABC: (ABC) | (undefined) => unit
-let testSquareConfig: (SquareConfig) | (undefined) => unit
-let err: ((number, string, )) | (undefined) => unit
-let toStr: ((number) | (bool)) | (undefined) => string
-let boo: ((T) & (U)) | (undefined) => unit
+let testABC: ((ABC) | (undefined)) => (unit)
+let testSquareConfig: ((SquareConfig) | (undefined)) => (unit)
+let err: (((number, string, )) | (undefined)) => (unit)
+let toStr: (((number) | (bool)) | (undefined)) => (string)
+let boo: (((T) & (U)) | (undefined)) => (unit)
 class B<T>(b: T)
-let boom: (B<nothing>) | (undefined) => anything
-//│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
-//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
+let boom: ((B<nothing>) | (undefined)) => (anything)
+//│ |#let| |buildName|#:| |(|string|)| |=>| |(|(|(|string|)| ||| |(|undefined|)|)| |=>| |(|string|)|)|↵|#let| |buildName2|#:| |(|string|)| |=>| |(|(|(|string|)| ||| |(|undefined|)|)| |=>| |(|string|)|)|↵|#let| |buildName3|#:| |(|string|)| |=>| |(|(|MutArray|‹|string|›|)| |=>| |(|string|)|)|↵|#let| |buildName4|#:| |(|string|)| |=>| |(|(|MutArray|‹|anything|›|)| |=>| |(|string|)|)|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#let| |did|#:| |(|number|)| |=>| |(|(|(|(|number|)| |=>| |(|number|)|)| ||| |(|undefined|)|)| |=>| |(|number|)|)|↵|#let| |getOrElse|#:| |(|(|MutArray|‹|object|›|)| ||| |(|undefined|)|)| |=>| |(|object|)|↵|#class| |ABC|↵|#let| |testABC|#:| |(|(|ABC|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#let| |testSquareConfig|#:| |(|(|SquareConfig|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#let| |err|#:| |(|(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#let| |toStr|#:| |(|(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)| |=>| |(|string|)|↵|#let| |boo|#:| |(|(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#let| |boom|#:| |(|(|B|‹|nothing|›|)| ||| |(|undefined|)|)| |=>| |(|anything|)|
+//│ Parsed: {fun buildName: [] -> string -> (((string,) | (undefined,)) -> (string,),); fun buildName2: [] -> string -> (((string,) | (undefined,)) -> (string,),); fun buildName3: [] -> string -> (MutArray[string] -> (string,),); fun buildName4: [] -> string -> (MutArray[anything] -> (string,),); trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> (((number -> (number,),) | (undefined,)) -> (number,),); fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> (object,); class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> (unit,); fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> (unit,); fun err: [] -> (((number, string,),) | (undefined,)) -> (unit,); fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> (string,); fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> (unit,); class B[T](b: T,) {}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> (anything,)}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 7f3424c976..8bd1c735ff 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,48 +1,48 @@
 :NewParser
 :ParseOnly
-let f: (number => string) & (string => string)
-class M(foo: (number => string) & (string => string))
-let app: (string => unit => number => unit) & (string => unit => string => unit)
-let create: (number => unit => bool) & (bool => unit => bool)
-let g0: (MutArray<string> => string) & (MutArray<object> => string)
-let db: (number => MutArray<number>) & (object => MutArray<number>)
+let f: ((number) => (string)) & ((string) => (string))
+class M(foo: ((number) => (string)) & ((string) => (string)))
+let app: (((string) => (unit)) => ((number) => (unit))) & (((string) => (unit)) => ((string) => (unit)))
+let create: ((number) => (unit => bool)) & ((bool) => (unit => bool))
+let g0: ((MutArray<string>) => (string)) & ((MutArray<object>) => (string))
+let db: ((number) => (MutArray<number>)) & ((object) => (MutArray<number>))
 class N
-let id: (M => unit) & (N => unit)
-let tst: ((z: number) => (y: string)) & ((z: bool) => (y: string))
-let op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
-let swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
-let u: ((number) | (bool) => string) & (object => string)
-let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+let id: ((M) => (unit)) & ((N) => (unit))
+let tst: (((z: number)) => ((y: string))) & (((z: bool)) => ((y: string)))
+let op: ((number) => (((number) | (undefined)) => (unit))) & ((number) => (((bool) | (undefined)) => (unit)))
+let swap: (((number, string, )) => ((number, string, ))) & (((string, number, )) => ((number, string, )))
+let u: (((number) | (bool)) => (string)) & ((object) => (string))
+let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
 namespace XX {
-  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
+  let f: (T) => ((anything) => (string)) /* warning: the overload of function f is not supported yet. */
 }
-class WWW(F: T => anything /* warning: the overload of function F is not supported yet. */)
+class WWW(F: (T) => (anything) /* warning: the overload of function F is not supported yet. */)
 let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(|foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|)|↵|#let| |app|#:| |(|string| |=>| |unit| |=>| |number| |=>| |unit|)| |&| |(|string| |=>| |unit| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|)| |=>| |(|y|#:| |string|)|)| |&| |(|(|z|#:| |bool|)| |=>| |(|y|#:| |string|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+//│ |#let| |f|#:| |(|(|number|)| |=>| |(|string|)|)| |&| |(|(|string|)| |=>| |(|string|)|)|↵|#class| |M|(|foo|#:| |(|(|number|)| |=>| |(|string|)|)| |&| |(|(|string|)| |=>| |(|string|)|)|)|↵|#let| |app|#:| |(|(|(|string|)| |=>| |(|unit|)|)| |=>| |(|(|number|)| |=>| |(|unit|)|)|)| |&| |(|(|(|string|)| |=>| |(|unit|)|)| |=>| |(|(|string|)| |=>| |(|unit|)|)|)|↵|#let| |create|#:| |(|(|number|)| |=>| |(|unit| |=>| |bool|)|)| |&| |(|(|bool|)| |=>| |(|unit| |=>| |bool|)|)|↵|#let| |g0|#:| |(|(|MutArray|‹|string|›|)| |=>| |(|string|)|)| |&| |(|(|MutArray|‹|object|›|)| |=>| |(|string|)|)|↵|#let| |db|#:| |(|(|number|)| |=>| |(|MutArray|‹|number|›|)|)| |&| |(|(|object|)| |=>| |(|MutArray|‹|number|›|)|)|↵|#class| |N|↵|#let| |id|#:| |(|(|M|)| |=>| |(|unit|)|)| |&| |(|(|N|)| |=>| |(|unit|)|)|↵|#let| |tst|#:| |(|(|(|z|#:| |number|)|)| |=>| |(|(|y|#:| |string|)|)|)| |&| |(|(|(|z|#:| |bool|)|)| |=>| |(|(|y|#:| |string|)|)|)|↵|#let| |op|#:| |(|(|number|)| |=>| |(|(|(|number|)| ||| |(|undefined|)|)| |=>| |(|unit|)|)|)| |&| |(|(|number|)| |=>| |(|(|(|bool|)| ||| |(|undefined|)|)| |=>| |(|unit|)|)|)|↵|#let| |swap|#:| |(|(|(|number|,| |string|,| |)|)| |=>| |(|(|number|,| |string|,| |)|)|)| |&| |(|(|(|string|,| |number|,| |)|)| |=>| |(|(|number|,| |string|,| |)|)|)|↵|#let| |u|#:| |(|(|(|number|)| ||| |(|bool|)|)| |=>| |(|string|)|)| |&| |(|(|object|)| |=>| |(|string|)|)|↵|#let| |doSome|#:| |(|anything|)| |=>| |(|unit|)| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |(|T|)| |=>| |(|(|anything|)| |=>| |(|string|)|)| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |(|T|)| |=>| |(|anything|)| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ╙──      	                                       ^
+//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
+//│ ╙──      	                                           ^
 //│ ╔══[PARSE ERROR] Unexpected operator in expression position
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ╙──      	                                                                                               ^^
+//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
+//│ ╙──      	                                                                                                   ^^
 //│ ╔══[PARSE ERROR] Unexpected newline in expression position
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ║        	                                                                                                 ^
+//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
+//│ ║        	                                                                                                     ^
 //│ ║  l.16: 	namespace XX {
 //│ ╙──      	
 //│ ╔══[PARSE ERROR] Unexpected 'namespace' keyword in expression position
 //│ ║  l.16: 	namespace XX {
 //│ ╙──      	^^^^^^^^^
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ║        	                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
+//│ ║        	                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.16: 	namespace XX {
 //│ ╙──      	^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
 //│ ║  l.16: 	namespace XX {
 //│ ║        	             ^
-//│ ║  l.17: 	  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.17: 	  let f: (T) => ((anything) => (string)) /* warning: the overload of function f is not supported yet. */
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.18: 	}
 //│ ╙──      	^
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> (string -> unit -> number -> unit,) & (string -> unit -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
+//│ Parsed: {fun f: [] -> (number -> (string,),) & (string -> (string,),); class M(foo: & (number, => '(' string, ')',) (string, => '(' string, ')',),) {}; fun app: [] -> ((string -> (unit,)) -> (number -> (unit,),),) & ((string -> (unit,)) -> (string -> (unit,),),); fun create: [] -> (number -> (unit -> bool,),) & (bool -> (unit -> bool,),); fun g0: [] -> (MutArray[string] -> (string,),) & (MutArray[object] -> (string,),); fun db: [] -> (number -> (MutArray[number],),) & (object -> (MutArray[number],),); class N() {}; fun id: [] -> (M -> (unit,),) & (N -> (unit,),); fun tst: [] -> ((z: number,) -> ((y: string,),),) & ((z: bool,) -> ((y: string,),),); fun op: [] -> (number -> (((number,) | (undefined,)) -> (unit,),),) & (number -> (((bool,) | (undefined,)) -> (unit,),),); fun swap: [] -> ((number, string,) -> ((number, string,),),) & ((string, number,) -> ((number, string,),),); fun u: [] -> (((number,) | (bool,)) -> (string,),) & (object -> (string,),); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 753f794b68..a1657ae958 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,18 +1,18 @@
 :NewParser
 :ParseOnly
-let key: (string, bool, ) => string
-let value: (string, bool, ) => bool
-let third: (number, number, number, ) => number
-let vec2: number => number => (number, number, )
-let twoFunctions: (number => number, number => number, ) => number => number
-let tupleIt: string => (unit => string, )
-let s: bool => ((string) | (number), (number) | (bool), )
-let s2: (bool, (string) | (number), ) => (string) | (number)
-let ex: T => U => (T, U, (T) & (U), )
-let foo: ((T) & (U), ) => unit
-let conv: (y: number) => ((y: number), (z: string), )
+let key: ((string, bool, )) => (string)
+let value: ((string, bool, )) => (bool)
+let third: ((number, number, number, )) => (number)
+let vec2: (number) => ((number) => ((number, number, )))
+let twoFunctions: (((number) => (number), (number) => (number), )) => ((number) => (number))
+let tupleIt: (string) => ((unit => string, ))
+let s: (bool) => (((string) | (number), (number) | (bool), ))
+let s2: ((bool, (string) | (number), )) => ((string) | (number))
+let ex: (T) => ((U) => ((T, U, (T) & (U), )))
+let foo: (((T) & (U), )) => (unit)
+let conv: ((y: number)) => (((y: number), (z: string), ))
 class A(x: number)
 class B
-let swap: (A, B, ) => (B, A, )
-//│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|)| |=>| |(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
-//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A(x: number,) {}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
+let swap: ((A, B, )) => ((B, A, ))
+//│ |#let| |key|#:| |(|(|string|,| |bool|,| |)|)| |=>| |(|string|)|↵|#let| |value|#:| |(|(|string|,| |bool|,| |)|)| |=>| |(|bool|)|↵|#let| |third|#:| |(|(|number|,| |number|,| |number|,| |)|)| |=>| |(|number|)|↵|#let| |vec2|#:| |(|number|)| |=>| |(|(|number|)| |=>| |(|(|number|,| |number|,| |)|)|)|↵|#let| |twoFunctions|#:| |(|(|(|number|)| |=>| |(|number|)|,| |(|number|)| |=>| |(|number|)|,| |)|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |tupleIt|#:| |(|string|)| |=>| |(|(|unit| |=>| |string|,| |)|)|↵|#let| |s|#:| |(|bool|)| |=>| |(|(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|)|↵|#let| |s2|#:| |(|(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)| |=>| |(|(|string|)| ||| |(|number|)|)|↵|#let| |ex|#:| |(|T|)| |=>| |(|(|U|)| |=>| |(|(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|)|)|↵|#let| |foo|#:| |(|(|(|T|)| |&| |(|U|)|,| |)|)| |=>| |(|unit|)|↵|#let| |conv|#:| |(|(|y|#:| |number|)|)| |=>| |(|(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#let| |swap|#:| |(|(|A|,| |B|,| |)|)| |=>| |(|(|B|,| |A|,| |)|)|
+//│ Parsed: {fun key: [] -> (string, bool,) -> (string,); fun value: [] -> (string, bool,) -> (bool,); fun third: [] -> (number, number, number,) -> (number,); fun vec2: [] -> number -> (number -> ((number, number,),),); fun twoFunctions: [] -> (number -> (number,), number -> (number,),) -> (number -> (number,),); fun tupleIt: [] -> string -> ((unit -> string,),); fun s: [] -> bool -> (((string,) | (number,), (number,) | (bool,),),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,),); fun ex: [] -> T -> (U -> ((T, U, (T,) & (U,),),),); fun foo: [] -> ((T,) & (U,)) -> (unit,); fun conv: [] -> (y: number,) -> (((y: number,), (z: string,),),); class A(x: number,) {}; class B() {}; fun swap: [] -> (A, B,) -> ((B, A,),)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index b416bd291d..938983dded 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,17 +1,17 @@
 :NewParser
 :ParseOnly
-let inc: T => number
-class CC<T>(print: T => unit)
-let con: T => U
-class Printer<T>(print: T => unit)
-let setStringPrinter: Printer<string> => unit
+let inc: (T) => (number)
+class CC<T>(print: (T) => (unit))
+let con: (T) => (U)
+class Printer<T>(print: (T) => (unit))
+let setStringPrinter: (Printer<string>) => (unit)
 let getStringPrinter: unit => Printer<string>
-let foo: Printer<T> => T => T
-let foo2: Printer<T> => T => T
-class F<T>(x: T, GG: U => T)
-trait I<T>(x: T, GG: U => T)
-class FFF<T>(fff: T => unit)
-let fff: FFF<string> => string => unit
+let foo: (Printer<T>) => ((T) => (T))
+let foo2: (Printer<T>) => ((T) => (T))
+class F<T>(x: T, GG: (U) => (T))
+trait I<T>(x: T, GG: (U) => (T))
+class FFF<T>(fff: (T) => (unit))
+let fff: (FFF<string>) => ((string) => (unit))
 let getFFF: unit => FFF<number>
-//│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |T| |=>| |unit|)|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> T -> number; class CC[T](print: T, => unit,) {}; fun con: [] -> T -> U; class Printer[T](print: T, => unit,) {}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T](x: T, GG: U, => T,) {}; trait I[T](x: T, GG: U, => T,): {}; class FFF[T](fff: T, => unit,) {}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
+//│ |#let| |inc|#:| |(|T|)| |=>| |(|number|)|↵|#class| |CC|‹|T|›|(|print|#:| |(|T|)| |=>| |(|unit|)|)|↵|#let| |con|#:| |(|T|)| |=>| |(|U|)|↵|#class| |Printer|‹|T|›|(|print|#:| |(|T|)| |=>| |(|unit|)|)|↵|#let| |setStringPrinter|#:| |(|Printer|‹|string|›|)| |=>| |(|unit|)|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |(|Printer|‹|T|›|)| |=>| |(|(|T|)| |=>| |(|T|)|)|↵|#let| |foo2|#:| |(|Printer|‹|T|›|)| |=>| |(|(|T|)| |=>| |(|T|)|)|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|U|)| |=>| |(|T|)|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|U|)| |=>| |(|T|)|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |(|T|)| |=>| |(|unit|)|)|↵|#let| |fff|#:| |(|FFF|‹|string|›|)| |=>| |(|(|string|)| |=>| |(|unit|)|)|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> T -> (number,); class CC[T](print: T, => '(' unit, ')',) {}; fun con: [] -> T -> (U,); class Printer[T](print: T, => '(' unit, ')',) {}; fun setStringPrinter: [] -> Printer[string] -> (unit,); fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> (T -> (T,),); fun foo2: [] -> Printer[T] -> (T -> (T,),); class F[T](x: T, GG: U, => '(' T, ')',) {}; trait I[T](x: T, GG: U, => '(' T, ')',): {}; class FFF[T](fff: T, => '(' unit, ')',) {}; fun fff: [] -> FFF[string] -> (string -> (unit,),); fun getFFF: [] -> unit -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 14daeda466..34f66f32f3 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,11 +1,11 @@
 :NewParser
 :ParseOnly
-let getString: ((string) | (number)) | (bool) => string
-let test: bool => (string) | (number)
-let run: (number => number) | (number => string) => anything
-let get: (MutArray<number>) | (MutArray<string>) => unit
-let get2: ((string, string, )) | ((number, string, )) => string
-let typeVar: (T) | (U) => (T) | (U)
-let uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
-//│ |#let| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#let| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#let| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#let| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#let| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#let| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#let| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}
+let getString: (((string) | (number)) | (bool)) => (string)
+let test: (bool) => ((string) | (number))
+let run: (((number) => (number)) | ((number) => (string))) => (anything)
+let get: ((MutArray<number>) | (MutArray<string>)) => (unit)
+let get2: (((string, string, )) | ((number, string, ))) => (string)
+let typeVar: ((T) | (U)) => ((T) | (U))
+let uuuu: (((string) | (number)) | (bool)) => (((string) | (number)) | (bool))
+//│ |#let| |getString|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)| |=>| |(|string|)|↵|#let| |test|#:| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)|↵|#let| |run|#:| |(|(|(|number|)| |=>| |(|number|)|)| ||| |(|(|number|)| |=>| |(|string|)|)|)| |=>| |(|anything|)|↵|#let| |get|#:| |(|(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)| |=>| |(|unit|)|↵|#let| |get2|#:| |(|(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)| |=>| |(|string|)|↵|#let| |typeVar|#:| |(|(|T|)| ||| |(|U|)|)| |=>| |(|(|T|)| ||| |(|U|)|)|↵|#let| |uuuu|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)| |=>| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|
+//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> (string,); fun test: [] -> bool -> ((string,) | (number,),); fun run: [] -> ((number -> (number,),) | (number -> (string,),)) -> (anything,); fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> (unit,); fun get2: [] -> (((string, string,),) | ((number, string,),)) -> (string,); fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,),); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,),)}

From a4f0b122792203ca665639e23fe37f70d2a5d7a7 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 14:55:46 +0800
Subject: [PATCH 09/40] Fix error tup

---
 .../main/scala/ts2mls/types/Converter.scala   |   5 +-
 ts2mls/js/src/test/diff/Array.d.mls           | 102 +++---------------
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  |  26 ++---
 ts2mls/js/src/test/diff/ClassMember.d.mls     |  12 +--
 ts2mls/js/src/test/diff/Enum.d.mls            |   8 +-
 ts2mls/js/src/test/diff/Heritage.d.mls        |  10 +-
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   |  10 +-
 ts2mls/js/src/test/diff/InterfaceMember.d.mls |  22 ++--
 ts2mls/js/src/test/diff/Intersection.d.mls    |  22 ++--
 ts2mls/js/src/test/diff/MultiFiles.d.mls      |   8 +-
 ts2mls/js/src/test/diff/Namespace.d.mls       |  18 ++--
 ts2mls/js/src/test/diff/Optional.d.mls        |  28 ++---
 ts2mls/js/src/test/diff/Overload.d.mls        |  52 ++++-----
 ts2mls/js/src/test/diff/Tuple.d.mls           |  28 ++---
 ts2mls/js/src/test/diff/TypeParameter.d.mls   |  26 ++---
 ts2mls/js/src/test/diff/Union.d.mls           |  18 ++--
 16 files changed, 163 insertions(+), 232 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index f39f202bdb..dd4a32eea8 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -25,7 +25,10 @@ object Converter {
       // since functions can be defined by both `def` and `method`, it only returns the type of functions
       if (params.length == 0) s"${primitiveName("void")} => ${convert(res)}"
       else
-        params.foldRight(convert(res))((p, f) => s"(${convert(p)}) => ($f)")
+        params.foldRight(convert(res))((p, f) => p match {
+          case _: TSFunctionType => s"(${convert(p)}) => $f"
+          case _ => s"${convert(p)} => $f"
+        })
     case TSUnionType(lhs, rhs) => {
       val lres = convert(lhs)
       val rres = convert(rhs)
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index c4a463650e..377b900dd4 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,95 +1,23 @@
 :NewParser
 :ParseOnly
-let first: (MutArray<string>) => (string)
+let first: MutArray<string> => string
 let getZero3: unit => MutArray<number>
-let first2: (MutArray<(number) => (number)>) => ((number) => (number))
-let doEs: (MutArray<int>) => (MutArray<int>)
+let first2: MutArray<number => number> => number => number
+let doEs: MutArray<int> => MutArray<int>
 class C
 trait I(i: number)
-let doCs: (MutArray<C>) => (MutArray<C>)
-let doIs: (MutArray<I>) => (MutArray<I>)
-let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
-let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
-let translate: (MutArray<T>) => (MutArray<U>)
-let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
+let doCs: MutArray<C> => MutArray<C>
+let doIs: MutArray<I> => MutArray<I>
+let inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
+let clean: MutArray<(string, number, )> => MutArray<(string, number, )>
+let translate: MutArray<T> => MutArray<U>
+let uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
 class Temp<T>(x: T)
-let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
-let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.5: 	let first2: (MutArray<(number) => (number)>) => ((number) => (number))
-//│ ║       	                                           ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.5: 	let first2: (MutArray<(number) => (number)>) => ((number) => (number))
-//│ ╙──     	                     ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
-//│ ║        	                               ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
-//│ ╙──      	                    ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
-//│ ║        	                                                        ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.11: 	let inter: (MutArray<(U) & (T)>) => (MutArray<(U) & (T)>)
-//│ ╙──      	                                             ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
-//│ ║        	                                        ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
-//│ ╙──      	                    ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
-//│ ║        	                                                                          ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.12: 	let clean: (MutArray<(string, number, )>) => (MutArray<(string, number, )>)
-//│ ╙──      	                                                      ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
-//│ ║        	                                    ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
-//│ ╙──      	                 ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
-//│ ║        	                                                                     ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.14: 	let uu: (MutArray<(number) | (bool)>) => (MutArray<(number) | (bool)>)
-//│ ╙──      	                                                  ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
-//│ ║        	                             ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
-//│ ╙──      	                      ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
-//│ ║        	                                                       ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.16: 	let ta: (MutArray<Temp<bool>>) => (MutArray<Temp<bool>>)
-//│ ╙──      	                                                ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ║        	                           ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ╙──      	                       ^
-//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis
-//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ║        	                                                  ^
-//│ ╟── does not correspond to opening angle bracket
-//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ╙──      	                                              ^
+let ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
+let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
 //│ ╔══[PARSE ERROR] Unmatched opening angle bracket
-//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ║        	                                         ^
+//│ ║  l.17: 	let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
+//│ ║        	                                           ^
 //│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator
-//│ |Temp|‹|T|>>|›|MutArray|
-//│ ╔══[PARSE ERROR] Unexpected end of angle bracket section; an expression was expected here
-//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ╙──      	                                                  ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.17: 	let tat: (MutArray<Temp<T>>) => (MutArray<Temp<T>>)
-//│ ╙──      	                                 ^^^^^^^^^^^^^^^^^
-//│ Parsed: {Temp‹>>[(T,), (undefined,)]› (MutArray,)}
+//│ |T|>>|Temp|
+//│ Parsed: {>> (T,) (Temp,)}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 1f6d6c2d47..c992b4a057 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
 let hello: unit => unit
-let add: (number) => ((number) => (number))
-let sub: (number) => ((number) => (number))
+let add: number => number => number
+let sub: number => number => number
 let foo: unit => number
-let id: (anything) => (anything)
-let odd: (number) => (bool)
-let isnull: (anything) => (bool)
+let id: anything => anything
+let odd: number => bool
+let isnull: anything => bool
 let bar: unit => anything
-let nu: (null) => (null)
-let un: (undefined) => (undefined)
+let nu: null => null
+let un: undefined => undefined
 let fail: unit => nothing
 let create: unit => object
-let pa: (number) => (number)
-let wtf: (anything) => (unit)
+let pa: number => number
+let wtf: anything => unit
 class Foooooo(ooooooo: number)
-let inn: (Foooooo) => (unit)
+let inn: Foooooo => unit
 let out: unit => Foooooo
 trait Barrrrrrrrr(rrrrrrr: number)
-let inn2: (Barrrrrrrrr) => (unit)
+let inn2: Barrrrrrrrr => unit
 let out2: unit => Barrrrrrrrr
-//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |(|number|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |sub|#:| |(|number|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |(|anything|)| |=>| |(|anything|)|↵|#let| |odd|#:| |(|number|)| |=>| |(|bool|)|↵|#let| |isnull|#:| |(|anything|)| |=>| |(|bool|)|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |(|null|)| |=>| |(|null|)|↵|#let| |un|#:| |(|undefined|)| |=>| |(|undefined|)|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |(|number|)| |=>| |(|number|)|↵|#let| |wtf|#:| |(|anything|)| |=>| |(|unit|)|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#let| |inn|#:| |(|Foooooo|)| |=>| |(|unit|)|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#let| |inn2|#:| |(|Barrrrrrrrr|)| |=>| |(|unit|)|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> (number -> (number,),); fun sub: [] -> number -> (number -> (number,),); fun foo: [] -> unit -> number; fun id: [] -> anything -> (anything,); fun odd: [] -> number -> (bool,); fun isnull: [] -> anything -> (bool,); fun bar: [] -> unit -> anything; fun nu: [] -> null -> (null,); fun un: [] -> undefined -> (undefined,); fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> (number,); fun wtf: [] -> anything -> (unit,); class Foooooo(ooooooo: number,) {}; fun inn: [] -> Foooooo -> (unit,); fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> Barrrrrrrrr -> (unit,); fun out2: [] -> unit -> Barrrrrrrrr}
+//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |number| |=>| |number| |=>| |number|↵|#let| |sub|#:| |number| |=>| |number| |=>| |number|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |anything| |=>| |anything|↵|#let| |odd|#:| |number| |=>| |bool|↵|#let| |isnull|#:| |anything| |=>| |bool|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |null| |=>| |null|↵|#let| |un|#:| |undefined| |=>| |undefined|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |number| |=>| |number|↵|#let| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#let| |inn|#:| |Foooooo| |=>| |unit|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#let| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo(ooooooo: number,) {}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index dc7bf89637..61149ba4a7 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,9 +1,9 @@
 :NewParser
 :ParseOnly
-class Student(name: string, isFriend: (Student) => (bool), addScore: (string) => ((number) => (unit)), getID: unit => number)
-class Foo<T>(bar: (T) => (unit))
-class EZ(inc: (number) => (number))
+class Student(name: string, isFriend: Student => bool, addScore: string => number => unit, getID: unit => number)
+class Foo<T>(bar: T => unit)
+class EZ(inc: number => number)
 class Outer
-class TTT<T>(ttt: (T) => (T), ttt2: (T) => (T))
-//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |(|Student|)| |=>| |(|bool|)|,| |addScore|#:| |(|string|)| |=>| |(|(|number|)| |=>| |(|unit|)|)|,| |getID|#:| |unit| |=>| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |(|T|)| |=>| |(|unit|)|)|↵|#class| |EZ|(|inc|#:| |(|number|)| |=>| |(|number|)|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |(|T|)| |=>| |(|T|)|,| |ttt2|#:| |(|T|)| |=>| |(|T|)|)|
-//│ Parsed: {class Student(name: string, isFriend: Student, => '(' bool, ')', addScore: string, => '(' number, => '(' unit, ')', ')', getID: unit, => number,) {}; class Foo[T](bar: T, => '(' unit, ')',) {}; class EZ(inc: number, => '(' number, ')',) {}; class Outer() {}; class TTT[T](ttt: T, => '(' T, ')', ttt2: T, => '(' T, ')',) {}}
+class TTT<T>(ttt: T => T, ttt2: T => T)
+//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |Student| |=>| |bool|,| |addScore|#:| |string| |=>| |number| |=>| |unit|,| |getID|#:| |unit| |=>| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |T| |=>| |unit|)|↵|#class| |EZ|(|inc|#:| |number| |=>| |number|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|,| |ttt2|#:| |T| |=>| |T|)|
+//│ Parsed: {class Student(name: string, isFriend: Student, => bool, addScore: string, => number, => unit, getID: unit, => number,) {}; class Foo[T](bar: T, => unit,) {}; class EZ(inc: number, => number,) {}; class Outer() {}; class TTT[T](ttt: T, => T, ttt2: T, => T,) {}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index 0a08cd599d..a9ce8f67b9 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-let pass: (int) => (bool)
+let pass: int => bool
 let stop: unit => int
-let g: (int) => (int)
-//│ |#let| |pass|#:| |(|int|)| |=>| |(|bool|)|↵|#let| |stop|#:| |unit| |=>| |int|↵|#let| |g|#:| |(|int|)| |=>| |(|int|)|
-//│ Parsed: {fun pass: [] -> int -> (bool,); fun stop: [] -> unit -> int; fun g: [] -> int -> (int,)}
+let g: int => int
+//│ |#let| |pass|#:| |int| |=>| |bool|↵|#let| |stop|#:| |unit| |=>| |int|↵|#let| |g|#:| |int| |=>| |int|
+//│ Parsed: {fun pass: [] -> int -> bool; fun stop: [] -> unit -> int; fun g: [] -> int -> int}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 086fde75e7..5e2275ddbb 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -2,7 +2,7 @@
 :ParseOnly
 class A(foo: unit => unit)
 class B: A
-class C<T>(set: (T) => (unit), get: unit => T)
+class C<T>(set: T => unit, get: unit => T)
 class D: C<number>
 trait Wu(x: bool)
 class WuWu(y: bool): Wu
@@ -10,12 +10,12 @@ trait WuWuWu(z: bool): WuWu
 trait Never(w: unit => nothing): WuWuWu
 class VG<T>(x: T)
 class Home<T>(y: T): VG<string>
-trait O<I>(xx: (I) => (I))
-class OR<R>(xx: (R) => (R)): O<R>
+trait O<I>(xx: I => I)
+class OR<R>(xx: R => R): O<R>
 namespace Five {
   class ROTK(wu: string)
   class Y: Five'ROTK
 }
 class Y: Five'ROTK
-//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |(|T|)| |=>| |(|unit|)|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |(|I|)| |=>| |(|I|)|)|↵|#class| |OR|‹|R|›|(|xx|#:| |(|R|)| |=>| |(|R|)|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |ROTK|(|wu|#:| |string|)|↵|#class| |Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
-//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => '(' unit, ')', get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => '(' I, ')',): {}; class OR[R](xx: R, => '(' R, ')',): O‹R› {}; namespace Five(): {class ROTK(wu: string,) {}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |ROTK|(|wu|#:| |string|)|↵|#class| |Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
+//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace Five(): {class ROTK(wu: string,) {}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index f8d442220d..eb105d2710 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-let h1: ((number) => (number)) => ((number) => (number))
-let h2: (string) => (unit => string)
-let h3: ((number) => (number)) => (((number) => (number)) => ((number) => (number)))
-//│ |#let| |h1|#:| |(|(|number|)| |=>| |(|number|)|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |h2|#:| |(|string|)| |=>| |(|unit| |=>| |string|)|↵|#let| |h3|#:| |(|(|number|)| |=>| |(|number|)|)| |=>| |(|(|(|number|)| |=>| |(|number|)|)| |=>| |(|(|number|)| |=>| |(|number|)|)|)|
-//│ Parsed: {fun h1: [] -> (number -> (number,)) -> (number -> (number,),); fun h2: [] -> string -> (unit -> string,); fun h3: [] -> (number -> (number,)) -> ((number -> (number,)) -> (number -> (number,),),)}
+let h1: (number => number) => number => number
+let h2: string => unit => string
+let h3: (number => number) => (number => number) => number => number
+//│ |#let| |h1|#:| |(|number| |=>| |number|)| |=>| |number| |=>| |number|↵|#let| |h2|#:| |string| |=>| |unit| |=>| |string|↵|#let| |h3|#:| |(|number| |=>| |number|)| |=>| |(|number| |=>| |number|)| |=>| |number| |=>| |number|
+//│ Parsed: {fun h1: [] -> (number -> number) -> number -> number; fun h2: [] -> string -> unit -> string; fun h3: [] -> (number -> number) -> (number -> number) -> number -> number}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index cf0c30a365..7a7e4511a4 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -1,16 +1,16 @@
 :NewParser
 :ParseOnly
-trait IFoo(a: string, b: (number) => (number), c: unit => bool, d: (string) => (unit))
-trait II<T>(test: (T) => (number))
+trait IFoo(a: string, b: number => number, c: unit => bool, d: string => unit)
+trait II<T>(test: T => number)
 let create: unit => (v: number)
-let get: ((t: string)) => (string)
-trait IEvent(callback: (unit) => ((number) => (unit)))
-trait SearchFunc(__call: (string) => ((string) => (bool)))
-trait StringArray(__index: (number) => (string))
-trait Counter(__call: (number) => (string), interval: number, reset: unit => unit)
-trait Simple(a: number, b: (bool) => (string))
+let get: (t: string) => string
+trait IEvent(callback: unit => number => unit)
+trait SearchFunc(__call: string => string => bool)
+trait StringArray(__index: number => string)
+trait Counter(__call: number => string, interval: number, reset: unit => unit)
+trait Simple(a: number, b: bool => string)
 trait Simple2<T>(abc: T)
 trait Next: Simple
-trait TTT<T>(ttt: (T) => (T))
-//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |(|number|)| |=>| |(|number|)|,| |c|#:| |unit| |=>| |bool|,| |d|#:| |(|string|)| |=>| |(|unit|)|)|↵|#trait| |II|‹|T|›|(|test|#:| |(|T|)| |=>| |(|number|)|)|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|)|↵|#let| |get|#:| |(|(|t|#:| |string|)|)| |=>| |(|string|)|↵|#trait| |IEvent|(|callback|#:| |(|unit|)| |=>| |(|(|number|)| |=>| |(|unit|)|)|)|↵|#trait| |SearchFunc|(|__call|#:| |(|string|)| |=>| |(|(|string|)| |=>| |(|bool|)|)|)|↵|#trait| |StringArray|(|__index|#:| |(|number|)| |=>| |(|string|)|)|↵|#trait| |Counter|(|__call|#:| |(|number|)| |=>| |(|string|)|,| |interval|#:| |number|,| |reset|#:| |unit| |=>| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |(|bool|)| |=>| |(|string|)|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |(|T|)| |=>| |(|T|)|)|
-//│ Parsed: {trait IFoo(a: string, b: number, => '(' number, ')', c: unit, => bool, d: string, => '(' unit, ')',): {}; trait II[T](test: T, => '(' number, ')',): {}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> (string,); trait IEvent(callback: unit, => '(' number, => '(' unit, ')', ')',): {}; trait SearchFunc(__call: string, => '(' string, => '(' bool, ')', ')',): {}; trait StringArray(__index: number, => '(' string, ')',): {}; trait Counter(__call: number, => '(' string, ')', interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => '(' string, ')',): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => '(' T, ')',): {}}
+trait TTT<T>(ttt: T => T)
+//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |number| |=>| |number|,| |c|#:| |unit| |=>| |bool|,| |d|#:| |string| |=>| |unit|)|↵|#trait| |II|‹|T|›|(|test|#:| |T| |=>| |number|)|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|)|↵|#let| |get|#:| |(|t|#:| |string|)| |=>| |string|↵|#trait| |IEvent|(|callback|#:| |unit| |=>| |number| |=>| |unit|)|↵|#trait| |SearchFunc|(|__call|#:| |string| |=>| |string| |=>| |bool|)|↵|#trait| |StringArray|(|__index|#:| |number| |=>| |string|)|↵|#trait| |Counter|(|__call|#:| |number| |=>| |string|,| |interval|#:| |number|,| |reset|#:| |unit| |=>| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |bool| |=>| |string|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|)|
+//│ Parsed: {trait IFoo(a: string, b: number, => number, c: unit, => bool, d: string, => unit,): {}; trait II[T](test: T, => number,): {}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(callback: unit, => number, => unit,): {}; trait SearchFunc(__call: string, => string, => bool,): {}; trait StringArray(__index: number, => string,): {}; trait Counter(__call: number, => string, interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => string,): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => T,): {}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 06ad21c2ea..bbbe8eb4c5 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,17 +1,17 @@
 :NewParser
 :ParseOnly
-let extend: (T) => ((U) => ((T) & (U)))
-let foo: ((T) & (U)) => (unit)
-let over: (((number) => (string)) & ((object) => (string))) => (string)
+let extend: T => U => (T) & (U)
+let foo: (T) & (U) => unit
+let over: (number => string) & (object => string) => string
 trait IA(x: number)
 trait IB(y: number)
-let iii: ((IA) & (IB)) => ((IA) & (IB))
-let uu: (((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))) => (((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)))
-let iiii: (((U) & (T)) & (V)) => (((U) & (T)) & (V))
-let arr: ((MutArray<U>) & (MutArray<T>)) => ((MutArray<U>) & (MutArray<T>))
-let tt: (((U, T, )) & ((V, V, ))) => (((U, T, )) & ((V, V, )))
+let iii: (IA) & (IB) => (IA) & (IB)
+let uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
+let iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
+let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
+let tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
 class A
 class B
-let inter: ((A) & (B)) => ((A) & (B))
-//│ |#let| |extend|#:| |(|T|)| |=>| |(|(|U|)| |=>| |(|(|T|)| |&| |(|U|)|)|)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|)| |=>| |(|unit|)|↵|#let| |over|#:| |(|(|(|number|)| |=>| |(|string|)|)| |&| |(|(|object|)| |=>| |(|string|)|)|)| |=>| |(|string|)|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#let| |iii|#:| |(|(|IA|)| |&| |(|IB|)|)| |=>| |(|(|IA|)| |&| |(|IB|)|)|↵|#let| |uu|#:| |(|(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)| |=>| |(|(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|↵|#let| |iiii|#:| |(|(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)| |=>| |(|(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|↵|#let| |arr|#:| |(|(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)| |=>| |(|(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|↵|#let| |tt|#:| |(|(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)| |=>| |(|(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|↵|#class| |A|↵|#class| |B|↵|#let| |inter|#:| |(|(|A|)| |&| |(|B|)|)| |=>| |(|(|A|)| |&| |(|B|)|)|
-//│ Parsed: {fun extend: [] -> T -> (U -> ((T,) & (U,),),); fun foo: [] -> ((T,) & (U,)) -> (unit,); fun over: [] -> ((number -> (string,),) & (object -> (string,),)) -> (string,); trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,),); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,),); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],),); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),),); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,),)}
+let inter: (A) & (B) => (A) & (B)
+//│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
+//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index 0b26159ee5..f0a5dfe0dc 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,6 +1,6 @@
 :NewParser
 :ParseOnly
-let multi1: (number) => (number)
+let multi1: number => number
 let multi3: unit => unit
 class Foo: Base
 trait AnotherBase(y: string)
@@ -9,10 +9,10 @@ namespace N {
   let g: unit => unit
   let h: unit => unit
 }
-let multi2: (string) => (string)
+let multi2: string => string
 let multi4: unit => unit
 trait Base(a: number)
 class AnotherFoo: AnotherBase
 let multi5: unit => unit
-//│ |#let| |multi1|#:| |(|number|)| |=>| |(|number|)|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |(|string|)| |=>| |(|string|)|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
-//│ Parsed: {fun multi1: [] -> number -> (number,); fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> (string,); fun multi4: [] -> unit -> unit; trait Base(a: number,): {}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
+//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
+//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(a: number,): {}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index d91556d537..dc2cd60edb 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
 namespace N1 {
-  let f: (anything) => (number)
-  let ff: (anything) => (number)
+  let f: anything => number
+  let ff: anything => number
   class C(f: unit => unit)
   trait I(f: unit => number)
   namespace N2 {
-    let fff: (bool) => (number)
-    let gg: (N1'C) => (N1'C)
+    let fff: bool => number
+    let gg: N1'C => N1'C
     class BBB: N1'C
   }
 }
 namespace AA {
-  let f: (anything) => (string)
+  let f: anything => string
   class C(f: unit => unit)
   trait I(f: unit => number)
   namespace N2 {
   }
 }
-let f1: (N1'C) => (N1'C)
-let f2: (AA'C) => (AA'C)
-//│ |#namespace| |N1| |{|→|#let| |f|#:| |(|anything|)| |=>| |(|number|)|↵|#let| |ff|#:| |(|anything|)| |=>| |(|number|)|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |(|bool|)| |=>| |(|number|)|↵|#let| |gg|#:| |(|N1'C|)| |=>| |(|N1'C|)|↵|#class| |BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |(|anything|)| |=>| |(|string|)|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |(|N1'C|)| |=>| |(|N1'C|)|↵|#let| |f2|#:| |(|AA'C|)| |=>| |(|AA'C|)|
-//│ Parsed: {namespace N1(): {fun f: [] -> anything -> (number,); fun ff: [] -> anything -> (number,); class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> (number,); fun gg: [] -> N1'C -> (N1'C,); class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> (string,); class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> (N1'C,); fun f2: [] -> AA'C -> (AA'C,)}
+let f1: N1'C => N1'C
+let f2: AA'C => AA'C
+//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index b09c51db67..9a4119d460 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,19 +1,19 @@
 :NewParser
 :ParseOnly
-let buildName: (string) => (((string) | (undefined)) => (string))
-let buildName2: (string) => (((string) | (undefined)) => (string))
-let buildName3: (string) => ((MutArray<string>) => (string))
-let buildName4: (string) => ((MutArray<anything>) => (string))
+let buildName: string => (string) | (undefined) => string
+let buildName2: string => (string) | (undefined) => string
+let buildName3: string => MutArray<string> => string
+let buildName4: string => MutArray<anything> => string
 trait SquareConfig(color: (string) | (undefined), width: (number) | (undefined))
-let did: (number) => ((((number) => (number)) | (undefined)) => (number))
-let getOrElse: ((MutArray<object>) | (undefined)) => (object)
+let did: number => (number => number) | (undefined) => number
+let getOrElse: (MutArray<object>) | (undefined) => object
 class ABC
-let testABC: ((ABC) | (undefined)) => (unit)
-let testSquareConfig: ((SquareConfig) | (undefined)) => (unit)
-let err: (((number, string, )) | (undefined)) => (unit)
-let toStr: (((number) | (bool)) | (undefined)) => (string)
-let boo: (((T) & (U)) | (undefined)) => (unit)
+let testABC: (ABC) | (undefined) => unit
+let testSquareConfig: (SquareConfig) | (undefined) => unit
+let err: ((number, string, )) | (undefined) => unit
+let toStr: ((number) | (bool)) | (undefined) => string
+let boo: ((T) & (U)) | (undefined) => unit
 class B<T>(b: T)
-let boom: ((B<nothing>) | (undefined)) => (anything)
-//│ |#let| |buildName|#:| |(|string|)| |=>| |(|(|(|string|)| ||| |(|undefined|)|)| |=>| |(|string|)|)|↵|#let| |buildName2|#:| |(|string|)| |=>| |(|(|(|string|)| ||| |(|undefined|)|)| |=>| |(|string|)|)|↵|#let| |buildName3|#:| |(|string|)| |=>| |(|(|MutArray|‹|string|›|)| |=>| |(|string|)|)|↵|#let| |buildName4|#:| |(|string|)| |=>| |(|(|MutArray|‹|anything|›|)| |=>| |(|string|)|)|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#let| |did|#:| |(|number|)| |=>| |(|(|(|(|number|)| |=>| |(|number|)|)| ||| |(|undefined|)|)| |=>| |(|number|)|)|↵|#let| |getOrElse|#:| |(|(|MutArray|‹|object|›|)| ||| |(|undefined|)|)| |=>| |(|object|)|↵|#class| |ABC|↵|#let| |testABC|#:| |(|(|ABC|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#let| |testSquareConfig|#:| |(|(|SquareConfig|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#let| |err|#:| |(|(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#let| |toStr|#:| |(|(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)| |=>| |(|string|)|↵|#let| |boo|#:| |(|(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)| |=>| |(|unit|)|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#let| |boom|#:| |(|(|B|‹|nothing|›|)| ||| |(|undefined|)|)| |=>| |(|anything|)|
-//│ Parsed: {fun buildName: [] -> string -> (((string,) | (undefined,)) -> (string,),); fun buildName2: [] -> string -> (((string,) | (undefined,)) -> (string,),); fun buildName3: [] -> string -> (MutArray[string] -> (string,),); fun buildName4: [] -> string -> (MutArray[anything] -> (string,),); trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> (((number -> (number,),) | (undefined,)) -> (number,),); fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> (object,); class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> (unit,); fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> (unit,); fun err: [] -> (((number, string,),) | (undefined,)) -> (unit,); fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> (string,); fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> (unit,); class B[T](b: T,) {}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> (anything,)}
+let boom: (B<nothing>) | (undefined) => anything
+//│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
+//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 8bd1c735ff..88d3e61eb4 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,48 +1,48 @@
 :NewParser
 :ParseOnly
-let f: ((number) => (string)) & ((string) => (string))
-class M(foo: ((number) => (string)) & ((string) => (string)))
-let app: (((string) => (unit)) => ((number) => (unit))) & (((string) => (unit)) => ((string) => (unit)))
-let create: ((number) => (unit => bool)) & ((bool) => (unit => bool))
-let g0: ((MutArray<string>) => (string)) & ((MutArray<object>) => (string))
-let db: ((number) => (MutArray<number>)) & ((object) => (MutArray<number>))
+let f: (number => string) & (string => string)
+class M(foo: (number => string) & (string => string))
+let app: ((string => unit) => number => unit) & ((string => unit) => string => unit)
+let create: (number => unit => bool) & (bool => unit => bool)
+let g0: (MutArray<string> => string) & (MutArray<object> => string)
+let db: (number => MutArray<number>) & (object => MutArray<number>)
 class N
-let id: ((M) => (unit)) & ((N) => (unit))
-let tst: (((z: number)) => ((y: string))) & (((z: bool)) => ((y: string)))
-let op: ((number) => (((number) | (undefined)) => (unit))) & ((number) => (((bool) | (undefined)) => (unit)))
-let swap: (((number, string, )) => ((number, string, ))) & (((string, number, )) => ((number, string, )))
-let u: (((number) | (bool)) => (string)) & ((object) => (string))
-let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
+let id: (M => unit) & (N => unit)
+let tst: ((z: number) => (y: string)) & ((z: bool) => (y: string))
+let op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
+let swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
+let u: ((number) | (bool) => string) & (object => string)
+let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 namespace XX {
-  let f: (T) => ((anything) => (string)) /* warning: the overload of function f is not supported yet. */
+  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
 }
-class WWW(F: (T) => (anything) /* warning: the overload of function F is not supported yet. */)
+class WWW(F: T => anything /* warning: the overload of function F is not supported yet. */)
 let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#let| |f|#:| |(|(|number|)| |=>| |(|string|)|)| |&| |(|(|string|)| |=>| |(|string|)|)|↵|#class| |M|(|foo|#:| |(|(|number|)| |=>| |(|string|)|)| |&| |(|(|string|)| |=>| |(|string|)|)|)|↵|#let| |app|#:| |(|(|(|string|)| |=>| |(|unit|)|)| |=>| |(|(|number|)| |=>| |(|unit|)|)|)| |&| |(|(|(|string|)| |=>| |(|unit|)|)| |=>| |(|(|string|)| |=>| |(|unit|)|)|)|↵|#let| |create|#:| |(|(|number|)| |=>| |(|unit| |=>| |bool|)|)| |&| |(|(|bool|)| |=>| |(|unit| |=>| |bool|)|)|↵|#let| |g0|#:| |(|(|MutArray|‹|string|›|)| |=>| |(|string|)|)| |&| |(|(|MutArray|‹|object|›|)| |=>| |(|string|)|)|↵|#let| |db|#:| |(|(|number|)| |=>| |(|MutArray|‹|number|›|)|)| |&| |(|(|object|)| |=>| |(|MutArray|‹|number|›|)|)|↵|#class| |N|↵|#let| |id|#:| |(|(|M|)| |=>| |(|unit|)|)| |&| |(|(|N|)| |=>| |(|unit|)|)|↵|#let| |tst|#:| |(|(|(|z|#:| |number|)|)| |=>| |(|(|y|#:| |string|)|)|)| |&| |(|(|(|z|#:| |bool|)|)| |=>| |(|(|y|#:| |string|)|)|)|↵|#let| |op|#:| |(|(|number|)| |=>| |(|(|(|number|)| ||| |(|undefined|)|)| |=>| |(|unit|)|)|)| |&| |(|(|number|)| |=>| |(|(|(|bool|)| ||| |(|undefined|)|)| |=>| |(|unit|)|)|)|↵|#let| |swap|#:| |(|(|(|number|,| |string|,| |)|)| |=>| |(|(|number|,| |string|,| |)|)|)| |&| |(|(|(|string|,| |number|,| |)|)| |=>| |(|(|number|,| |string|,| |)|)|)|↵|#let| |u|#:| |(|(|(|number|)| ||| |(|bool|)|)| |=>| |(|string|)|)| |&| |(|(|object|)| |=>| |(|string|)|)|↵|#let| |doSome|#:| |(|anything|)| |=>| |(|unit|)| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |(|T|)| |=>| |(|(|anything|)| |=>| |(|string|)|)| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |(|T|)| |=>| |(|anything|)| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(|foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|)|↵|#let| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|)| |=>| |(|y|#:| |string|)|)| |&| |(|(|z|#:| |bool|)| |=>| |(|y|#:| |string|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
-//│ ╙──      	                                           ^
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ╙──      	                                       ^
 //│ ╔══[PARSE ERROR] Unexpected operator in expression position
-//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
-//│ ╙──      	                                                                                                   ^^
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ╙──      	                                                                                               ^^
 //│ ╔══[PARSE ERROR] Unexpected newline in expression position
-//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
-//│ ║        	                                                                                                     ^
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║        	                                                                                                 ^
 //│ ║  l.16: 	namespace XX {
 //│ ╙──      	
 //│ ╔══[PARSE ERROR] Unexpected 'namespace' keyword in expression position
 //│ ║  l.16: 	namespace XX {
 //│ ╙──      	^^^^^^^^^
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.15: 	let doSome: (anything) => (unit) /* warning: the overload of function doSome is not supported yet. */
-//│ ║        	                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║        	                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.16: 	namespace XX {
 //│ ╙──      	^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
 //│ ║  l.16: 	namespace XX {
 //│ ║        	             ^
-//│ ║  l.17: 	  let f: (T) => ((anything) => (string)) /* warning: the overload of function f is not supported yet. */
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//│ ║  l.17: 	  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
+//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 //│ ║  l.18: 	}
 //│ ╙──      	^
-//│ Parsed: {fun f: [] -> (number -> (string,),) & (string -> (string,),); class M(foo: & (number, => '(' string, ')',) (string, => '(' string, ')',),) {}; fun app: [] -> ((string -> (unit,)) -> (number -> (unit,),),) & ((string -> (unit,)) -> (string -> (unit,),),); fun create: [] -> (number -> (unit -> bool,),) & (bool -> (unit -> bool,),); fun g0: [] -> (MutArray[string] -> (string,),) & (MutArray[object] -> (string,),); fun db: [] -> (number -> (MutArray[number],),) & (object -> (MutArray[number],),); class N() {}; fun id: [] -> (M -> (unit,),) & (N -> (unit,),); fun tst: [] -> ((z: number,) -> ((y: string,),),) & ((z: bool,) -> ((y: string,),),); fun op: [] -> (number -> (((number,) | (undefined,)) -> (unit,),),) & (number -> (((bool,) | (undefined,)) -> (unit,),),); fun swap: [] -> ((number, string,) -> ((number, string,),),) & ((string, number,) -> ((number, string,),),); fun u: [] -> (((number,) | (bool,)) -> (string,),) & (object -> (string,),); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index a1657ae958..753f794b68 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,18 +1,18 @@
 :NewParser
 :ParseOnly
-let key: ((string, bool, )) => (string)
-let value: ((string, bool, )) => (bool)
-let third: ((number, number, number, )) => (number)
-let vec2: (number) => ((number) => ((number, number, )))
-let twoFunctions: (((number) => (number), (number) => (number), )) => ((number) => (number))
-let tupleIt: (string) => ((unit => string, ))
-let s: (bool) => (((string) | (number), (number) | (bool), ))
-let s2: ((bool, (string) | (number), )) => ((string) | (number))
-let ex: (T) => ((U) => ((T, U, (T) & (U), )))
-let foo: (((T) & (U), )) => (unit)
-let conv: ((y: number)) => (((y: number), (z: string), ))
+let key: (string, bool, ) => string
+let value: (string, bool, ) => bool
+let third: (number, number, number, ) => number
+let vec2: number => number => (number, number, )
+let twoFunctions: (number => number, number => number, ) => number => number
+let tupleIt: string => (unit => string, )
+let s: bool => ((string) | (number), (number) | (bool), )
+let s2: (bool, (string) | (number), ) => (string) | (number)
+let ex: T => U => (T, U, (T) & (U), )
+let foo: ((T) & (U), ) => unit
+let conv: (y: number) => ((y: number), (z: string), )
 class A(x: number)
 class B
-let swap: ((A, B, )) => ((B, A, ))
-//│ |#let| |key|#:| |(|(|string|,| |bool|,| |)|)| |=>| |(|string|)|↵|#let| |value|#:| |(|(|string|,| |bool|,| |)|)| |=>| |(|bool|)|↵|#let| |third|#:| |(|(|number|,| |number|,| |number|,| |)|)| |=>| |(|number|)|↵|#let| |vec2|#:| |(|number|)| |=>| |(|(|number|)| |=>| |(|(|number|,| |number|,| |)|)|)|↵|#let| |twoFunctions|#:| |(|(|(|number|)| |=>| |(|number|)|,| |(|number|)| |=>| |(|number|)|,| |)|)| |=>| |(|(|number|)| |=>| |(|number|)|)|↵|#let| |tupleIt|#:| |(|string|)| |=>| |(|(|unit| |=>| |string|,| |)|)|↵|#let| |s|#:| |(|bool|)| |=>| |(|(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|)|↵|#let| |s2|#:| |(|(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)| |=>| |(|(|string|)| ||| |(|number|)|)|↵|#let| |ex|#:| |(|T|)| |=>| |(|(|U|)| |=>| |(|(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|)|)|↵|#let| |foo|#:| |(|(|(|T|)| |&| |(|U|)|,| |)|)| |=>| |(|unit|)|↵|#let| |conv|#:| |(|(|y|#:| |number|)|)| |=>| |(|(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#let| |swap|#:| |(|(|A|,| |B|,| |)|)| |=>| |(|(|B|,| |A|,| |)|)|
-//│ Parsed: {fun key: [] -> (string, bool,) -> (string,); fun value: [] -> (string, bool,) -> (bool,); fun third: [] -> (number, number, number,) -> (number,); fun vec2: [] -> number -> (number -> ((number, number,),),); fun twoFunctions: [] -> (number -> (number,), number -> (number,),) -> (number -> (number,),); fun tupleIt: [] -> string -> ((unit -> string,),); fun s: [] -> bool -> (((string,) | (number,), (number,) | (bool,),),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,),); fun ex: [] -> T -> (U -> ((T, U, (T,) & (U,),),),); fun foo: [] -> ((T,) & (U,)) -> (unit,); fun conv: [] -> (y: number,) -> (((y: number,), (z: string,),),); class A(x: number,) {}; class B() {}; fun swap: [] -> (A, B,) -> ((B, A,),)}
+let swap: (A, B, ) => (B, A, )
+//│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|)| |=>| |(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
+//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A(x: number,) {}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index 938983dded..b416bd291d 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,17 +1,17 @@
 :NewParser
 :ParseOnly
-let inc: (T) => (number)
-class CC<T>(print: (T) => (unit))
-let con: (T) => (U)
-class Printer<T>(print: (T) => (unit))
-let setStringPrinter: (Printer<string>) => (unit)
+let inc: T => number
+class CC<T>(print: T => unit)
+let con: T => U
+class Printer<T>(print: T => unit)
+let setStringPrinter: Printer<string> => unit
 let getStringPrinter: unit => Printer<string>
-let foo: (Printer<T>) => ((T) => (T))
-let foo2: (Printer<T>) => ((T) => (T))
-class F<T>(x: T, GG: (U) => (T))
-trait I<T>(x: T, GG: (U) => (T))
-class FFF<T>(fff: (T) => (unit))
-let fff: (FFF<string>) => ((string) => (unit))
+let foo: Printer<T> => T => T
+let foo2: Printer<T> => T => T
+class F<T>(x: T, GG: U => T)
+trait I<T>(x: T, GG: U => T)
+class FFF<T>(fff: T => unit)
+let fff: FFF<string> => string => unit
 let getFFF: unit => FFF<number>
-//│ |#let| |inc|#:| |(|T|)| |=>| |(|number|)|↵|#class| |CC|‹|T|›|(|print|#:| |(|T|)| |=>| |(|unit|)|)|↵|#let| |con|#:| |(|T|)| |=>| |(|U|)|↵|#class| |Printer|‹|T|›|(|print|#:| |(|T|)| |=>| |(|unit|)|)|↵|#let| |setStringPrinter|#:| |(|Printer|‹|string|›|)| |=>| |(|unit|)|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |(|Printer|‹|T|›|)| |=>| |(|(|T|)| |=>| |(|T|)|)|↵|#let| |foo2|#:| |(|Printer|‹|T|›|)| |=>| |(|(|T|)| |=>| |(|T|)|)|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|U|)| |=>| |(|T|)|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |(|U|)| |=>| |(|T|)|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |(|T|)| |=>| |(|unit|)|)|↵|#let| |fff|#:| |(|FFF|‹|string|›|)| |=>| |(|(|string|)| |=>| |(|unit|)|)|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> T -> (number,); class CC[T](print: T, => '(' unit, ')',) {}; fun con: [] -> T -> (U,); class Printer[T](print: T, => '(' unit, ')',) {}; fun setStringPrinter: [] -> Printer[string] -> (unit,); fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> (T -> (T,),); fun foo2: [] -> Printer[T] -> (T -> (T,),); class F[T](x: T, GG: U, => '(' T, ')',) {}; trait I[T](x: T, GG: U, => '(' T, ')',): {}; class FFF[T](fff: T, => '(' unit, ')',) {}; fun fff: [] -> FFF[string] -> (string -> (unit,),); fun getFFF: [] -> unit -> FFF[number]}
+//│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |T| |=>| |unit|)|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> T -> number; class CC[T](print: T, => unit,) {}; fun con: [] -> T -> U; class Printer[T](print: T, => unit,) {}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T](x: T, GG: U, => T,) {}; trait I[T](x: T, GG: U, => T,): {}; class FFF[T](fff: T, => unit,) {}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 34f66f32f3..14daeda466 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,11 +1,11 @@
 :NewParser
 :ParseOnly
-let getString: (((string) | (number)) | (bool)) => (string)
-let test: (bool) => ((string) | (number))
-let run: (((number) => (number)) | ((number) => (string))) => (anything)
-let get: ((MutArray<number>) | (MutArray<string>)) => (unit)
-let get2: (((string, string, )) | ((number, string, ))) => (string)
-let typeVar: ((T) | (U)) => ((T) | (U))
-let uuuu: (((string) | (number)) | (bool)) => (((string) | (number)) | (bool))
-//│ |#let| |getString|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)| |=>| |(|string|)|↵|#let| |test|#:| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)|↵|#let| |run|#:| |(|(|(|number|)| |=>| |(|number|)|)| ||| |(|(|number|)| |=>| |(|string|)|)|)| |=>| |(|anything|)|↵|#let| |get|#:| |(|(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)| |=>| |(|unit|)|↵|#let| |get2|#:| |(|(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)| |=>| |(|string|)|↵|#let| |typeVar|#:| |(|(|T|)| ||| |(|U|)|)| |=>| |(|(|T|)| ||| |(|U|)|)|↵|#let| |uuuu|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)| |=>| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|
-//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> (string,); fun test: [] -> bool -> ((string,) | (number,),); fun run: [] -> ((number -> (number,),) | (number -> (string,),)) -> (anything,); fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> (unit,); fun get2: [] -> (((string, string,),) | ((number, string,),)) -> (string,); fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,),); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,),)}
+let getString: ((string) | (number)) | (bool) => string
+let test: bool => (string) | (number)
+let run: (number => number) | (number => string) => anything
+let get: (MutArray<number>) | (MutArray<string>) => unit
+let get2: ((string, string, )) | ((number, string, )) => string
+let typeVar: (T) | (U) => (T) | (U)
+let uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
+//│ |#let| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#let| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#let| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#let| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#let| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#let| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#let| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
+//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}

From 4c5247164c37587a04ac599f6adf7d34e99a2aa1 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 15:38:44 +0800
Subject: [PATCH 10/40] Fix class format

---
 .../src/main/scala/ts2mls/TSNamespace.scala   |  4 ++
 .../main/scala/ts2mls/types/Converter.scala   | 29 +++++-----
 ts2mls/js/src/test/diff/Array.d.mls           | 12 ++--
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  | 12 ++--
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 26 ++++++---
 ts2mls/js/src/test/diff/Heritage.d.mls        | 57 +++++++++++++------
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 52 ++++++++++++-----
 ts2mls/js/src/test/diff/Intersection.d.mls    | 16 ++++--
 ts2mls/js/src/test/diff/MultiFiles.d.mls      | 16 ++++--
 ts2mls/js/src/test/diff/Namespace.d.mls       | 22 ++++---
 ts2mls/js/src/test/diff/Optional.d.mls        | 15 +++--
 ts2mls/js/src/test/diff/Overload.d.mls        | 36 ++++++------
 ts2mls/js/src/test/diff/Tuple.d.mls           | 12 ++--
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 26 ++++++---
 14 files changed, 224 insertions(+), 111 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index 8489c8d204..cc4ba9413b 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -2,6 +2,7 @@ package ts2mls
 
 import scala.collection.mutable.{HashMap, ListBuffer}
 import types._
+import mlscript.utils._
 
 class TSNamespace(name: String, parent: Option[TSNamespace]) {
   private val subSpace = HashMap[String, TSNamespace]()
@@ -65,6 +66,9 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
           //     else // TODO: add constraints
           //       writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(overload)}")
           // }
+          case _: TSClassType => writer.writeln(indent + Converter.convert(mem)(indent))
+          case _ @ TSInterfaceType(name, _, _, _) if (name =/= "") =>
+            writer.writeln(indent + Converter.convert(mem)(indent))
           case _ => writer.writeln(indent + Converter.convert(mem))
         }
       }
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index dd4a32eea8..7bd3c56cb7 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -18,7 +18,7 @@ object Converter {
     "false" -> "" // will not appear individually
   )
 
-  def convert(tsType: TSType): String = tsType match {
+  def convert(tsType: TSType)(implicit indent: String = ""): String = tsType match {
     case TSPrimitiveType(typeName) => primitiveName(typeName)
     case TSReferenceType(name) => name
     case TSFunctionType(params, res, _) =>
@@ -43,16 +43,18 @@ object Converter {
     case TSArrayType(element) => s"MutArray<${convert(element)}>"
     case TSEnumType => "int"
     case TSMemberType(base, _) => convert(base) // TODO: support private/protected members
-    case TSInterfaceType(name, members, typeVars, parents) => convertRecord(s"trait $name", members, typeVars, parents)
-    case TSClassType(name, members, _, typeVars, parents) => convertRecord(s"class $name", members, typeVars, parents) // TODO: support static members
+    case TSInterfaceType(name, members, typeVars, parents) => convertRecord(s"trait $name", members, typeVars, parents)(indent)
+    case TSClassType(name, members, _, typeVars, parents) => convertRecord(s"class $name", members, typeVars, parents)(indent) // TODO: support static members
     case TSSubstitutionType(base, applied) => s"${base}<${applied.map((app) => convert(app)).reduceLeft((res, s) => s"$res, $s")}>"
     case overload @ TSIgnoredOverload(base, _) => s"${convert(base)} ${overload.warning}"
   }
 
   private def convertRecord(typeName: String, members: Map[String, TSMemberType],
-    typeVars: List[TSTypeParameter], parents: List[TSType]) = {
+    typeVars: List[TSTypeParameter], parents: List[TSType])(implicit indent: String) = {
     val allRecs = members.toList.map((m) => m._2.modifier match {
-      case Public => s"${m._1}: ${convert(m._2)}"
+      case Public =>
+        if (typeName === "trait ") s"${m._1}: ${convert(m._2)},"
+        else s"${indent}  let ${m._1}: ${convert(m._2)}\n"
       // case Public => {
       //   m._2.base match { // methods
       //     case f @ TSFunctionType(_, _, typeVars) if (!typeVars.isEmpty) =>
@@ -69,8 +71,9 @@ object Converter {
 
     val body = { // members without independent type parameters, translate them directly
       val lst = allRecs.filter((s) => !s.isEmpty())
-      if (lst.isEmpty) ""
-      else s"(${lst.reduceLeft((bd, m) => s"$bd, $m")})"
+      if (lst.isEmpty) "{}"
+      else if (typeName === "trait ") s"(${lst.reduceLeft((bd, m) => s"$bd$m")})"
+      else s"{\n${lst.reduceLeft((bd, m) => s"$bd$m")}$indent}"
     }
     // val methods = { // members with independent type parameters, use methods instead
     //   val lst = allRecs.filter(_.startsWith("  "))
@@ -78,14 +81,14 @@ object Converter {
     //   else "\n" + lst.reduceLeft((bd, m) => s"$bd\n$m")
     // }
     
-    if (typeName.equals("trait ")) body // anonymous interfaces
+    if (typeName === "trait ") body // anonymous interfaces
     else { // named interfaces and classes
-      val bodyWithParents =
-        if (parents.isEmpty) body
-        else parents.foldLeft(s"$body: ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
-      if (typeVars.isEmpty) s"$typeName$bodyWithParents"
+      val herirage =
+        if (parents.isEmpty) ""
+        else parents.foldLeft("(): ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
+      if (typeVars.isEmpty) s"$typeName$herirage $body"
       else
-        s"$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$bodyWithParents" // TODO: add constraints
+        s"$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$herirage $body" // TODO: add constraints
     }
   }
 }
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 377b900dd4..7aa5fe2da7 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -4,19 +4,23 @@ let first: MutArray<string> => string
 let getZero3: unit => MutArray<number>
 let first2: MutArray<number => number> => number => number
 let doEs: MutArray<int> => MutArray<int>
-class C
-trait I(i: number)
+class C {}
+trait I {
+  let i: number
+}
 let doCs: MutArray<C> => MutArray<C>
 let doIs: MutArray<I> => MutArray<I>
 let inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
 let clean: MutArray<(string, number, )> => MutArray<(string, number, )>
 let translate: MutArray<T> => MutArray<U>
 let uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
-class Temp<T>(x: T)
+class Temp<T> {
+  let x: T
+}
 let ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
 let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
 //│ ╔══[PARSE ERROR] Unmatched opening angle bracket
-//│ ║  l.17: 	let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
+//│ ║  l.21: 	let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
 //│ ║        	                                           ^
 //│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator
 //│ |T|>>|Temp|
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index c992b4a057..6991ddf823 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -14,11 +14,15 @@ let fail: unit => nothing
 let create: unit => object
 let pa: number => number
 let wtf: anything => unit
-class Foooooo(ooooooo: number)
+class Foooooo {
+  let ooooooo: number
+}
 let inn: Foooooo => unit
 let out: unit => Foooooo
-trait Barrrrrrrrr(rrrrrrr: number)
+trait Barrrrrrrrr {
+  let rrrrrrr: number
+}
 let inn2: Barrrrrrrrr => unit
 let out2: unit => Barrrrrrrrr
-//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |number| |=>| |number| |=>| |number|↵|#let| |sub|#:| |number| |=>| |number| |=>| |number|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |anything| |=>| |anything|↵|#let| |odd|#:| |number| |=>| |bool|↵|#let| |isnull|#:| |anything| |=>| |bool|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |null| |=>| |null|↵|#let| |un|#:| |undefined| |=>| |undefined|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |number| |=>| |number|↵|#let| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo|(|ooooooo|#:| |number|)|↵|#let| |inn|#:| |Foooooo| |=>| |unit|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(|rrrrrrr|#:| |number|)|↵|#let| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo(ooooooo: number,) {}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(rrrrrrr: number,): {}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
+//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |number| |=>| |number| |=>| |number|↵|#let| |sub|#:| |number| |=>| |number| |=>| |number|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |anything| |=>| |anything|↵|#let| |odd|#:| |number| |=>| |bool|↵|#let| |isnull|#:| |anything| |=>| |bool|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |null| |=>| |null|↵|#let| |un|#:| |undefined| |=>| |undefined|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |number| |=>| |number|↵|#let| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#let| |inn|#:| |Foooooo| |=>| |unit|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#let| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo() {fun ooooooo: [] -> number}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(): {fun rrrrrrr: [] -> number}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index 61149ba4a7..49b8a9df5c 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,9 +1,21 @@
 :NewParser
 :ParseOnly
-class Student(name: string, isFriend: Student => bool, addScore: string => number => unit, getID: unit => number)
-class Foo<T>(bar: T => unit)
-class EZ(inc: number => number)
-class Outer
-class TTT<T>(ttt: T => T, ttt2: T => T)
-//│ |#class| |Student|(|name|#:| |string|,| |isFriend|#:| |Student| |=>| |bool|,| |addScore|#:| |string| |=>| |number| |=>| |unit|,| |getID|#:| |unit| |=>| |number|)|↵|#class| |Foo|‹|T|›|(|bar|#:| |T| |=>| |unit|)|↵|#class| |EZ|(|inc|#:| |number| |=>| |number|)|↵|#class| |Outer|↵|#class| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|,| |ttt2|#:| |T| |=>| |T|)|
-//│ Parsed: {class Student(name: string, isFriend: Student, => bool, addScore: string, => number, => unit, getID: unit, => number,) {}; class Foo[T](bar: T, => unit,) {}; class EZ(inc: number, => number,) {}; class Outer() {}; class TTT[T](ttt: T, => T, ttt2: T, => T,) {}}
+class Student {
+  let name: string
+  let isFriend: Student => bool
+  let addScore: string => number => unit
+  let getID: unit => number
+}
+class Foo<T> {
+  let bar: T => unit
+}
+class EZ {
+  let inc: number => number
+}
+class Outer {}
+class TTT<T> {
+  let ttt: T => T
+  let ttt2: T => T
+}
+//│ |#class| |Student| |{|→|#let| |name|#:| |string|↵|#let| |isFriend|#:| |Student| |=>| |bool|↵|#let| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#let| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›| |{|→|#let| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ| |{|→|#let| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer| |{||}|↵|#class| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|↵|#let| |ttt2|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {class Student() {fun name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 5e2275ddbb..1280c5bf40 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -1,21 +1,44 @@
 :NewParser
 :ParseOnly
-class A(foo: unit => unit)
-class B: A
-class C<T>(set: T => unit, get: unit => T)
-class D: C<number>
-trait Wu(x: bool)
-class WuWu(y: bool): Wu
-trait WuWuWu(z: bool): WuWu
-trait Never(w: unit => nothing): WuWuWu
-class VG<T>(x: T)
-class Home<T>(y: T): VG<string>
-trait O<I>(xx: I => I)
-class OR<R>(xx: R => R): O<R>
+class A {
+  let foo: unit => unit
+}
+class B(): A {}
+class C<T> {
+  let set: T => unit
+  let get: unit => T
+}
+class D(): C<number> {}
+trait Wu {
+  let x: bool
+}
+class WuWu(): Wu {
+  let y: bool
+}
+trait WuWuWu(): WuWu {
+  let z: bool
+}
+trait Never(): WuWuWu {
+  let w: unit => nothing
+}
+class VG<T> {
+  let x: T
+}
+class Home<T>(): VG<string> {
+  let y: T
+}
+trait O<I> {
+  let xx: I => I
+}
+class OR<R>(): O<R> {
+  let xx: R => R
+}
 namespace Five {
-  class ROTK(wu: string)
-  class Y: Five'ROTK
+  class ROTK {
+    let wu: string
+  }
+  class Y(): Five'ROTK {}
 }
-class Y: Five'ROTK
-//│ |#class| |A|(|foo|#:| |unit| |=>| |unit|)|↵|#class| |B|#:| |A|↵|#class| |C|‹|T|›|(|set|#:| |T| |=>| |unit|,| |get|#:| |unit| |=>| |T|)|↵|#class| |D|#:| |C|‹|number|›|↵|#trait| |Wu|(|x|#:| |bool|)|↵|#class| |WuWu|(|y|#:| |bool|)|#:| |Wu|↵|#trait| |WuWuWu|(|z|#:| |bool|)|#:| |WuWu|↵|#trait| |Never|(|w|#:| |unit| |=>| |nothing|)|#:| |WuWuWu|↵|#class| |VG|‹|T|›|(|x|#:| |T|)|↵|#class| |Home|‹|T|›|(|y|#:| |T|)|#:| |VG|‹|string|›|↵|#trait| |O|‹|I|›|(|xx|#:| |I| |=>| |I|)|↵|#class| |OR|‹|R|›|(|xx|#:| |R| |=>| |R|)|#:| |O|‹|R|›|↵|#namespace| |Five| |{|→|#class| |ROTK|(|wu|#:| |string|)|↵|#class| |Y|#:| |Five'ROTK|←|↵|}|↵|#class| |Y|#:| |Five'ROTK|
-//│ Parsed: {class A(foo: unit, => unit,) {}; class B(): A {}; class C[T](set: T, => unit, get: unit, => T,) {}; class D(): C‹number› {}; trait Wu(x: bool,): {}; class WuWu(y: bool,): Wu {}; trait WuWuWu(z: bool,): WuWu: {}; trait Never(w: unit, => nothing,): WuWuWu: {}; class VG[T](x: T,) {}; class Home[T](y: T,): VG‹string› {}; trait O[I](xx: I, => I,): {}; class OR[R](xx: R, => R,): O‹R› {}; namespace Five(): {class ROTK(wu: string,) {}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+class Y(): Five'ROTK {}
+//│ |#class| |A| |{|→|#let| |foo|#:| |unit| |=>| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›| |{|→|#let| |set|#:| |T| |=>| |unit|↵|#let| |get|#:| |unit| |=>| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#let| |w|#:| |unit| |=>| |nothing|←|↵|}|↵|#class| |VG|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›| |{|→|#let| |xx|#:| |I| |=>| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#let| |xx|#:| |R| |=>| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
+//│ Parsed: {class A() {fun foo: [] -> unit -> unit}; class B(): A {}; class C[T]() {fun set: [] -> T -> unit; fun get: [] -> unit -> T}; class D(): C‹number› {}; trait Wu(): {fun x: [] -> bool}; class WuWu(): Wu {fun y: [] -> bool}; trait WuWuWu(): WuWu: {fun z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> unit -> nothing}; class VG[T]() {fun x: [] -> T}; class Home[T](): VG‹string› {fun y: [] -> T}; trait O[I](): {fun xx: [] -> I -> I}; class OR[R](): O‹R› {fun xx: [] -> R -> R}; namespace Five(): {class ROTK() {fun wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 7a7e4511a4..3f2eecb239 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -1,16 +1,40 @@
 :NewParser
 :ParseOnly
-trait IFoo(a: string, b: number => number, c: unit => bool, d: string => unit)
-trait II<T>(test: T => number)
-let create: unit => (v: number)
-let get: (t: string) => string
-trait IEvent(callback: unit => number => unit)
-trait SearchFunc(__call: string => string => bool)
-trait StringArray(__index: number => string)
-trait Counter(__call: number => string, interval: number, reset: unit => unit)
-trait Simple(a: number, b: bool => string)
-trait Simple2<T>(abc: T)
-trait Next: Simple
-trait TTT<T>(ttt: T => T)
-//│ |#trait| |IFoo|(|a|#:| |string|,| |b|#:| |number| |=>| |number|,| |c|#:| |unit| |=>| |bool|,| |d|#:| |string| |=>| |unit|)|↵|#trait| |II|‹|T|›|(|test|#:| |T| |=>| |number|)|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|)|↵|#let| |get|#:| |(|t|#:| |string|)| |=>| |string|↵|#trait| |IEvent|(|callback|#:| |unit| |=>| |number| |=>| |unit|)|↵|#trait| |SearchFunc|(|__call|#:| |string| |=>| |string| |=>| |bool|)|↵|#trait| |StringArray|(|__index|#:| |number| |=>| |string|)|↵|#trait| |Counter|(|__call|#:| |number| |=>| |string|,| |interval|#:| |number|,| |reset|#:| |unit| |=>| |unit|)|↵|#trait| |Simple|(|a|#:| |number|,| |b|#:| |bool| |=>| |string|)|↵|#trait| |Simple2|‹|T|›|(|abc|#:| |T|)|↵|#trait| |Next|#:| |Simple|↵|#trait| |TTT|‹|T|›|(|ttt|#:| |T| |=>| |T|)|
-//│ Parsed: {trait IFoo(a: string, b: number, => number, c: unit, => bool, d: string, => unit,): {}; trait II[T](test: T, => number,): {}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(callback: unit, => number, => unit,): {}; trait SearchFunc(__call: string, => string, => bool,): {}; trait StringArray(__index: number, => string,): {}; trait Counter(__call: number, => string, interval: number, reset: unit, => unit,): {}; trait Simple(a: number, b: bool, => string,): {}; trait Simple2[T](abc: T,): {}; trait Next(): Simple: {}; trait TTT[T](ttt: T, => T,): {}}
+trait IFoo {
+  let a: string
+  let b: number => number
+  let c: unit => bool
+  let d: string => unit
+}
+trait II<T> {
+  let test: T => number
+}
+let create: unit => (v: number,)
+let get: (t: string,) => string
+trait IEvent {
+  let callback: unit => number => unit
+}
+trait SearchFunc {
+  let __call: string => string => bool
+}
+trait StringArray {
+  let __index: number => string
+}
+trait Counter {
+  let __call: number => string
+  let interval: number
+  let reset: unit => unit
+}
+trait Simple {
+  let a: number
+  let b: bool => string
+}
+trait Simple2<T> {
+  let abc: T
+}
+trait Next(): Simple {}
+trait TTT<T> {
+  let ttt: T => T
+}
+//│ |#trait| |IFoo| |{|→|#let| |a|#:| |string|↵|#let| |b|#:| |number| |=>| |number|↵|#let| |c|#:| |unit| |=>| |bool|↵|#let| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›| |{|→|#let| |test|#:| |T| |=>| |number|←|↵|}|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#let| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent| |{|→|#let| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc| |{|→|#let| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray| |{|→|#let| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter| |{|→|#let| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#let| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple| |{|→|#let| |a|#:| |number|↵|#let| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {fun a: [] -> string; fun b: [] -> number -> number; fun c: [] -> unit -> bool; fun d: [] -> string -> unit}; trait II[T](): {fun test: [] -> T -> number}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(): {fun callback: [] -> unit -> number -> unit}; trait SearchFunc(): {fun __call: [] -> string -> string -> bool}; trait StringArray(): {fun __index: [] -> number -> string}; trait Counter(): {fun __call: [] -> number -> string; fun interval: [] -> number; fun reset: [] -> unit -> unit}; trait Simple(): {fun a: [] -> number; fun b: [] -> bool -> string}; trait Simple2[T](): {fun abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index bbbe8eb4c5..20a97ba3d5 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -3,15 +3,19 @@
 let extend: T => U => (T) & (U)
 let foo: (T) & (U) => unit
 let over: (number => string) & (object => string) => string
-trait IA(x: number)
-trait IB(y: number)
+trait IA {
+  let x: number
+}
+trait IB {
+  let y: number
+}
 let iii: (IA) & (IB) => (IA) & (IB)
 let uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
 let iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
 let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
 let tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
-class A
-class B
+class A {}
+class B {}
 let inter: (A) & (B) => (A) & (B)
-//│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA|(|x|#:| |number|)|↵|#trait| |IB|(|y|#:| |number|)|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|↵|#class| |B|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
-//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(x: number,): {}; trait IB(y: number,): {}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
+//│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB| |{|→|#let| |y|#:| |number|←|↵|}|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A| |{||}|↵|#class| |B| |{||}|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
+//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(): {fun x: [] -> number}; trait IB(): {fun y: [] -> number}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index f0a5dfe0dc..2de1cf4fa7 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -2,8 +2,10 @@
 :ParseOnly
 let multi1: number => number
 let multi3: unit => unit
-class Foo: Base
-trait AnotherBase(y: string)
+class Foo(): Base {}
+trait AnotherBase {
+  let y: string
+}
 namespace N {
   let f: unit => unit
   let g: unit => unit
@@ -11,8 +13,10 @@ namespace N {
 }
 let multi2: string => string
 let multi4: unit => unit
-trait Base(a: number)
-class AnotherFoo: AnotherBase
+trait Base {
+  let a: number
+}
+class AnotherFoo(): AnotherBase {}
 let multi5: unit => unit
-//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|#:| |Base|↵|#trait| |AnotherBase|(|y|#:| |string|)|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(|a|#:| |number|)|↵|#class| |AnotherFoo|#:| |AnotherBase|↵|#let| |multi5|#:| |unit| |=>| |unit|
-//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(y: string,): {}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(a: number,): {}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
+//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#let| |multi5|#:| |unit| |=>| |unit|
+//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(): {fun y: [] -> string}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(): {fun a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index dc2cd60edb..53a710b56a 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -3,22 +3,30 @@
 namespace N1 {
   let f: anything => number
   let ff: anything => number
-  class C(f: unit => unit)
-  trait I(f: unit => number)
+  class C {
+    let f: unit => unit
+  }
+  trait I {
+    let f: unit => number
+  }
   namespace N2 {
     let fff: bool => number
     let gg: N1'C => N1'C
-    class BBB: N1'C
+    class BBB(): N1'C {}
   }
 }
 namespace AA {
   let f: anything => string
-  class C(f: unit => unit)
-  trait I(f: unit => number)
+  class C {
+    let f: unit => unit
+  }
+  trait I {
+    let f: unit => number
+  }
   namespace N2 {
   }
 }
 let f1: N1'C => N1'C
 let f2: AA'C => AA'C
-//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|#:| |N1'C|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |C|(|f|#:| |unit| |=>| |unit|)|↵|#trait| |I|(|f|#:| |unit| |=>| |number|)|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C(f: unit, => unit,) {}; trait I(f: unit, => number,): {}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
+//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 9a4119d460..fab4395089 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -4,16 +4,21 @@ let buildName: string => (string) | (undefined) => string
 let buildName2: string => (string) | (undefined) => string
 let buildName3: string => MutArray<string> => string
 let buildName4: string => MutArray<anything> => string
-trait SquareConfig(color: (string) | (undefined), width: (number) | (undefined))
+trait SquareConfig {
+  let color: (string) | (undefined)
+  let width: (number) | (undefined)
+}
 let did: number => (number => number) | (undefined) => number
 let getOrElse: (MutArray<object>) | (undefined) => object
-class ABC
+class ABC {}
 let testABC: (ABC) | (undefined) => unit
 let testSquareConfig: (SquareConfig) | (undefined) => unit
 let err: ((number, string, )) | (undefined) => unit
 let toStr: ((number) | (bool)) | (undefined) => string
 let boo: ((T) & (U)) | (undefined) => unit
-class B<T>(b: T)
+class B<T> {
+  let b: T
+}
 let boom: (B<nothing>) | (undefined) => anything
-//│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig|(|color|#:| |(|string|)| ||| |(|undefined|)|,| |width|#:| |(|number|)| ||| |(|undefined|)|)|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›|(|b|#:| |T|)|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
-//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(color: | (string,) (undefined,), width: | (number,) (undefined,),): {}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T](b: T,) {}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
+//│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC| |{||}|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›| |{|→|#let| |b|#:| |T|←|↵|}|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
+//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(): {fun color: [] -> (string,) | (undefined,); fun width: [] -> (number,) | (undefined,)}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T]() {fun b: [] -> T}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 88d3e61eb4..df88907109 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,14 +1,16 @@
 :NewParser
 :ParseOnly
 let f: (number => string) & (string => string)
-class M(foo: (number => string) & (string => string))
+class M {
+  let foo: (number => string) & (string => string)
+}
 let app: ((string => unit) => number => unit) & ((string => unit) => string => unit)
 let create: (number => unit => bool) & (bool => unit => bool)
 let g0: (MutArray<string> => string) & (MutArray<object> => string)
 let db: (number => MutArray<number>) & (object => MutArray<number>)
-class N
+class N {}
 let id: (M => unit) & (N => unit)
-let tst: ((z: number) => (y: string)) & ((z: bool) => (y: string))
+let tst: ((z: number,) => (y: string,)) & ((z: bool,) => (y: string,))
 let op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
 let swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
 let u: ((number) | (bool) => string) & (object => string)
@@ -16,33 +18,35 @@ let doSome: anything => unit /* warning: the overload of function doSome is not
 namespace XX {
   let f: T => anything => string /* warning: the overload of function f is not supported yet. */
 }
-class WWW(F: T => anything /* warning: the overload of function F is not supported yet. */)
+class WWW {
+  let F: T => anything /* warning: the overload of function F is not supported yet. */
+}
 let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(|foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|)|↵|#let| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|)| |=>| |(|y|#:| |string|)|)| |&| |(|(|z|#:| |bool|)| |=>| |(|y|#:| |string|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW|(|F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|)|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
+//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#let| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW| |{|→|#let| |F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
 //│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 //│ ╙──      	                                       ^
 //│ ╔══[PARSE ERROR] Unexpected operator in expression position
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 //│ ╙──      	                                                                                               ^^
 //│ ╔══[PARSE ERROR] Unexpected newline in expression position
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 //│ ║        	                                                                                                 ^
-//│ ║  l.16: 	namespace XX {
+//│ ║  l.18: 	namespace XX {
 //│ ╙──      	
 //│ ╔══[PARSE ERROR] Unexpected 'namespace' keyword in expression position
-//│ ║  l.16: 	namespace XX {
+//│ ║  l.18: 	namespace XX {
 //│ ╙──      	^^^^^^^^^
 //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.15: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 //│ ║        	                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.16: 	namespace XX {
+//│ ║  l.18: 	namespace XX {
 //│ ╙──      	^^^^^^^^^^^^
 //│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
-//│ ║  l.16: 	namespace XX {
+//│ ║  l.18: 	namespace XX {
 //│ ║        	             ^
-//│ ║  l.17: 	  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
+//│ ║  l.19: 	  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
 //│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.18: 	}
+//│ ║  l.20: 	}
 //│ ╙──      	^
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M(foo: & (number, => string,) (string, => string,),) {}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {fun foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 753f794b68..865d55d103 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -10,9 +10,11 @@ let s: bool => ((string) | (number), (number) | (bool), )
 let s2: (bool, (string) | (number), ) => (string) | (number)
 let ex: T => U => (T, U, (T) & (U), )
 let foo: ((T) & (U), ) => unit
-let conv: (y: number) => ((y: number), (z: string), )
-class A(x: number)
-class B
+let conv: (y: number,) => ((y: number,), (z: string,), )
+class A {
+  let x: number
+}
+class B {}
 let swap: (A, B, ) => (B, A, )
-//│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|)| |=>| |(|(|y|#:| |number|)|,| |(|z|#:| |string|)|,| |)|↵|#class| |A|(|x|#:| |number|)|↵|#class| |B|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
-//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A(x: number,) {}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
+//│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|,|)| |=>| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B| |{||}|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
+//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A() {fun x: [] -> number}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index b416bd291d..cafc3b6c37 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,17 +1,29 @@
 :NewParser
 :ParseOnly
 let inc: T => number
-class CC<T>(print: T => unit)
+class CC<T> {
+  let print: T => unit
+}
 let con: T => U
-class Printer<T>(print: T => unit)
+class Printer<T> {
+  let print: T => unit
+}
 let setStringPrinter: Printer<string> => unit
 let getStringPrinter: unit => Printer<string>
 let foo: Printer<T> => T => T
 let foo2: Printer<T> => T => T
-class F<T>(x: T, GG: U => T)
-trait I<T>(x: T, GG: U => T)
-class FFF<T>(fff: T => unit)
+class F<T> {
+  let x: T
+  let GG: U => T
+}
+trait I<T> {
+  let x: T
+  let GG: U => T
+}
+class FFF<T> {
+  let fff: T => unit
+}
 let fff: FFF<string> => string => unit
 let getFFF: unit => FFF<number>
-//│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›|(|print|#:| |T| |=>| |unit|)|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#trait| |I|‹|T|›|(|x|#:| |T|,| |GG|#:| |U| |=>| |T|)|↵|#class| |FFF|‹|T|›|(|fff|#:| |T| |=>| |unit|)|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> T -> number; class CC[T](print: T, => unit,) {}; fun con: [] -> T -> U; class Printer[T](print: T, => unit,) {}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T](x: T, GG: U, => T,) {}; trait I[T](x: T, GG: U, => T,): {}; class FFF[T](fff: T, => unit,) {}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
+//│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›| |{|→|#let| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> T -> number; class CC[T]() {fun print: [] -> T -> unit}; fun con: [] -> T -> U; class Printer[T]() {fun print: [] -> T -> unit}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T]() {fun x: [] -> T; fun GG: [] -> U -> T}; trait I[T](): {fun x: [] -> T; fun GG: [] -> U -> T}; class FFF[T]() {fun fff: [] -> T -> unit}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}

From ca9904640eb70e743650f01111aab8032a0e2105 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 16:45:54 +0800
Subject: [PATCH 11/40] Add comments

---
 shared/src/main/scala/mlscript/NewLexer.scala | 10 +++++++
 .../src/main/scala/mlscript/NewParser.scala   |  5 +++-
 shared/src/test/diff/parser/Comments.mls      | 14 +++------
 ts2mls/js/src/test/diff/Overload.d.mls        | 30 ++-----------------
 4 files changed, 20 insertions(+), 39 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewLexer.scala b/shared/src/main/scala/mlscript/NewLexer.scala
index 7369cc02b8..64d2e12c45 100644
--- a/shared/src/main/scala/mlscript/NewLexer.scala
+++ b/shared/src/main/scala/mlscript/NewLexer.scala
@@ -84,6 +84,16 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
         val (txt, k) =
           takeWhile(j)(c => c =/= '\n')
         go(k, COMMENT(txt))
+      case '/' if bytes.lift(i + 1).contains('*') =>
+        val j = i + 2
+        var prev1 = '/'; var prev2 = '*'
+        val (txt, k) =
+          takeWhile(j)(c => {
+            val r = prev1 =/= '*' || prev2 =/= '/'
+            prev1 = prev2; prev2 = c
+            r
+          })
+        go(k, COMMENT(txt.dropRight(2)))
       case BracketKind(Left(k)) => go(i + 1, OPEN_BRACKET(k))
       case BracketKind(Right(k)) => go(i + 1, CLOSE_BRACKET(k))
       case '\n' =>
diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala
index 2e2993451b..ea9366f88b 100644
--- a/shared/src/main/scala/mlscript/NewParser.scala
+++ b/shared/src/main/scala/mlscript/NewParser.scala
@@ -137,7 +137,10 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
   
   private def cur(implicit l: Line, n: Name) = {
     if (dbg) printDbg(s"? ${n.value}\t\tinspects ${summarizeCur}    [at l.${l.value}]")
-    _cur
+    _cur.dropWhile(_._1 match {
+      case COMMENT(_) => true
+      case _ => false
+    })
   }
   
   def consume(implicit l: Line, n: Name): Unit = {
diff --git a/shared/src/test/diff/parser/Comments.mls b/shared/src/test/diff/parser/Comments.mls
index 9dc5cdda90..a7c2f6a4f5 100644
--- a/shared/src/test/diff/parser/Comments.mls
+++ b/shared/src/test/diff/parser/Comments.mls
@@ -2,14 +2,8 @@
 // TODO comments
 1 // whoops
 //│ |1| |/* whoops*/|
-//│ ╔══[PARSE ERROR] Unexpected comment in expression position
-//│ ║  l.3: 	1 // whoops
-//│ ╙──     	  ^^^^^^^^^
-//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here
-//│ ║  l.3: 	1 // whoops
-//│ ╙──     	           ^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.3: 	1 // whoops
-//│ ╙──     	^^^^^^^^^^^
-//│ Parsed: {1 (undefined,)}
+//│ Parsed: {1}
 
+2 /* whoops */
+//│ |2| |/* whoops */|
+//│ Parsed: {2}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index df88907109..d95692b4b9 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -22,31 +22,5 @@ class WWW {
   let F: T => anything /* warning: the overload of function F is not supported yet. */
 }
 let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#let| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/*| |warning|#:| |the| |overload| |#of| |function| |doSome| |is| |not| |supported| |yet|.| |*/|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/*| |warning|#:| |the| |overload| |#of| |function| |f| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#class| |WWW| |{|→|#let| |F|#:| |T| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |F| |is| |not| |supported| |yet|.| |*/|←|↵|}|↵|#let| |baz|#:| |unit| |=>| |anything| |/*| |warning|#:| |the| |overload| |#of| |function| |baz| |is| |not| |supported| |yet|.| |*/|
-//│ ╔══[PARSE ERROR] Unexpected ':' keyword in expression position
-//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ╙──      	                                       ^
-//│ ╔══[PARSE ERROR] Unexpected operator in expression position
-//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ╙──      	                                                                                               ^^
-//│ ╔══[PARSE ERROR] Unexpected newline in expression position
-//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ║        	                                                                                                 ^
-//│ ║  l.18: 	namespace XX {
-//│ ╙──      	
-//│ ╔══[PARSE ERROR] Unexpected 'namespace' keyword in expression position
-//│ ║  l.18: 	namespace XX {
-//│ ╙──      	^^^^^^^^^
-//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
-//│ ║  l.17: 	let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
-//│ ║        	                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.18: 	namespace XX {
-//│ ╙──      	^^^^^^^^^^^^
-//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead
-//│ ║  l.18: 	namespace XX {
-//│ ║        	             ^
-//│ ║  l.19: 	  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
-//│ ║        	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//│ ║  l.20: 	}
-//│ ╙──      	^
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {fun foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> /*[(unit,), (warning[(the[(overload[(function[(is[(doSome,), (not[(supported[(.[(yet,), (XX,)],)],)],)],)],)],)],)],)]}
+//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#let| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW| |{|→|#let| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#let| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {fun foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> unit; namespace XX(): {fun f: [] -> T -> anything -> string}; class WWW() {fun F: [] -> T -> anything}; fun baz: [] -> unit -> anything}

From 50b8c1457d2dfc06841f84e65c150b55ad548559 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 13 Sep 2022 16:51:08 +0800
Subject: [PATCH 12/40] Update fun/let

---
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  | 2 +-
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 2 +-
 ts2mls/js/src/test/diff/Enum.d.mls            | 2 +-
 ts2mls/js/src/test/diff/Heritage.d.mls        | 2 +-
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   | 2 +-
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 2 +-
 ts2mls/js/src/test/diff/Intersection.d.mls    | 2 +-
 ts2mls/js/src/test/diff/MultiFiles.d.mls      | 2 +-
 ts2mls/js/src/test/diff/Namespace.d.mls       | 2 +-
 ts2mls/js/src/test/diff/Optional.d.mls        | 2 +-
 ts2mls/js/src/test/diff/Overload.d.mls        | 2 +-
 ts2mls/js/src/test/diff/Tuple.d.mls           | 2 +-
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 2 +-
 ts2mls/js/src/test/diff/Union.d.mls           | 2 +-
 14 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 6991ddf823..6e478893d0 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -25,4 +25,4 @@ trait Barrrrrrrrr {
 let inn2: Barrrrrrrrr => unit
 let out2: unit => Barrrrrrrrr
 //│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |number| |=>| |number| |=>| |number|↵|#let| |sub|#:| |number| |=>| |number| |=>| |number|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |anything| |=>| |anything|↵|#let| |odd|#:| |number| |=>| |bool|↵|#let| |isnull|#:| |anything| |=>| |bool|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |null| |=>| |null|↵|#let| |un|#:| |undefined| |=>| |undefined|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |number| |=>| |number|↵|#let| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#let| |inn|#:| |Foooooo| |=>| |unit|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#let| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo() {fun ooooooo: [] -> number}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(): {fun rrrrrrr: [] -> number}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
+//│ Parsed: {let hello: [] -> unit -> unit; let add: [] -> number -> number -> number; let sub: [] -> number -> number -> number; let foo: [] -> unit -> number; let id: [] -> anything -> anything; let odd: [] -> number -> bool; let isnull: [] -> anything -> bool; let bar: [] -> unit -> anything; let nu: [] -> null -> null; let un: [] -> undefined -> undefined; let fail: [] -> unit -> nothing; let create: [] -> unit -> object; let pa: [] -> number -> number; let wtf: [] -> anything -> unit; class Foooooo() {let ooooooo: [] -> number}; let inn: [] -> Foooooo -> unit; let out: [] -> unit -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; let inn2: [] -> Barrrrrrrrr -> unit; let out2: [] -> unit -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index 49b8a9df5c..ddf42e1e5f 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -18,4 +18,4 @@ class TTT<T> {
   let ttt2: T => T
 }
 //│ |#class| |Student| |{|→|#let| |name|#:| |string|↵|#let| |isFriend|#:| |Student| |=>| |bool|↵|#let| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#let| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›| |{|→|#let| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ| |{|→|#let| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer| |{||}|↵|#class| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|↵|#let| |ttt2|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {class Student() {fun name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}
+//│ Parsed: {class Student() {let name: [] -> string; let isFriend: [] -> Student -> bool; let addScore: [] -> string -> number -> unit; let getID: [] -> unit -> number}; class Foo[T]() {let bar: [] -> T -> unit}; class EZ() {let inc: [] -> number -> number}; class Outer() {}; class TTT[T]() {let ttt: [] -> T -> T; let ttt2: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index a9ce8f67b9..8eb2d7a5bf 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -4,4 +4,4 @@ let pass: int => bool
 let stop: unit => int
 let g: int => int
 //│ |#let| |pass|#:| |int| |=>| |bool|↵|#let| |stop|#:| |unit| |=>| |int|↵|#let| |g|#:| |int| |=>| |int|
-//│ Parsed: {fun pass: [] -> int -> bool; fun stop: [] -> unit -> int; fun g: [] -> int -> int}
+//│ Parsed: {let pass: [] -> int -> bool; let stop: [] -> unit -> int; let g: [] -> int -> int}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 1280c5bf40..f929bb4c08 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -41,4 +41,4 @@ namespace Five {
 }
 class Y(): Five'ROTK {}
 //│ |#class| |A| |{|→|#let| |foo|#:| |unit| |=>| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›| |{|→|#let| |set|#:| |T| |=>| |unit|↵|#let| |get|#:| |unit| |=>| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#let| |w|#:| |unit| |=>| |nothing|←|↵|}|↵|#class| |VG|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›| |{|→|#let| |xx|#:| |I| |=>| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#let| |xx|#:| |R| |=>| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
-//│ Parsed: {class A() {fun foo: [] -> unit -> unit}; class B(): A {}; class C[T]() {fun set: [] -> T -> unit; fun get: [] -> unit -> T}; class D(): C‹number› {}; trait Wu(): {fun x: [] -> bool}; class WuWu(): Wu {fun y: [] -> bool}; trait WuWuWu(): WuWu: {fun z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> unit -> nothing}; class VG[T]() {fun x: [] -> T}; class Home[T](): VG‹string› {fun y: [] -> T}; trait O[I](): {fun xx: [] -> I -> I}; class OR[R](): O‹R› {fun xx: [] -> R -> R}; namespace Five(): {class ROTK() {fun wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ Parsed: {class A() {let foo: [] -> unit -> unit}; class B(): A {}; class C[T]() {let set: [] -> T -> unit; let get: [] -> unit -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {let w: [] -> unit -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {let xx: [] -> I -> I}; class OR[R](): O‹R› {let xx: [] -> R -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index eb105d2710..775f040b1c 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -4,4 +4,4 @@ let h1: (number => number) => number => number
 let h2: string => unit => string
 let h3: (number => number) => (number => number) => number => number
 //│ |#let| |h1|#:| |(|number| |=>| |number|)| |=>| |number| |=>| |number|↵|#let| |h2|#:| |string| |=>| |unit| |=>| |string|↵|#let| |h3|#:| |(|number| |=>| |number|)| |=>| |(|number| |=>| |number|)| |=>| |number| |=>| |number|
-//│ Parsed: {fun h1: [] -> (number -> number) -> number -> number; fun h2: [] -> string -> unit -> string; fun h3: [] -> (number -> number) -> (number -> number) -> number -> number}
+//│ Parsed: {let h1: [] -> (number -> number) -> number -> number; let h2: [] -> string -> unit -> string; let h3: [] -> (number -> number) -> (number -> number) -> number -> number}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 3f2eecb239..f704a077a2 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -37,4 +37,4 @@ trait TTT<T> {
   let ttt: T => T
 }
 //│ |#trait| |IFoo| |{|→|#let| |a|#:| |string|↵|#let| |b|#:| |number| |=>| |number|↵|#let| |c|#:| |unit| |=>| |bool|↵|#let| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›| |{|→|#let| |test|#:| |T| |=>| |number|←|↵|}|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#let| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent| |{|→|#let| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc| |{|→|#let| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray| |{|→|#let| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter| |{|→|#let| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#let| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple| |{|→|#let| |a|#:| |number|↵|#let| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {fun a: [] -> string; fun b: [] -> number -> number; fun c: [] -> unit -> bool; fun d: [] -> string -> unit}; trait II[T](): {fun test: [] -> T -> number}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(): {fun callback: [] -> unit -> number -> unit}; trait SearchFunc(): {fun __call: [] -> string -> string -> bool}; trait StringArray(): {fun __index: [] -> number -> string}; trait Counter(): {fun __call: [] -> number -> string; fun interval: [] -> number; fun reset: [] -> unit -> unit}; trait Simple(): {fun a: [] -> number; fun b: [] -> bool -> string}; trait Simple2[T](): {fun abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> T -> T}}
+//│ Parsed: {trait IFoo(): {let a: [] -> string; let b: [] -> number -> number; let c: [] -> unit -> bool; let d: [] -> string -> unit}; trait II[T](): {let test: [] -> T -> number}; let create: [] -> unit -> (v: number,); let get: [] -> (t: string,) -> string; trait IEvent(): {let callback: [] -> unit -> number -> unit}; trait SearchFunc(): {let __call: [] -> string -> string -> bool}; trait StringArray(): {let __index: [] -> number -> string}; trait Counter(): {let __call: [] -> number -> string; let interval: [] -> number; let reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; let b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {let ttt: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 20a97ba3d5..68881f6027 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -18,4 +18,4 @@ class A {}
 class B {}
 let inter: (A) & (B) => (A) & (B)
 //│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB| |{|→|#let| |y|#:| |number|←|↵|}|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A| |{||}|↵|#class| |B| |{||}|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
-//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(): {fun x: [] -> number}; trait IB(): {fun y: [] -> number}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
+//│ Parsed: {let extend: [] -> T -> U -> ((T,) & (U,)); let foo: [] -> ((T,) & (U,)) -> unit; let over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; let iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); let uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); let iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); let arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); let tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; let inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index 2de1cf4fa7..cf528c63c9 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -19,4 +19,4 @@ trait Base {
 class AnotherFoo(): AnotherBase {}
 let multi5: unit => unit
 //│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#let| |multi5|#:| |unit| |=>| |unit|
-//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(): {fun y: [] -> string}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(): {fun a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
+//│ Parsed: {let multi1: [] -> number -> number; let multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {let f: [] -> unit -> unit; let g: [] -> unit -> unit; let h: [] -> unit -> unit}; let multi2: [] -> string -> string; let multi4: [] -> unit -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; let multi5: [] -> unit -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 53a710b56a..f3b62a4ce8 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -29,4 +29,4 @@ namespace AA {
 let f1: N1'C => N1'C
 let f2: AA'C => AA'C
 //│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
+//│ Parsed: {namespace N1(): {let f: [] -> anything -> number; let ff: [] -> anything -> number; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {let fff: [] -> bool -> number; let gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {let f: [] -> anything -> string; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {}}; let f1: [] -> N1'C -> N1'C; let f2: [] -> AA'C -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index fab4395089..c230030fe9 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -21,4 +21,4 @@ class B<T> {
 }
 let boom: (B<nothing>) | (undefined) => anything
 //│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC| |{||}|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›| |{|→|#let| |b|#:| |T|←|↵|}|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
-//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(): {fun color: [] -> (string,) | (undefined,); fun width: [] -> (number,) | (undefined,)}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T]() {fun b: [] -> T}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
+//│ Parsed: {let buildName: [] -> string -> ((string,) | (undefined,)) -> string; let buildName2: [] -> string -> ((string,) | (undefined,)) -> string; let buildName3: [] -> string -> MutArray[string] -> string; let buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; let did: [] -> number -> ((number -> number,) | (undefined,)) -> number; let getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; let testABC: [] -> ((ABC,) | (undefined,)) -> unit; let testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; let err: [] -> (((number, string,),) | (undefined,)) -> unit; let toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; let boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T]() {let b: [] -> T}; let boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index d95692b4b9..542d3dbcda 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -23,4 +23,4 @@ class WWW {
 }
 let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
 //│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#let| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW| |{|→|#let| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#let| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {fun foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> unit; namespace XX(): {fun f: [] -> T -> anything -> string}; class WWW() {fun F: [] -> T -> anything}; fun baz: [] -> unit -> anything}
+//│ Parsed: {let f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; let app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); let create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); let g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); let db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; let id: [] -> (M -> unit,) & (N -> unit,); let tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); let op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); let swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); let u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); let doSome: [] -> anything -> unit; namespace XX(): {let f: [] -> T -> anything -> string}; class WWW() {let F: [] -> T -> anything}; let baz: [] -> unit -> anything}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 865d55d103..d61a723374 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -17,4 +17,4 @@ class A {
 class B {}
 let swap: (A, B, ) => (B, A, )
 //│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|,|)| |=>| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B| |{||}|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
-//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A() {fun x: [] -> number}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
+//│ Parsed: {let key: [] -> (string, bool,) -> string; let value: [] -> (string, bool,) -> bool; let third: [] -> (number, number, number,) -> number; let vec2: [] -> number -> number -> (number, number,); let twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; let tupleIt: [] -> string -> (unit -> string,); let s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); let s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); let ex: [] -> T -> U -> (T, U, (T,) & (U,),); let foo: [] -> ((T,) & (U,)) -> unit; let conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; let swap: [] -> (A, B,) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index cafc3b6c37..b67b35ab4d 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -26,4 +26,4 @@ class FFF<T> {
 let fff: FFF<string> => string => unit
 let getFFF: unit => FFF<number>
 //│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›| |{|→|#let| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> T -> number; class CC[T]() {fun print: [] -> T -> unit}; fun con: [] -> T -> U; class Printer[T]() {fun print: [] -> T -> unit}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T]() {fun x: [] -> T; fun GG: [] -> U -> T}; trait I[T](): {fun x: [] -> T; fun GG: [] -> U -> T}; class FFF[T]() {fun fff: [] -> T -> unit}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
+//│ Parsed: {let inc: [] -> T -> number; class CC[T]() {let print: [] -> T -> unit}; let con: [] -> T -> U; class Printer[T]() {let print: [] -> T -> unit}; let setStringPrinter: [] -> Printer[string] -> unit; let getStringPrinter: [] -> unit -> Printer[string]; let foo: [] -> Printer[T] -> T -> T; let foo2: [] -> Printer[T] -> T -> T; class F[T]() {let x: [] -> T; let GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; let GG: [] -> U -> T}; class FFF[T]() {let fff: [] -> T -> unit}; let fff: [] -> FFF[string] -> string -> unit; let getFFF: [] -> unit -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 14daeda466..df0ed7dd0b 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -8,4 +8,4 @@ let get2: ((string, string, )) | ((number, string, )) => string
 let typeVar: (T) | (U) => (T) | (U)
 let uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
 //│ |#let| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#let| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#let| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#let| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#let| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#let| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#let| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}
+//│ Parsed: {let getString: [] -> (((string,) | (number,),) | (bool,)) -> string; let test: [] -> bool -> ((string,) | (number,)); let run: [] -> ((number -> number,) | (number -> string,)) -> anything; let get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; let get2: [] -> (((string, string,),) | ((number, string,),)) -> string; let typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); let uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}

From 1bb4c2f6800d946480c401703b3fc2687d3fb584 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 14 Sep 2022 11:07:36 +0800
Subject: [PATCH 13/40] Fix nested type arguments

---
 shared/src/main/scala/mlscript/NewLexer.scala | 4 +++-
 ts2mls/js/src/test/diff/Array.d.mls           | 8 ++------
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewLexer.scala b/shared/src/main/scala/mlscript/NewLexer.scala
index ba4ab86436..11d590e6b6 100644
--- a/shared/src/main/scala/mlscript/NewLexer.scala
+++ b/shared/src/main/scala/mlscript/NewLexer.scala
@@ -129,6 +129,8 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
           val (name, k) = takeWhile(j)(isIdentChar)
           go(k, SELECT(name))
         }
+        else if (c === '>' && n.length > 1 && n.foldLeft(true)((r, i) => r && (i === c)))
+          go(i + 1, IDENT(">", true))
         else go(j, if (isSymKeyword.contains(n)) KEYWORD(n) else IDENT(n, true))
       case _ if isDigit(c) =>
         val (str, j) = takeWhile(i)(isDigit)
@@ -174,7 +176,7 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
               if (k0 =/= k1)
                 raise(ErrorReport(msg"Mistmatched closing ${k1.name}" -> S(l1) ::
                   msg"does not correspond to opening ${k0.name}" -> S(l0) :: Nil, source = Parsing))
-              go(rest, false, stack, BRACKETS(k0, acc.reverse)(l0.right ++ l1.left) -> (l0 ++ l1) :: oldAcc)
+              go(rest, true, stack, BRACKETS(k0, acc.reverse)(l0.right ++ l1.left) -> (l0 ++ l1) :: oldAcc)
             case Nil =>
               raise(ErrorReport(msg"Unexpected closing ${k1.name}" -> S(l1) :: Nil, source = Parsing))
               go(rest, false, stack, acc)
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 7aa5fe2da7..33978d15c0 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -19,9 +19,5 @@ class Temp<T> {
 }
 let ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
 let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
-//│ ╔══[PARSE ERROR] Unmatched opening angle bracket
-//│ ║  l.21: 	let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
-//│ ║        	                                           ^
-//│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator
-//│ |T|>>|Temp|
-//│ Parsed: {>> (T,) (Temp,)}
+//│ |#let| |first|#:| |MutArray|‹|string|›| |=>| |string|↵|#let| |getZero3|#:| |unit| |=>| |MutArray|‹|number|›|↵|#let| |first2|#:| |MutArray|‹|number| |=>| |number|›| |=>| |number| |=>| |number|↵|#let| |doEs|#:| |MutArray|‹|int|›| |=>| |MutArray|‹|int|›|↵|#class| |C| |{||}|↵|#trait| |I| |{|→|#let| |i|#:| |number|←|↵|}|↵|#let| |doCs|#:| |MutArray|‹|C|›| |=>| |MutArray|‹|C|›|↵|#let| |doIs|#:| |MutArray|‹|I|›| |=>| |MutArray|‹|I|›|↵|#let| |inter|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›| |=>| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#let| |clean|#:| |MutArray|‹|(|string|,| |number|,| |)|›| |=>| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#let| |translate|#:| |MutArray|‹|T|›| |=>| |MutArray|‹|U|›|↵|#let| |uu|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›| |=>| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#let| |ta|#:| |MutArray|‹|Temp|‹|bool|›|›| |=>| |MutArray|‹|Temp|‹|bool|›|›|↵|#let| |tat|#:| |MutArray|‹|Temp|‹|T|›|›| |=>| |MutArray|‹|Temp|‹|T|›|›|
+//│ Parsed: {let first: [] -> MutArray[string] -> string; let getZero3: [] -> unit -> MutArray[number]; let first2: [] -> MutArray[number -> number] -> number -> number; let doEs: [] -> MutArray[int] -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; let doCs: [] -> MutArray[C] -> MutArray[C]; let doIs: [] -> MutArray[I] -> MutArray[I]; let inter: [] -> MutArray[(U,) & (T,)] -> MutArray[(U,) & (T,)]; let clean: [] -> MutArray[(string, number,)] -> MutArray[(string, number,)]; let translate: [] -> MutArray[T] -> MutArray[U]; let uu: [] -> MutArray[(number,) | (bool,)] -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; let ta: [] -> MutArray[Temp[bool]] -> MutArray[Temp[bool]]; let tat: [] -> MutArray[Temp[T]] -> MutArray[Temp[T]]}

From 7fce986d2d3ecda0ca22d08b2f2159ab42b1d138 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 14 Sep 2022 11:33:12 +0800
Subject: [PATCH 14/40] Hide warning temporarily

---
 shared/src/main/scala/mlscript/JSBackend.scala      | 1 +
 shared/src/main/scala/mlscript/MLParser.scala       | 1 +
 shared/src/main/scala/mlscript/Typer.scala          | 3 +++
 shared/src/main/scala/mlscript/TyperDatatypes.scala | 1 +
 shared/src/main/scala/mlscript/codegen/Scope.scala  | 4 +++-
 5 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/shared/src/main/scala/mlscript/JSBackend.scala b/shared/src/main/scala/mlscript/JSBackend.scala
index d3a3e068c3..a4a9aeaf9c 100644
--- a/shared/src/main/scala/mlscript/JSBackend.scala
+++ b/shared/src/main/scala/mlscript/JSBackend.scala
@@ -459,6 +459,7 @@ class JSBackend {
         traits += topLevelScope.declareTrait(name, tparams map { _.name }, body, methods)
       case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _) =>
         classes += topLevelScope.declareClass(name, tparams map { _.name }, baseType, members)
+      case TypeDef(Nms, TypeName(name), _, _, _, members, _) => () // TODO: deal with namespace
     }
     (traits.toList, classes.toList)
   }
diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala
index d49a5fee62..a7f5f70841 100644
--- a/shared/src/main/scala/mlscript/MLParser.scala
+++ b/shared/src/main/scala/mlscript/MLParser.scala
@@ -204,6 +204,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {
           ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil)
       }
       case (k @ Als, id, ts) => "=" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil))
+      case (k @ Nms, id, _) => "=" ~ ty map (bod => TypeDef(k, id, Nil, bod, Nil, Nil, Nil)) // TODO: deal with namespaces
     })
   def tyParams[p: P]: P[Ls[TypeName]] =
     ("[" ~ tyName.rep(0, ",") ~ "]").?.map(_.toList.flatten)
diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala
index 7fe06560b3..45067c0a25 100644
--- a/shared/src/main/scala/mlscript/Typer.scala
+++ b/shared/src/main/scala/mlscript/Typer.scala
@@ -307,6 +307,8 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool)
                   case Trt => trtNameToNomTag(td)(tyTp(tyLoc, "trait tag"), ctx)
                   case Als => err(
                     msg"Type alias ${name.capitalize} cannot be used as a type tag", tyLoc)(raise)
+                  case Nms => err(
+                    msg"Namespaces ${name.capitalize} cannot be used as a type tag", tyLoc)(raise)
                 }
                 case _ => e()
               }
@@ -750,6 +752,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool)
             case Some(td) =>
               td.kind match {
                 case Als => err(msg"can only match on classes and traits", pat.toLoc)(raise)
+                case Nms => err(msg"can only match on classes and traits", pat.toLoc)(raise)
                 case Cls => clsNameToNomTag(td)(tp(pat.toLoc, "class pattern"), ctx)
                 case Trt => trtNameToNomTag(td)(tp(pat.toLoc, "trait pattern"), ctx)
               }
diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala
index def866daa1..22b7845765 100644
--- a/shared/src/main/scala/mlscript/TyperDatatypes.scala
+++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala
@@ -234,6 +234,7 @@ abstract class TyperDatatypes extends TyperHelpers { self: Typer =>
         else TopType
       subst(td.kind match {
         case Als => td.bodyTy
+        case Nms => td.bodyTy // TODO: deal with namespaces
         case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
         case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
       }, td.targs.lazyZip(targs).toMap) //.withProv(prov)
diff --git a/shared/src/main/scala/mlscript/codegen/Scope.scala b/shared/src/main/scala/mlscript/codegen/Scope.scala
index dd1ce4fe0c..1e39a9590a 100644
--- a/shared/src/main/scala/mlscript/codegen/Scope.scala
+++ b/shared/src/main/scala/mlscript/codegen/Scope.scala
@@ -4,7 +4,7 @@ import mlscript.utils.shorthands._
 import mlscript.{JSStmt, JSExpr, JSLetDecl}
 import mlscript.Type
 import scala.reflect.ClassTag
-import mlscript.{TypeName, Top, Bot, TypeDef, Als, Trt, Cls}
+import mlscript.{TypeName, Top, Bot, TypeDef, Als, Trt, Cls, Nms}
 import mlscript.MethodDef
 import mlscript.Term
 import mlscript.utils.{AnyOps, lastWords}
@@ -200,6 +200,8 @@ class Scope(name: Str, enclosing: Opt[Scope]) {
       declareTrait(name, tparams map { _.name }, body, mthdDefs)
     case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _) =>
       declareClass(name, tparams map { _.name }, baseType, members)
+    case TypeDef(Nms, TypeName(name), _, body, _, _, _) =>
+      declareTypeAlias(name, Ls(), body) // TODO: deal with namespaces
   }
 
   def declareClass(

From 1bd40975c43ae7e0b106cfcf4730e6edf43bfafa Mon Sep 17 00:00:00 2001
From: "Cunyuan(Holden) Gao" <neilkleistgao@bupt.edu.cn>
Date: Thu, 15 Sep 2022 09:21:34 +0800
Subject: [PATCH 15/40] Update shared/src/main/scala/mlscript/NewParser.scala

Co-authored-by: Lionel Parreaux <lionel.parreaux@gmail.com>
---
 shared/src/main/scala/mlscript/NewParser.scala | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala
index 73ff5ab86e..d9739c2062 100644
--- a/shared/src/main/scala/mlscript/NewParser.scala
+++ b/shared/src/main/scala/mlscript/NewParser.scala
@@ -137,10 +137,11 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
   
   private def cur(implicit l: Line, n: Name) = {
     if (dbg) printDbg(s"? ${n.value}\t\tinspects ${summarizeCur}    [at l.${l.value}]")
-    _cur.dropWhile(_._1 match {
+    while (_cur match {
       case COMMENT(_) => true
       case _ => false
-    })
+    }) consume
+    _cur
   }
   
   def consume(implicit l: Line, n: Name): Unit = {

From 7b09aae0e1d84c060b9f748ed3ef1962a482f6cd Mon Sep 17 00:00:00 2001
From: "Cunyuan(Holden) Gao" <neilkleistgao@bupt.edu.cn>
Date: Thu, 15 Sep 2022 09:21:44 +0800
Subject: [PATCH 16/40] Update
 ts2mls/js/src/main/scala/ts2mls/types/Converter.scala

Co-authored-by: Lionel Parreaux <lionel.parreaux@gmail.com>
---
 ts2mls/js/src/main/scala/ts2mls/types/Converter.scala | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 7bd3c56cb7..a6dd826ccb 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -83,7 +83,7 @@ object Converter {
     
     if (typeName === "trait ") body // anonymous interfaces
     else { // named interfaces and classes
-      val herirage =
+      val inheritance =
         if (parents.isEmpty) ""
         else parents.foldLeft("(): ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
       if (typeVars.isEmpty) s"$typeName$herirage $body"

From 15dfcb4da7fab4773e7afdae2e38a7d94abd362f Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 15 Sep 2022 09:28:56 +0800
Subject: [PATCH 17/40] Fix ce

---
 shared/src/main/scala/mlscript/NewParser.scala        | 4 ++--
 ts2mls/js/src/main/scala/ts2mls/types/Converter.scala | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala
index d9739c2062..a40598ba47 100644
--- a/shared/src/main/scala/mlscript/NewParser.scala
+++ b/shared/src/main/scala/mlscript/NewParser.scala
@@ -137,10 +137,10 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
   
   private def cur(implicit l: Line, n: Name) = {
     if (dbg) printDbg(s"? ${n.value}\t\tinspects ${summarizeCur}    [at l.${l.value}]")
-    while (_cur match {
+    while (!_cur.isEmpty && (_cur.head._1 match {
       case COMMENT(_) => true
       case _ => false
-    }) consume
+    })) consume
     _cur
   }
   
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index a6dd826ccb..b9dc9736b6 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -86,9 +86,9 @@ object Converter {
       val inheritance =
         if (parents.isEmpty) ""
         else parents.foldLeft("(): ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
-      if (typeVars.isEmpty) s"$typeName$herirage $body"
+      if (typeVars.isEmpty) s"$typeName$inheritance $body"
       else
-        s"$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$herirage $body" // TODO: add constraints
+        s"$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$inheritance $body" // TODO: add constraints
     }
   }
 }

From 921f1ff0514250a89e2dc8726d44c8f41fb99f4c Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 15 Sep 2022 09:41:05 +0800
Subject: [PATCH 18/40] Remove silent errors

---
 shared/src/main/scala/mlscript/JSBackend.scala     | 2 +-
 shared/src/main/scala/mlscript/codegen/Scope.scala | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/shared/src/main/scala/mlscript/JSBackend.scala b/shared/src/main/scala/mlscript/JSBackend.scala
index a4a9aeaf9c..2172884e24 100644
--- a/shared/src/main/scala/mlscript/JSBackend.scala
+++ b/shared/src/main/scala/mlscript/JSBackend.scala
@@ -459,7 +459,7 @@ class JSBackend {
         traits += topLevelScope.declareTrait(name, tparams map { _.name }, body, methods)
       case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _) =>
         classes += topLevelScope.declareClass(name, tparams map { _.name }, baseType, members)
-      case TypeDef(Nms, TypeName(name), _, _, _, members, _) => () // TODO: deal with namespace
+      case TypeDef(Nms, TypeName(name), _, _, _, members, _) => throw CodeGenError("Namespaces are not supported yet.") // TODO: deal with namespaces
     }
     (traits.toList, classes.toList)
   }
diff --git a/shared/src/main/scala/mlscript/codegen/Scope.scala b/shared/src/main/scala/mlscript/codegen/Scope.scala
index 1e39a9590a..227ddd7e5e 100644
--- a/shared/src/main/scala/mlscript/codegen/Scope.scala
+++ b/shared/src/main/scala/mlscript/codegen/Scope.scala
@@ -201,7 +201,7 @@ class Scope(name: Str, enclosing: Opt[Scope]) {
     case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _) =>
       declareClass(name, tparams map { _.name }, baseType, members)
     case TypeDef(Nms, TypeName(name), _, body, _, _, _) =>
-      declareTypeAlias(name, Ls(), body) // TODO: deal with namespaces
+      throw CodeGenError("Namespaces are not supported yet.") // TODO: deal with namespaces
   }
 
   def declareClass(

From 18664800e36e28feeb2e82445ca3f75aab9201c8 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 15 Sep 2022 09:48:38 +0800
Subject: [PATCH 19/40] Fix fun

---
 .../src/main/scala/ts2mls/TSNamespace.scala   |  6 +--
 ts2mls/js/src/test/diff/Array.d.mls           | 28 ++++++-------
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  | 40 +++++++++----------
 ts2mls/js/src/test/diff/Enum.d.mls            | 10 ++---
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   | 10 ++---
 ts2mls/js/src/test/diff/InterfaceMember.d.mls |  8 ++--
 ts2mls/js/src/test/diff/Intersection.d.mls    | 22 +++++-----
 ts2mls/js/src/test/diff/MultiFiles.d.mls      | 20 +++++-----
 ts2mls/js/src/test/diff/Namespace.d.mls       | 18 ++++-----
 ts2mls/js/src/test/diff/Optional.d.mls        | 28 ++++++-------
 ts2mls/js/src/test/diff/Overload.d.mls        | 30 +++++++-------
 ts2mls/js/src/test/diff/Tuple.d.mls           | 28 ++++++-------
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 20 +++++-----
 ts2mls/js/src/test/diff/Union.d.mls           | 18 ++++-----
 14 files changed, 143 insertions(+), 143 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index cc4ba9413b..f41e7a649f 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -47,9 +47,9 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
         // val fullName = getFullPath(name)
         mem match {
           case inter: TSIntersectionType => // overloaded functions
-            writer.writeln(s"${indent}let ${name}: ${Converter.convert(inter)}")
+            writer.writeln(s"${indent}fun ${name}: ${Converter.convert(inter)}")
           case f: TSFunctionType =>
-            writer.writeln(s"${indent}let ${name}: ${Converter.convert(f)}")
+            writer.writeln(s"${indent}fun ${name}: ${Converter.convert(f)}")
           // {
           //   val typeParams = f.typeVars.map((t) => t.name)
           //   if (typeParams.isEmpty)
@@ -58,7 +58,7 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
           //     writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(f)}")
           // }
           case overload @ TSIgnoredOverload(base, _) =>
-            writer.writeln(s"${indent}let ${name}: ${Converter.convert(overload)}")
+            writer.writeln(s"${indent}fun ${name}: ${Converter.convert(overload)}")
           // {
           //   val typeParams = base.typeVars.map((t) => t.name)
           //     if (typeParams.isEmpty)
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 33978d15c0..ffea1f6b50 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,23 +1,23 @@
 :NewParser
 :ParseOnly
-let first: MutArray<string> => string
-let getZero3: unit => MutArray<number>
-let first2: MutArray<number => number> => number => number
-let doEs: MutArray<int> => MutArray<int>
+fun first: MutArray<string> => string
+fun getZero3: unit => MutArray<number>
+fun first2: MutArray<number => number> => number => number
+fun doEs: MutArray<int> => MutArray<int>
 class C {}
 trait I {
   let i: number
 }
-let doCs: MutArray<C> => MutArray<C>
-let doIs: MutArray<I> => MutArray<I>
-let inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
-let clean: MutArray<(string, number, )> => MutArray<(string, number, )>
-let translate: MutArray<T> => MutArray<U>
-let uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
+fun doCs: MutArray<C> => MutArray<C>
+fun doIs: MutArray<I> => MutArray<I>
+fun inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
+fun clean: MutArray<(string, number, )> => MutArray<(string, number, )>
+fun translate: MutArray<T> => MutArray<U>
+fun uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
 class Temp<T> {
   let x: T
 }
-let ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
-let tat: MutArray<Temp<T>> => MutArray<Temp<T>>
-//│ |#let| |first|#:| |MutArray|‹|string|›| |=>| |string|↵|#let| |getZero3|#:| |unit| |=>| |MutArray|‹|number|›|↵|#let| |first2|#:| |MutArray|‹|number| |=>| |number|›| |=>| |number| |=>| |number|↵|#let| |doEs|#:| |MutArray|‹|int|›| |=>| |MutArray|‹|int|›|↵|#class| |C| |{||}|↵|#trait| |I| |{|→|#let| |i|#:| |number|←|↵|}|↵|#let| |doCs|#:| |MutArray|‹|C|›| |=>| |MutArray|‹|C|›|↵|#let| |doIs|#:| |MutArray|‹|I|›| |=>| |MutArray|‹|I|›|↵|#let| |inter|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›| |=>| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#let| |clean|#:| |MutArray|‹|(|string|,| |number|,| |)|›| |=>| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#let| |translate|#:| |MutArray|‹|T|›| |=>| |MutArray|‹|U|›|↵|#let| |uu|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›| |=>| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#let| |ta|#:| |MutArray|‹|Temp|‹|bool|›|›| |=>| |MutArray|‹|Temp|‹|bool|›|›|↵|#let| |tat|#:| |MutArray|‹|Temp|‹|T|›|›| |=>| |MutArray|‹|Temp|‹|T|›|›|
-//│ Parsed: {let first: [] -> MutArray[string] -> string; let getZero3: [] -> unit -> MutArray[number]; let first2: [] -> MutArray[number -> number] -> number -> number; let doEs: [] -> MutArray[int] -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; let doCs: [] -> MutArray[C] -> MutArray[C]; let doIs: [] -> MutArray[I] -> MutArray[I]; let inter: [] -> MutArray[(U,) & (T,)] -> MutArray[(U,) & (T,)]; let clean: [] -> MutArray[(string, number,)] -> MutArray[(string, number,)]; let translate: [] -> MutArray[T] -> MutArray[U]; let uu: [] -> MutArray[(number,) | (bool,)] -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; let ta: [] -> MutArray[Temp[bool]] -> MutArray[Temp[bool]]; let tat: [] -> MutArray[Temp[T]] -> MutArray[Temp[T]]}
+fun ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
+fun tat: MutArray<Temp<T>> => MutArray<Temp<T>>
+//│ |#fun| |first|#:| |MutArray|‹|string|›| |=>| |string|↵|#fun| |getZero3|#:| |unit| |=>| |MutArray|‹|number|›|↵|#fun| |first2|#:| |MutArray|‹|number| |=>| |number|›| |=>| |number| |=>| |number|↵|#fun| |doEs|#:| |MutArray|‹|int|›| |=>| |MutArray|‹|int|›|↵|#class| |C| |{||}|↵|#trait| |I| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|#:| |MutArray|‹|C|›| |=>| |MutArray|‹|C|›|↵|#fun| |doIs|#:| |MutArray|‹|I|›| |=>| |MutArray|‹|I|›|↵|#fun| |inter|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›| |=>| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|#:| |MutArray|‹|(|string|,| |number|,| |)|›| |=>| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|#:| |MutArray|‹|T|›| |=>| |MutArray|‹|U|›|↵|#fun| |uu|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›| |=>| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|#:| |MutArray|‹|Temp|‹|bool|›|›| |=>| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|#:| |MutArray|‹|Temp|‹|T|›|›| |=>| |MutArray|‹|Temp|‹|T|›|›|
+//│ Parsed: {fun first: [] -> MutArray[string] -> string; fun getZero3: [] -> unit -> MutArray[number]; fun first2: [] -> MutArray[number -> number] -> number -> number; fun doEs: [] -> MutArray[int] -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> MutArray[C] -> MutArray[C]; fun doIs: [] -> MutArray[I] -> MutArray[I]; fun inter: [] -> MutArray[(U,) & (T,)] -> MutArray[(U,) & (T,)]; fun clean: [] -> MutArray[(string, number,)] -> MutArray[(string, number,)]; fun translate: [] -> MutArray[T] -> MutArray[U]; fun uu: [] -> MutArray[(number,) | (bool,)] -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> MutArray[Temp[bool]] -> MutArray[Temp[bool]]; fun tat: [] -> MutArray[Temp[T]] -> MutArray[Temp[T]]}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 6e478893d0..cdffcdfaa9 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,28 +1,28 @@
 :NewParser
 :ParseOnly
-let hello: unit => unit
-let add: number => number => number
-let sub: number => number => number
-let foo: unit => number
-let id: anything => anything
-let odd: number => bool
-let isnull: anything => bool
-let bar: unit => anything
-let nu: null => null
-let un: undefined => undefined
-let fail: unit => nothing
-let create: unit => object
-let pa: number => number
-let wtf: anything => unit
+fun hello: unit => unit
+fun add: number => number => number
+fun sub: number => number => number
+fun foo: unit => number
+fun id: anything => anything
+fun odd: number => bool
+fun isnull: anything => bool
+fun bar: unit => anything
+fun nu: null => null
+fun un: undefined => undefined
+fun fail: unit => nothing
+fun create: unit => object
+fun pa: number => number
+fun wtf: anything => unit
 class Foooooo {
   let ooooooo: number
 }
-let inn: Foooooo => unit
-let out: unit => Foooooo
+fun inn: Foooooo => unit
+fun out: unit => Foooooo
 trait Barrrrrrrrr {
   let rrrrrrr: number
 }
-let inn2: Barrrrrrrrr => unit
-let out2: unit => Barrrrrrrrr
-//│ |#let| |hello|#:| |unit| |=>| |unit|↵|#let| |add|#:| |number| |=>| |number| |=>| |number|↵|#let| |sub|#:| |number| |=>| |number| |=>| |number|↵|#let| |foo|#:| |unit| |=>| |number|↵|#let| |id|#:| |anything| |=>| |anything|↵|#let| |odd|#:| |number| |=>| |bool|↵|#let| |isnull|#:| |anything| |=>| |bool|↵|#let| |bar|#:| |unit| |=>| |anything|↵|#let| |nu|#:| |null| |=>| |null|↵|#let| |un|#:| |undefined| |=>| |undefined|↵|#let| |fail|#:| |unit| |=>| |nothing|↵|#let| |create|#:| |unit| |=>| |object|↵|#let| |pa|#:| |number| |=>| |number|↵|#let| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#let| |inn|#:| |Foooooo| |=>| |unit|↵|#let| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#let| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#let| |out2|#:| |unit| |=>| |Barrrrrrrrr|
-//│ Parsed: {let hello: [] -> unit -> unit; let add: [] -> number -> number -> number; let sub: [] -> number -> number -> number; let foo: [] -> unit -> number; let id: [] -> anything -> anything; let odd: [] -> number -> bool; let isnull: [] -> anything -> bool; let bar: [] -> unit -> anything; let nu: [] -> null -> null; let un: [] -> undefined -> undefined; let fail: [] -> unit -> nothing; let create: [] -> unit -> object; let pa: [] -> number -> number; let wtf: [] -> anything -> unit; class Foooooo() {let ooooooo: [] -> number}; let inn: [] -> Foooooo -> unit; let out: [] -> unit -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; let inn2: [] -> Barrrrrrrrr -> unit; let out2: [] -> unit -> Barrrrrrrrr}
+fun inn2: Barrrrrrrrr => unit
+fun out2: unit => Barrrrrrrrr
+//│ |#fun| |hello|#:| |unit| |=>| |unit|↵|#fun| |add|#:| |number| |=>| |number| |=>| |number|↵|#fun| |sub|#:| |number| |=>| |number| |=>| |number|↵|#fun| |foo|#:| |unit| |=>| |number|↵|#fun| |id|#:| |anything| |=>| |anything|↵|#fun| |odd|#:| |number| |=>| |bool|↵|#fun| |isnull|#:| |anything| |=>| |bool|↵|#fun| |bar|#:| |unit| |=>| |anything|↵|#fun| |nu|#:| |null| |=>| |null|↵|#fun| |un|#:| |undefined| |=>| |undefined|↵|#fun| |fail|#:| |unit| |=>| |nothing|↵|#fun| |create|#:| |unit| |=>| |object|↵|#fun| |pa|#:| |number| |=>| |number|↵|#fun| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|#:| |Foooooo| |=>| |unit|↵|#fun| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#fun| |out2|#:| |unit| |=>| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index 8eb2d7a5bf..ab520f2345 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-let pass: int => bool
-let stop: unit => int
-let g: int => int
-//│ |#let| |pass|#:| |int| |=>| |bool|↵|#let| |stop|#:| |unit| |=>| |int|↵|#let| |g|#:| |int| |=>| |int|
-//│ Parsed: {let pass: [] -> int -> bool; let stop: [] -> unit -> int; let g: [] -> int -> int}
+fun pass: int => bool
+fun stop: unit => int
+fun g: int => int
+//│ |#fun| |pass|#:| |int| |=>| |bool|↵|#fun| |stop|#:| |unit| |=>| |int|↵|#fun| |g|#:| |int| |=>| |int|
+//│ Parsed: {fun pass: [] -> int -> bool; fun stop: [] -> unit -> int; fun g: [] -> int -> int}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index 775f040b1c..ef4fc55d59 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-let h1: (number => number) => number => number
-let h2: string => unit => string
-let h3: (number => number) => (number => number) => number => number
-//│ |#let| |h1|#:| |(|number| |=>| |number|)| |=>| |number| |=>| |number|↵|#let| |h2|#:| |string| |=>| |unit| |=>| |string|↵|#let| |h3|#:| |(|number| |=>| |number|)| |=>| |(|number| |=>| |number|)| |=>| |number| |=>| |number|
-//│ Parsed: {let h1: [] -> (number -> number) -> number -> number; let h2: [] -> string -> unit -> string; let h3: [] -> (number -> number) -> (number -> number) -> number -> number}
+fun h1: (number => number) => number => number
+fun h2: string => unit => string
+fun h3: (number => number) => (number => number) => number => number
+//│ |#fun| |h1|#:| |(|number| |=>| |number|)| |=>| |number| |=>| |number|↵|#fun| |h2|#:| |string| |=>| |unit| |=>| |string|↵|#fun| |h3|#:| |(|number| |=>| |number|)| |=>| |(|number| |=>| |number|)| |=>| |number| |=>| |number|
+//│ Parsed: {fun h1: [] -> (number -> number) -> number -> number; fun h2: [] -> string -> unit -> string; fun h3: [] -> (number -> number) -> (number -> number) -> number -> number}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index f704a077a2..a50c89a53e 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -9,8 +9,8 @@ trait IFoo {
 trait II<T> {
   let test: T => number
 }
-let create: unit => (v: number,)
-let get: (t: string,) => string
+fun create: unit => (v: number,)
+fun get: (t: string,) => string
 trait IEvent {
   let callback: unit => number => unit
 }
@@ -36,5 +36,5 @@ trait Next(): Simple {}
 trait TTT<T> {
   let ttt: T => T
 }
-//│ |#trait| |IFoo| |{|→|#let| |a|#:| |string|↵|#let| |b|#:| |number| |=>| |number|↵|#let| |c|#:| |unit| |=>| |bool|↵|#let| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›| |{|→|#let| |test|#:| |T| |=>| |number|←|↵|}|↵|#let| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#let| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent| |{|→|#let| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc| |{|→|#let| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray| |{|→|#let| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter| |{|→|#let| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#let| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple| |{|→|#let| |a|#:| |number|↵|#let| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {let a: [] -> string; let b: [] -> number -> number; let c: [] -> unit -> bool; let d: [] -> string -> unit}; trait II[T](): {let test: [] -> T -> number}; let create: [] -> unit -> (v: number,); let get: [] -> (t: string,) -> string; trait IEvent(): {let callback: [] -> unit -> number -> unit}; trait SearchFunc(): {let __call: [] -> string -> string -> bool}; trait StringArray(): {let __index: [] -> number -> string}; trait Counter(): {let __call: [] -> number -> string; let interval: [] -> number; let reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; let b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {let ttt: [] -> T -> T}}
+//│ |#trait| |IFoo| |{|→|#let| |a|#:| |string|↵|#let| |b|#:| |number| |=>| |number|↵|#let| |c|#:| |unit| |=>| |bool|↵|#let| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›| |{|→|#let| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#fun| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent| |{|→|#let| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc| |{|→|#let| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray| |{|→|#let| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter| |{|→|#let| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#let| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple| |{|→|#let| |a|#:| |number|↵|#let| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {let a: [] -> string; let b: [] -> number -> number; let c: [] -> unit -> bool; let d: [] -> string -> unit}; trait II[T](): {let test: [] -> T -> number}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(): {let callback: [] -> unit -> number -> unit}; trait SearchFunc(): {let __call: [] -> string -> string -> bool}; trait StringArray(): {let __index: [] -> number -> string}; trait Counter(): {let __call: [] -> number -> string; let interval: [] -> number; let reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; let b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {let ttt: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 68881f6027..e2e2d6ae54 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,21 +1,21 @@
 :NewParser
 :ParseOnly
-let extend: T => U => (T) & (U)
-let foo: (T) & (U) => unit
-let over: (number => string) & (object => string) => string
+fun extend: T => U => (T) & (U)
+fun foo: (T) & (U) => unit
+fun over: (number => string) & (object => string) => string
 trait IA {
   let x: number
 }
 trait IB {
   let y: number
 }
-let iii: (IA) & (IB) => (IA) & (IB)
-let uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
-let iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
-let arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
-let tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
+fun iii: (IA) & (IB) => (IA) & (IB)
+fun uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
+fun iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
+fun arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
+fun tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
 class A {}
 class B {}
-let inter: (A) & (B) => (A) & (B)
-//│ |#let| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#let| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#let| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB| |{|→|#let| |y|#:| |number|←|↵|}|↵|#let| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#let| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#let| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#let| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#let| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A| |{||}|↵|#class| |B| |{||}|↵|#let| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
-//│ Parsed: {let extend: [] -> T -> U -> ((T,) & (U,)); let foo: [] -> ((T,) & (U,)) -> unit; let over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; let iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); let uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); let iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); let arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); let tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; let inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
+fun inter: (A) & (B) => (A) & (B)
+//│ |#fun| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#fun| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#fun| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A| |{||}|↵|#class| |B| |{||}|↵|#fun| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
+//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index cf528c63c9..921304da1f 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,22 +1,22 @@
 :NewParser
 :ParseOnly
-let multi1: number => number
-let multi3: unit => unit
+fun multi1: number => number
+fun multi3: unit => unit
 class Foo(): Base {}
 trait AnotherBase {
   let y: string
 }
 namespace N {
-  let f: unit => unit
-  let g: unit => unit
-  let h: unit => unit
+  fun f: unit => unit
+  fun g: unit => unit
+  fun h: unit => unit
 }
-let multi2: string => string
-let multi4: unit => unit
+fun multi2: string => string
+fun multi4: unit => unit
 trait Base {
   let a: number
 }
 class AnotherFoo(): AnotherBase {}
-let multi5: unit => unit
-//│ |#let| |multi1|#:| |number| |=>| |number|↵|#let| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#let| |f|#:| |unit| |=>| |unit|↵|#let| |g|#:| |unit| |=>| |unit|↵|#let| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#let| |multi2|#:| |string| |=>| |string|↵|#let| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#let| |multi5|#:| |unit| |=>| |unit|
-//│ Parsed: {let multi1: [] -> number -> number; let multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {let f: [] -> unit -> unit; let g: [] -> unit -> unit; let h: [] -> unit -> unit}; let multi2: [] -> string -> string; let multi4: [] -> unit -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; let multi5: [] -> unit -> unit}
+fun multi5: unit => unit
+//│ |#fun| |multi1|#:| |number| |=>| |number|↵|#fun| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|#:| |unit| |=>| |unit|↵|#fun| |g|#:| |unit| |=>| |unit|↵|#fun| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#fun| |multi2|#:| |string| |=>| |string|↵|#fun| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|#:| |unit| |=>| |unit|
+//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index f3b62a4ce8..a877fab7ec 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,8 +1,8 @@
 :NewParser
 :ParseOnly
 namespace N1 {
-  let f: anything => number
-  let ff: anything => number
+  fun f: anything => number
+  fun ff: anything => number
   class C {
     let f: unit => unit
   }
@@ -10,13 +10,13 @@ namespace N1 {
     let f: unit => number
   }
   namespace N2 {
-    let fff: bool => number
-    let gg: N1'C => N1'C
+    fun fff: bool => number
+    fun gg: N1'C => N1'C
     class BBB(): N1'C {}
   }
 }
 namespace AA {
-  let f: anything => string
+  fun f: anything => string
   class C {
     let f: unit => unit
   }
@@ -26,7 +26,7 @@ namespace AA {
   namespace N2 {
   }
 }
-let f1: N1'C => N1'C
-let f2: AA'C => AA'C
-//│ |#namespace| |N1| |{|→|#let| |f|#:| |anything| |=>| |number|↵|#let| |ff|#:| |anything| |=>| |number|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#let| |fff|#:| |bool| |=>| |number|↵|#let| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#let| |f|#:| |anything| |=>| |string|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#let| |f1|#:| |N1'C| |=>| |N1'C|↵|#let| |f2|#:| |AA'C| |=>| |AA'C|
-//│ Parsed: {namespace N1(): {let f: [] -> anything -> number; let ff: [] -> anything -> number; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {let fff: [] -> bool -> number; let gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {let f: [] -> anything -> string; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {}}; let f1: [] -> N1'C -> N1'C; let f2: [] -> AA'C -> AA'C}
+fun f1: N1'C => N1'C
+fun f2: AA'C => AA'C
+//│ |#namespace| |N1| |{|→|#fun| |f|#:| |anything| |=>| |number|↵|#fun| |ff|#:| |anything| |=>| |number|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|#:| |bool| |=>| |number|↵|#fun| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|#:| |anything| |=>| |string|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|#:| |N1'C| |=>| |N1'C|↵|#fun| |f2|#:| |AA'C| |=>| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index c230030fe9..3b5053ba8a 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
-let buildName: string => (string) | (undefined) => string
-let buildName2: string => (string) | (undefined) => string
-let buildName3: string => MutArray<string> => string
-let buildName4: string => MutArray<anything> => string
+fun buildName: string => (string) | (undefined) => string
+fun buildName2: string => (string) | (undefined) => string
+fun buildName3: string => MutArray<string> => string
+fun buildName4: string => MutArray<anything> => string
 trait SquareConfig {
   let color: (string) | (undefined)
   let width: (number) | (undefined)
 }
-let did: number => (number => number) | (undefined) => number
-let getOrElse: (MutArray<object>) | (undefined) => object
+fun did: number => (number => number) | (undefined) => number
+fun getOrElse: (MutArray<object>) | (undefined) => object
 class ABC {}
-let testABC: (ABC) | (undefined) => unit
-let testSquareConfig: (SquareConfig) | (undefined) => unit
-let err: ((number, string, )) | (undefined) => unit
-let toStr: ((number) | (bool)) | (undefined) => string
-let boo: ((T) & (U)) | (undefined) => unit
+fun testABC: (ABC) | (undefined) => unit
+fun testSquareConfig: (SquareConfig) | (undefined) => unit
+fun err: ((number, string, )) | (undefined) => unit
+fun toStr: ((number) | (bool)) | (undefined) => string
+fun boo: ((T) & (U)) | (undefined) => unit
 class B<T> {
   let b: T
 }
-let boom: (B<nothing>) | (undefined) => anything
-//│ |#let| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#let| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#let| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#let| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#let| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC| |{||}|↵|#let| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#let| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#let| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›| |{|→|#let| |b|#:| |T|←|↵|}|↵|#let| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
-//│ Parsed: {let buildName: [] -> string -> ((string,) | (undefined,)) -> string; let buildName2: [] -> string -> ((string,) | (undefined,)) -> string; let buildName3: [] -> string -> MutArray[string] -> string; let buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; let did: [] -> number -> ((number -> number,) | (undefined,)) -> number; let getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; let testABC: [] -> ((ABC,) | (undefined,)) -> unit; let testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; let err: [] -> (((number, string,),) | (undefined,)) -> unit; let toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; let boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T]() {let b: [] -> T}; let boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
+fun boom: (B<nothing>) | (undefined) => anything
+//│ |#fun| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#fun| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#fun| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC| |{||}|↵|#fun| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
+//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 542d3dbcda..654b2b6c4f 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,26 +1,26 @@
 :NewParser
 :ParseOnly
-let f: (number => string) & (string => string)
+fun f: (number => string) & (string => string)
 class M {
   let foo: (number => string) & (string => string)
 }
-let app: ((string => unit) => number => unit) & ((string => unit) => string => unit)
-let create: (number => unit => bool) & (bool => unit => bool)
-let g0: (MutArray<string> => string) & (MutArray<object> => string)
-let db: (number => MutArray<number>) & (object => MutArray<number>)
+fun app: ((string => unit) => number => unit) & ((string => unit) => string => unit)
+fun create: (number => unit => bool) & (bool => unit => bool)
+fun g0: (MutArray<string> => string) & (MutArray<object> => string)
+fun db: (number => MutArray<number>) & (object => MutArray<number>)
 class N {}
-let id: (M => unit) & (N => unit)
-let tst: ((z: number,) => (y: string,)) & ((z: bool,) => (y: string,))
-let op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
-let swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
-let u: ((number) | (bool) => string) & (object => string)
-let doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+fun id: (M => unit) & (N => unit)
+fun tst: ((z: number,) => (y: string,)) & ((z: bool,) => (y: string,))
+fun op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
+fun swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
+fun u: ((number) | (bool) => string) & (object => string)
+fun doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
 namespace XX {
-  let f: T => anything => string /* warning: the overload of function f is not supported yet. */
+  fun f: T => anything => string /* warning: the overload of function f is not supported yet. */
 }
 class WWW {
   let F: T => anything /* warning: the overload of function F is not supported yet. */
 }
-let baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#let| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#let| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#let| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#let| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#let| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#let| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#let| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#let| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#let| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#let| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#let| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#let| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW| |{|→|#let| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#let| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
-//│ Parsed: {let f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; let app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); let create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); let g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); let db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; let id: [] -> (M -> unit,) & (N -> unit,); let tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); let op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); let swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); let u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); let doSome: [] -> anything -> unit; namespace XX(): {let f: [] -> T -> anything -> string}; class WWW() {let F: [] -> T -> anything}; let baz: [] -> unit -> anything}
+fun baz: unit => anything /* warning: the overload of function baz is not supported yet. */
+//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW| |{|→|#let| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> unit; namespace XX(): {fun f: [] -> T -> anything -> string}; class WWW() {let F: [] -> T -> anything}; fun baz: [] -> unit -> anything}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index d61a723374..1f9ea8ebba 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,20 +1,20 @@
 :NewParser
 :ParseOnly
-let key: (string, bool, ) => string
-let value: (string, bool, ) => bool
-let third: (number, number, number, ) => number
-let vec2: number => number => (number, number, )
-let twoFunctions: (number => number, number => number, ) => number => number
-let tupleIt: string => (unit => string, )
-let s: bool => ((string) | (number), (number) | (bool), )
-let s2: (bool, (string) | (number), ) => (string) | (number)
-let ex: T => U => (T, U, (T) & (U), )
-let foo: ((T) & (U), ) => unit
-let conv: (y: number,) => ((y: number,), (z: string,), )
+fun key: (string, bool, ) => string
+fun value: (string, bool, ) => bool
+fun third: (number, number, number, ) => number
+fun vec2: number => number => (number, number, )
+fun twoFunctions: (number => number, number => number, ) => number => number
+fun tupleIt: string => (unit => string, )
+fun s: bool => ((string) | (number), (number) | (bool), )
+fun s2: (bool, (string) | (number), ) => (string) | (number)
+fun ex: T => U => (T, U, (T) & (U), )
+fun foo: ((T) & (U), ) => unit
+fun conv: (y: number,) => ((y: number,), (z: string,), )
 class A {
   let x: number
 }
 class B {}
-let swap: (A, B, ) => (B, A, )
-//│ |#let| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#let| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#let| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#let| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#let| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#let| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#let| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#let| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#let| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#let| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#let| |conv|#:| |(|y|#:| |number|,|)| |=>| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B| |{||}|↵|#let| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
-//│ Parsed: {let key: [] -> (string, bool,) -> string; let value: [] -> (string, bool,) -> bool; let third: [] -> (number, number, number,) -> number; let vec2: [] -> number -> number -> (number, number,); let twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; let tupleIt: [] -> string -> (unit -> string,); let s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); let s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); let ex: [] -> T -> U -> (T, U, (T,) & (U,),); let foo: [] -> ((T,) & (U,)) -> unit; let conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; let swap: [] -> (A, B,) -> (B, A,)}
+fun swap: (A, B, ) => (B, A, )
+//│ |#fun| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#fun| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#fun| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#fun| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#fun| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#fun| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#fun| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#fun| |conv|#:| |(|y|#:| |number|,|)| |=>| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B| |{||}|↵|#fun| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
+//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index b67b35ab4d..579e46b4c1 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,17 +1,17 @@
 :NewParser
 :ParseOnly
-let inc: T => number
+fun inc: T => number
 class CC<T> {
   let print: T => unit
 }
-let con: T => U
+fun con: T => U
 class Printer<T> {
   let print: T => unit
 }
-let setStringPrinter: Printer<string> => unit
-let getStringPrinter: unit => Printer<string>
-let foo: Printer<T> => T => T
-let foo2: Printer<T> => T => T
+fun setStringPrinter: Printer<string> => unit
+fun getStringPrinter: unit => Printer<string>
+fun foo: Printer<T> => T => T
+fun foo2: Printer<T> => T => T
 class F<T> {
   let x: T
   let GG: U => T
@@ -23,7 +23,7 @@ trait I<T> {
 class FFF<T> {
   let fff: T => unit
 }
-let fff: FFF<string> => string => unit
-let getFFF: unit => FFF<number>
-//│ |#let| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#let| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#let| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#let| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#let| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#let| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›| |{|→|#let| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#let| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#let| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ Parsed: {let inc: [] -> T -> number; class CC[T]() {let print: [] -> T -> unit}; let con: [] -> T -> U; class Printer[T]() {let print: [] -> T -> unit}; let setStringPrinter: [] -> Printer[string] -> unit; let getStringPrinter: [] -> unit -> Printer[string]; let foo: [] -> Printer[T] -> T -> T; let foo2: [] -> Printer[T] -> T -> T; class F[T]() {let x: [] -> T; let GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; let GG: [] -> U -> T}; class FFF[T]() {let fff: [] -> T -> unit}; let fff: [] -> FFF[string] -> string -> unit; let getFFF: [] -> unit -> FFF[number]}
+fun fff: FFF<string> => string => unit
+fun getFFF: unit => FFF<number>
+//│ |#fun| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#fun| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#fun| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#fun| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›| |{|→|#let| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#fun| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> T -> number; class CC[T]() {let print: [] -> T -> unit}; fun con: [] -> T -> U; class Printer[T]() {let print: [] -> T -> unit}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T]() {let x: [] -> T; let GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; let GG: [] -> U -> T}; class FFF[T]() {let fff: [] -> T -> unit}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index df0ed7dd0b..ff94527d83 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,11 +1,11 @@
 :NewParser
 :ParseOnly
-let getString: ((string) | (number)) | (bool) => string
-let test: bool => (string) | (number)
-let run: (number => number) | (number => string) => anything
-let get: (MutArray<number>) | (MutArray<string>) => unit
-let get2: ((string, string, )) | ((number, string, )) => string
-let typeVar: (T) | (U) => (T) | (U)
-let uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
-//│ |#let| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#let| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#let| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#let| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#let| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#let| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#let| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ Parsed: {let getString: [] -> (((string,) | (number,),) | (bool,)) -> string; let test: [] -> bool -> ((string,) | (number,)); let run: [] -> ((number -> number,) | (number -> string,)) -> anything; let get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; let get2: [] -> (((string, string,),) | ((number, string,),)) -> string; let typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); let uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}
+fun getString: ((string) | (number)) | (bool) => string
+fun test: bool => (string) | (number)
+fun run: (number => number) | (number => string) => anything
+fun get: (MutArray<number>) | (MutArray<string>) => unit
+fun get2: ((string, string, )) | ((number, string, )) => string
+fun typeVar: (T) | (U) => (T) | (U)
+fun uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
+//│ |#fun| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#fun| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#fun| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#fun| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#fun| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#fun| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
+//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}

From 9c9a9a572665e22e1fcc440a358fc9b2c3f3bd8a Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 15 Sep 2022 09:53:30 +0800
Subject: [PATCH 20/40] Fix fun

---
 .../main/scala/ts2mls/types/Converter.scala   |  6 ++++-
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 18 ++++++-------
 ts2mls/js/src/test/diff/Heritage.d.mls        | 16 ++++++------
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 26 +++++++++----------
 ts2mls/js/src/test/diff/Namespace.d.mls       | 12 ++++-----
 ts2mls/js/src/test/diff/Overload.d.mls        |  6 ++---
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 14 +++++-----
 7 files changed, 51 insertions(+), 47 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index b9dc9736b6..5f5c0ef337 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -54,7 +54,11 @@ object Converter {
     val allRecs = members.toList.map((m) => m._2.modifier match {
       case Public =>
         if (typeName === "trait ") s"${m._1}: ${convert(m._2)},"
-        else s"${indent}  let ${m._1}: ${convert(m._2)}\n"
+        else m._2.base match {
+          case _: TSFunctionType => s"${indent}  fun ${m._1}: ${convert(m._2)}\n"
+          case _: TSIgnoredOverload => s"${indent}  fun ${m._1}: ${convert(m._2)}\n"
+          case _ => s"${indent}  let ${m._1}: ${convert(m._2)}\n"
+        }
       // case Public => {
       //   m._2.base match { // methods
       //     case f @ TSFunctionType(_, _, typeVars) if (!typeVars.isEmpty) =>
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index ddf42e1e5f..4d55d23e29 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -2,20 +2,20 @@
 :ParseOnly
 class Student {
   let name: string
-  let isFriend: Student => bool
-  let addScore: string => number => unit
-  let getID: unit => number
+  fun isFriend: Student => bool
+  fun addScore: string => number => unit
+  fun getID: unit => number
 }
 class Foo<T> {
-  let bar: T => unit
+  fun bar: T => unit
 }
 class EZ {
-  let inc: number => number
+  fun inc: number => number
 }
 class Outer {}
 class TTT<T> {
-  let ttt: T => T
-  let ttt2: T => T
+  fun ttt: T => T
+  fun ttt2: T => T
 }
-//│ |#class| |Student| |{|→|#let| |name|#:| |string|↵|#let| |isFriend|#:| |Student| |=>| |bool|↵|#let| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#let| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›| |{|→|#let| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ| |{|→|#let| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer| |{||}|↵|#class| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|↵|#let| |ttt2|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {class Student() {let name: [] -> string; let isFriend: [] -> Student -> bool; let addScore: [] -> string -> number -> unit; let getID: [] -> unit -> number}; class Foo[T]() {let bar: [] -> T -> unit}; class EZ() {let inc: [] -> number -> number}; class Outer() {}; class TTT[T]() {let ttt: [] -> T -> T; let ttt2: [] -> T -> T}}
+//│ |#class| |Student| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|#:| |Student| |=>| |bool|↵|#fun| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#fun| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›| |{|→|#fun| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ| |{|→|#fun| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer| |{||}|↵|#class| |TTT|‹|T|›| |{|→|#fun| |ttt|#:| |T| |=>| |T|↵|#fun| |ttt2|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {class Student() {let name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index f929bb4c08..67ed2b87b3 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -1,12 +1,12 @@
 :NewParser
 :ParseOnly
 class A {
-  let foo: unit => unit
+  fun foo: unit => unit
 }
 class B(): A {}
 class C<T> {
-  let set: T => unit
-  let get: unit => T
+  fun set: T => unit
+  fun get: unit => T
 }
 class D(): C<number> {}
 trait Wu {
@@ -19,7 +19,7 @@ trait WuWuWu(): WuWu {
   let z: bool
 }
 trait Never(): WuWuWu {
-  let w: unit => nothing
+  fun w: unit => nothing
 }
 class VG<T> {
   let x: T
@@ -28,10 +28,10 @@ class Home<T>(): VG<string> {
   let y: T
 }
 trait O<I> {
-  let xx: I => I
+  fun xx: I => I
 }
 class OR<R>(): O<R> {
-  let xx: R => R
+  fun xx: R => R
 }
 namespace Five {
   class ROTK {
@@ -40,5 +40,5 @@ namespace Five {
   class Y(): Five'ROTK {}
 }
 class Y(): Five'ROTK {}
-//│ |#class| |A| |{|→|#let| |foo|#:| |unit| |=>| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›| |{|→|#let| |set|#:| |T| |=>| |unit|↵|#let| |get|#:| |unit| |=>| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#let| |w|#:| |unit| |=>| |nothing|←|↵|}|↵|#class| |VG|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›| |{|→|#let| |xx|#:| |I| |=>| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#let| |xx|#:| |R| |=>| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
-//│ Parsed: {class A() {let foo: [] -> unit -> unit}; class B(): A {}; class C[T]() {let set: [] -> T -> unit; let get: [] -> unit -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {let w: [] -> unit -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {let xx: [] -> I -> I}; class OR[R](): O‹R› {let xx: [] -> R -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A| |{|→|#fun| |foo|#:| |unit| |=>| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›| |{|→|#fun| |set|#:| |T| |=>| |unit|↵|#fun| |get|#:| |unit| |=>| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|#:| |unit| |=>| |nothing|←|↵|}|↵|#class| |VG|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›| |{|→|#fun| |xx|#:| |I| |=>| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|#:| |R| |=>| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
+//│ Parsed: {class A() {fun foo: [] -> unit -> unit}; class B(): A {}; class C[T]() {fun set: [] -> T -> unit; fun get: [] -> unit -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> unit -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> I -> I}; class OR[R](): O‹R› {fun xx: [] -> R -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index a50c89a53e..2a9d7572d7 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -2,39 +2,39 @@
 :ParseOnly
 trait IFoo {
   let a: string
-  let b: number => number
-  let c: unit => bool
-  let d: string => unit
+  fun b: number => number
+  fun c: unit => bool
+  fun d: string => unit
 }
 trait II<T> {
-  let test: T => number
+  fun test: T => number
 }
 fun create: unit => (v: number,)
 fun get: (t: string,) => string
 trait IEvent {
-  let callback: unit => number => unit
+  fun callback: unit => number => unit
 }
 trait SearchFunc {
-  let __call: string => string => bool
+  fun __call: string => string => bool
 }
 trait StringArray {
-  let __index: number => string
+  fun __index: number => string
 }
 trait Counter {
-  let __call: number => string
+  fun __call: number => string
   let interval: number
-  let reset: unit => unit
+  fun reset: unit => unit
 }
 trait Simple {
   let a: number
-  let b: bool => string
+  fun b: bool => string
 }
 trait Simple2<T> {
   let abc: T
 }
 trait Next(): Simple {}
 trait TTT<T> {
-  let ttt: T => T
+  fun ttt: T => T
 }
-//│ |#trait| |IFoo| |{|→|#let| |a|#:| |string|↵|#let| |b|#:| |number| |=>| |number|↵|#let| |c|#:| |unit| |=>| |bool|↵|#let| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›| |{|→|#let| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#fun| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent| |{|→|#let| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc| |{|→|#let| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray| |{|→|#let| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter| |{|→|#let| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#let| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple| |{|→|#let| |a|#:| |number|↵|#let| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›| |{|→|#let| |ttt|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {let a: [] -> string; let b: [] -> number -> number; let c: [] -> unit -> bool; let d: [] -> string -> unit}; trait II[T](): {let test: [] -> T -> number}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(): {let callback: [] -> unit -> number -> unit}; trait SearchFunc(): {let __call: [] -> string -> string -> bool}; trait StringArray(): {let __index: [] -> number -> string}; trait Counter(): {let __call: [] -> number -> string; let interval: [] -> number; let reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; let b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {let ttt: [] -> T -> T}}
+//│ |#trait| |IFoo| |{|→|#let| |a|#:| |string|↵|#fun| |b|#:| |number| |=>| |number|↵|#fun| |c|#:| |unit| |=>| |bool|↵|#fun| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›| |{|→|#fun| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#fun| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent| |{|→|#fun| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc| |{|→|#fun| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray| |{|→|#fun| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter| |{|→|#fun| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple| |{|→|#let| |a|#:| |number|↵|#fun| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›| |{|→|#fun| |ttt|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> number -> number; fun c: [] -> unit -> bool; fun d: [] -> string -> unit}; trait II[T](): {fun test: [] -> T -> number}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(): {fun callback: [] -> unit -> number -> unit}; trait SearchFunc(): {fun __call: [] -> string -> string -> bool}; trait StringArray(): {fun __index: [] -> number -> string}; trait Counter(): {fun __call: [] -> number -> string; let interval: [] -> number; fun reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index a877fab7ec..08df8b8182 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -4,10 +4,10 @@ namespace N1 {
   fun f: anything => number
   fun ff: anything => number
   class C {
-    let f: unit => unit
+    fun f: unit => unit
   }
   trait I {
-    let f: unit => number
+    fun f: unit => number
   }
   namespace N2 {
     fun fff: bool => number
@@ -18,15 +18,15 @@ namespace N1 {
 namespace AA {
   fun f: anything => string
   class C {
-    let f: unit => unit
+    fun f: unit => unit
   }
   trait I {
-    let f: unit => number
+    fun f: unit => number
   }
   namespace N2 {
   }
 }
 fun f1: N1'C => N1'C
 fun f2: AA'C => AA'C
-//│ |#namespace| |N1| |{|→|#fun| |f|#:| |anything| |=>| |number|↵|#fun| |ff|#:| |anything| |=>| |number|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|#:| |bool| |=>| |number|↵|#fun| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|#:| |anything| |=>| |string|↵|#class| |C| |{|→|#let| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#let| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|#:| |N1'C| |=>| |N1'C|↵|#fun| |f2|#:| |AA'C| |=>| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C() {let f: [] -> unit -> unit}; trait I(): {let f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
+//│ |#namespace| |N1| |{|→|#fun| |f|#:| |anything| |=>| |number|↵|#fun| |ff|#:| |anything| |=>| |number|↵|#class| |C| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|#:| |bool| |=>| |number|↵|#fun| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|#:| |anything| |=>| |string|↵|#class| |C| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|#:| |N1'C| |=>| |N1'C|↵|#fun| |f2|#:| |AA'C| |=>| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 654b2b6c4f..7f038398bc 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -19,8 +19,8 @@ namespace XX {
   fun f: T => anything => string /* warning: the overload of function f is not supported yet. */
 }
 class WWW {
-  let F: T => anything /* warning: the overload of function F is not supported yet. */
+  fun F: T => anything /* warning: the overload of function F is not supported yet. */
 }
 fun baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW| |{|→|#let| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> unit; namespace XX(): {fun f: [] -> T -> anything -> string}; class WWW() {let F: [] -> T -> anything}; fun baz: [] -> unit -> anything}
+//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW| |{|→|#fun| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> unit; namespace XX(): {fun f: [] -> T -> anything -> string}; class WWW() {fun F: [] -> T -> anything}; fun baz: [] -> unit -> anything}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index 579e46b4c1..a949273357 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -2,11 +2,11 @@
 :ParseOnly
 fun inc: T => number
 class CC<T> {
-  let print: T => unit
+  fun print: T => unit
 }
 fun con: T => U
 class Printer<T> {
-  let print: T => unit
+  fun print: T => unit
 }
 fun setStringPrinter: Printer<string> => unit
 fun getStringPrinter: unit => Printer<string>
@@ -14,16 +14,16 @@ fun foo: Printer<T> => T => T
 fun foo2: Printer<T> => T => T
 class F<T> {
   let x: T
-  let GG: U => T
+  fun GG: U => T
 }
 trait I<T> {
   let x: T
-  let GG: U => T
+  fun GG: U => T
 }
 class FFF<T> {
-  let fff: T => unit
+  fun fff: T => unit
 }
 fun fff: FFF<string> => string => unit
 fun getFFF: unit => FFF<number>
-//│ |#fun| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›| |{|→|#let| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#fun| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#fun| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#fun| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›| |{|→|#let| |x|#:| |T|↵|#let| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›| |{|→|#let| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#fun| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> T -> number; class CC[T]() {let print: [] -> T -> unit}; fun con: [] -> T -> U; class Printer[T]() {let print: [] -> T -> unit}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T]() {let x: [] -> T; let GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; let GG: [] -> U -> T}; class FFF[T]() {let fff: [] -> T -> unit}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
+//│ |#fun| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#fun| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#fun| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#fun| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›| |{|→|#fun| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#fun| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> T -> number; class CC[T]() {fun print: [] -> T -> unit}; fun con: [] -> T -> U; class Printer[T]() {fun print: [] -> T -> unit}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T]() {let x: [] -> T; fun GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> U -> T}; class FFF[T]() {fun fff: [] -> T -> unit}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}

From 75317f8383384d14b932b2a97b1bfd8922ac1047 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 15 Sep 2022 10:05:32 +0800
Subject: [PATCH 21/40] Add inner class translation

---
 .../src/main/scala/ts2mls/TSNamespace.scala   |  6 +++---
 .../main/scala/ts2mls/types/Converter.scala   | 19 +++++++++++++------
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 10 +++++++---
 3 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index f41e7a649f..92ad84a197 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -66,10 +66,10 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
           //     else // TODO: add constraints
           //       writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(overload)}")
           // }
-          case _: TSClassType => writer.writeln(indent + Converter.convert(mem)(indent))
+          case _: TSClassType => writer.writeln(Converter.convert(mem)(indent))
           case _ @ TSInterfaceType(name, _, _, _) if (name =/= "") =>
-            writer.writeln(indent + Converter.convert(mem)(indent))
-          case _ => writer.writeln(indent + Converter.convert(mem))
+            writer.writeln(Converter.convert(mem)(indent))
+          case _ => writer.writeln(Converter.convert(mem))
         }
       }
     })
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 5f5c0ef337..6a8e7d9e9d 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -43,14 +43,14 @@ object Converter {
     case TSArrayType(element) => s"MutArray<${convert(element)}>"
     case TSEnumType => "int"
     case TSMemberType(base, _) => convert(base) // TODO: support private/protected members
-    case TSInterfaceType(name, members, typeVars, parents) => convertRecord(s"trait $name", members, typeVars, parents)(indent)
-    case TSClassType(name, members, _, typeVars, parents) => convertRecord(s"class $name", members, typeVars, parents)(indent) // TODO: support static members
+    case TSInterfaceType(name, members, typeVars, parents) => convertRecord(s"trait $name", members, typeVars, parents, Map())(indent)
+    case TSClassType(name, members, statics, typeVars, parents) => convertRecord(s"class $name", members, typeVars, parents, statics)(indent)
     case TSSubstitutionType(base, applied) => s"${base}<${applied.map((app) => convert(app)).reduceLeft((res, s) => s"$res, $s")}>"
     case overload @ TSIgnoredOverload(base, _) => s"${convert(base)} ${overload.warning}"
   }
 
   private def convertRecord(typeName: String, members: Map[String, TSMemberType],
-    typeVars: List[TSTypeParameter], parents: List[TSType])(implicit indent: String) = {
+    typeVars: List[TSTypeParameter], parents: List[TSType], statics: Map[String, TSMemberType])(implicit indent: String) = {
     val allRecs = members.toList.map((m) => m._2.modifier match {
       case Public =>
         if (typeName === "trait ") s"${m._1}: ${convert(m._2)},"
@@ -71,7 +71,14 @@ object Converter {
       //   }
       // }
       case _ => "" // TODO: deal with private/protected members
-    })
+    }) :::
+      statics.toList.map((s) => s._2.modifier match {
+        case Public => s._2.base match {
+          case _: TSClassType => convert(s._2)(indent + "  ") + "\n"
+          case _ => "" // TODO: deal with other static type
+        }
+        case _ => "" // TODO: deal with private/protected members
+      })
 
     val body = { // members without independent type parameters, translate them directly
       val lst = allRecs.filter((s) => !s.isEmpty())
@@ -90,9 +97,9 @@ object Converter {
       val inheritance =
         if (parents.isEmpty) ""
         else parents.foldLeft("(): ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
-      if (typeVars.isEmpty) s"$typeName$inheritance $body"
+      if (typeVars.isEmpty) s"${indent}$typeName$inheritance $body"
       else
-        s"$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$inheritance $body" // TODO: add constraints
+        s"${indent}$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$inheritance $body" // TODO: add constraints
     }
   }
 }
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index 4d55d23e29..a1a3a805a5 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -12,10 +12,14 @@ class Foo<T> {
 class EZ {
   fun inc: number => number
 }
-class Outer {}
+class Outer {
+  class Inner {
+    let a: number
+  }
+}
 class TTT<T> {
   fun ttt: T => T
   fun ttt2: T => T
 }
-//│ |#class| |Student| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|#:| |Student| |=>| |bool|↵|#fun| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#fun| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›| |{|→|#fun| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ| |{|→|#fun| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer| |{||}|↵|#class| |TTT|‹|T|›| |{|→|#fun| |ttt|#:| |T| |=>| |T|↵|#fun| |ttt2|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {class Student() {let name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}
+//│ |#class| |Student| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|#:| |Student| |=>| |bool|↵|#fun| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#fun| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›| |{|→|#fun| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ| |{|→|#fun| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer| |{|→|#class| |Inner| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›| |{|→|#fun| |ttt|#:| |T| |=>| |T|↵|#fun| |ttt2|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {class Student() {let name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}

From 1fa6c95cdd79e9f22048fcb45ec21d68694505c8 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 15 Sep 2022 10:38:20 +0800
Subject: [PATCH 22/40] Add constructor translation

---
 .../src/main/scala/ts2mls/TSSourceFile.scala  | 12 +++++++++--
 .../main/scala/ts2mls/types/Converter.scala   | 18 +++++++++++------
 .../src/main/scala/ts2mls/types/TSType.scala  |  1 +
 ts2mls/js/src/test/diff/Array.d.mls           |  8 ++++----
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  |  6 +++---
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 16 +++++++--------
 ts2mls/js/src/test/diff/Heritage.d.mls        | 14 ++++++-------
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 20 +++++++++----------
 ts2mls/js/src/test/diff/Intersection.d.mls    | 10 +++++-----
 ts2mls/js/src/test/diff/MultiFiles.d.mls      |  6 +++---
 ts2mls/js/src/test/diff/Namespace.d.mls       | 10 +++++-----
 ts2mls/js/src/test/diff/Optional.d.mls        |  8 ++++----
 ts2mls/js/src/test/diff/Overload.d.mls        |  8 ++++----
 ts2mls/js/src/test/diff/Tuple.d.mls           |  6 +++---
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 12 +++++------
 ts2mls/js/src/test/typescript/ClassMember.ts  |  2 +-
 16 files changed, 86 insertions(+), 71 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala b/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
index 6c0e807e77..6d0be40b12 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
@@ -78,7 +78,6 @@ object TSSourceFile {
     list.foldLeft(Map[String, TSMemberType]())((mp, p) => {
       val name = p.symbol.escapedName
 
-      // TODO: support `__constructor`
       if (name =/= "__constructor" && p.isStatic == requireStatic) {
         val mem =
           if (!p.isStatic) getMemberType(p)
@@ -111,6 +110,14 @@ object TSSourceFile {
       else mp
     })
 
+  private def getConstructorList(members: TSNodeArray): List[TSType] =
+    members.foldLeft(List[TSType]())((lst, mem) => {
+      val name = mem.symbol.escapedName
+
+      if (name =/= "__constructor") lst
+      else mem.parameters.foldLeft(List[TSType]())((res, p) => res :+ getMemberType(p))
+    })
+
   private def getInterfacePropertiesType(list: TSNodeArray): Map[String, TSMemberType] =
     list.foldLeft(Map[String, TSMemberType]())((mp, p) => mp ++ Map(p.symbol.escapedName -> TSMemberType(getMemberType(p))))
 
@@ -120,7 +127,8 @@ object TSSourceFile {
 
   private def parseMembers(name: String, node: TSNodeObject, isClass: Boolean): TSType =
     if (isClass)
-      TSClassType(name, getClassMembersType(node.members, false), getClassMembersType(node.members, true), getTypeParametes(node), getHeritageList(node))
+      TSClassType(name, getClassMembersType(node.members, false), getClassMembersType(node.members, true),
+        getTypeParametes(node), getHeritageList(node), getConstructorList(node.members))
     else TSInterfaceType(name, getInterfacePropertiesType(node.members), getTypeParametes(node), getHeritageList(node))
 
   private def parseNamespaceLocals(map: TSSymbolMap)(implicit ns: TSNamespace) =
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 6a8e7d9e9d..4b84939bde 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -43,14 +43,16 @@ object Converter {
     case TSArrayType(element) => s"MutArray<${convert(element)}>"
     case TSEnumType => "int"
     case TSMemberType(base, _) => convert(base) // TODO: support private/protected members
-    case TSInterfaceType(name, members, typeVars, parents) => convertRecord(s"trait $name", members, typeVars, parents, Map())(indent)
-    case TSClassType(name, members, statics, typeVars, parents) => convertRecord(s"class $name", members, typeVars, parents, statics)(indent)
+    case TSInterfaceType(name, members, typeVars, parents) =>
+      convertRecord(s"trait $name", members, typeVars, parents, Map(), List())(indent)
+    case TSClassType(name, members, statics, typeVars, parents, cons) =>
+      convertRecord(s"class $name", members, typeVars, parents, statics, cons)(indent)
     case TSSubstitutionType(base, applied) => s"${base}<${applied.map((app) => convert(app)).reduceLeft((res, s) => s"$res, $s")}>"
     case overload @ TSIgnoredOverload(base, _) => s"${convert(base)} ${overload.warning}"
   }
 
-  private def convertRecord(typeName: String, members: Map[String, TSMemberType],
-    typeVars: List[TSTypeParameter], parents: List[TSType], statics: Map[String, TSMemberType])(implicit indent: String) = {
+  private def convertRecord(typeName: String, members: Map[String, TSMemberType], typeVars: List[TSTypeParameter],
+    parents: List[TSType], statics: Map[String, TSMemberType], constructorList: List[TSType])(implicit indent: String) = {
     val allRecs = members.toList.map((m) => m._2.modifier match {
       case Public =>
         if (typeName === "trait ") s"${m._1}: ${convert(m._2)},"
@@ -94,9 +96,13 @@ object Converter {
     
     if (typeName === "trait ") body // anonymous interfaces
     else { // named interfaces and classes
+      val constructor =
+        if (constructorList.isEmpty) "()"
+        else s"(${constructorList.map(p => "_: " + convert(p)).reduceLeft((res, p) => s"$res, $p")})"
+
       val inheritance =
-        if (parents.isEmpty) ""
-        else parents.foldLeft("(): ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
+        if (parents.isEmpty) constructor
+        else parents.foldLeft(s"$constructor: ")((b, p) => s"$b${convert(p)}, ").dropRight(2)
       if (typeVars.isEmpty) s"${indent}$typeName$inheritance $body"
       else
         s"${indent}$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}>$inheritance $body" // TODO: add constraints
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala b/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
index f65df790c7..fa1746687e 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
@@ -22,6 +22,7 @@ case class TSClassType(
     statics: Map[String, TSMemberType],
     typeVars: List[TSTypeParameter],
     parents: List[TSType],
+    constructor: List[TSType]
   ) extends TSType
 
 case class TSInterfaceType(
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index ffea1f6b50..59b3d5b55a 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -4,8 +4,8 @@ fun first: MutArray<string> => string
 fun getZero3: unit => MutArray<number>
 fun first2: MutArray<number => number> => number => number
 fun doEs: MutArray<int> => MutArray<int>
-class C {}
-trait I {
+class C() {}
+trait I() {
   let i: number
 }
 fun doCs: MutArray<C> => MutArray<C>
@@ -14,10 +14,10 @@ fun inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
 fun clean: MutArray<(string, number, )> => MutArray<(string, number, )>
 fun translate: MutArray<T> => MutArray<U>
 fun uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
-class Temp<T> {
+class Temp<T>() {
   let x: T
 }
 fun ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
 fun tat: MutArray<Temp<T>> => MutArray<Temp<T>>
-//│ |#fun| |first|#:| |MutArray|‹|string|›| |=>| |string|↵|#fun| |getZero3|#:| |unit| |=>| |MutArray|‹|number|›|↵|#fun| |first2|#:| |MutArray|‹|number| |=>| |number|›| |=>| |number| |=>| |number|↵|#fun| |doEs|#:| |MutArray|‹|int|›| |=>| |MutArray|‹|int|›|↵|#class| |C| |{||}|↵|#trait| |I| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|#:| |MutArray|‹|C|›| |=>| |MutArray|‹|C|›|↵|#fun| |doIs|#:| |MutArray|‹|I|›| |=>| |MutArray|‹|I|›|↵|#fun| |inter|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›| |=>| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|#:| |MutArray|‹|(|string|,| |number|,| |)|›| |=>| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|#:| |MutArray|‹|T|›| |=>| |MutArray|‹|U|›|↵|#fun| |uu|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›| |=>| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|#:| |MutArray|‹|Temp|‹|bool|›|›| |=>| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|#:| |MutArray|‹|Temp|‹|T|›|›| |=>| |MutArray|‹|Temp|‹|T|›|›|
+//│ |#fun| |first|#:| |MutArray|‹|string|›| |=>| |string|↵|#fun| |getZero3|#:| |unit| |=>| |MutArray|‹|number|›|↵|#fun| |first2|#:| |MutArray|‹|number| |=>| |number|›| |=>| |number| |=>| |number|↵|#fun| |doEs|#:| |MutArray|‹|int|›| |=>| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|#:| |MutArray|‹|C|›| |=>| |MutArray|‹|C|›|↵|#fun| |doIs|#:| |MutArray|‹|I|›| |=>| |MutArray|‹|I|›|↵|#fun| |inter|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›| |=>| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|#:| |MutArray|‹|(|string|,| |number|,| |)|›| |=>| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|#:| |MutArray|‹|T|›| |=>| |MutArray|‹|U|›|↵|#fun| |uu|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›| |=>| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|#:| |MutArray|‹|Temp|‹|bool|›|›| |=>| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|#:| |MutArray|‹|Temp|‹|T|›|›| |=>| |MutArray|‹|Temp|‹|T|›|›|
 //│ Parsed: {fun first: [] -> MutArray[string] -> string; fun getZero3: [] -> unit -> MutArray[number]; fun first2: [] -> MutArray[number -> number] -> number -> number; fun doEs: [] -> MutArray[int] -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> MutArray[C] -> MutArray[C]; fun doIs: [] -> MutArray[I] -> MutArray[I]; fun inter: [] -> MutArray[(U,) & (T,)] -> MutArray[(U,) & (T,)]; fun clean: [] -> MutArray[(string, number,)] -> MutArray[(string, number,)]; fun translate: [] -> MutArray[T] -> MutArray[U]; fun uu: [] -> MutArray[(number,) | (bool,)] -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> MutArray[Temp[bool]] -> MutArray[Temp[bool]]; fun tat: [] -> MutArray[Temp[T]] -> MutArray[Temp[T]]}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index cdffcdfaa9..8c5e6e7efb 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -14,15 +14,15 @@ fun fail: unit => nothing
 fun create: unit => object
 fun pa: number => number
 fun wtf: anything => unit
-class Foooooo {
+class Foooooo() {
   let ooooooo: number
 }
 fun inn: Foooooo => unit
 fun out: unit => Foooooo
-trait Barrrrrrrrr {
+trait Barrrrrrrrr() {
   let rrrrrrr: number
 }
 fun inn2: Barrrrrrrrr => unit
 fun out2: unit => Barrrrrrrrr
-//│ |#fun| |hello|#:| |unit| |=>| |unit|↵|#fun| |add|#:| |number| |=>| |number| |=>| |number|↵|#fun| |sub|#:| |number| |=>| |number| |=>| |number|↵|#fun| |foo|#:| |unit| |=>| |number|↵|#fun| |id|#:| |anything| |=>| |anything|↵|#fun| |odd|#:| |number| |=>| |bool|↵|#fun| |isnull|#:| |anything| |=>| |bool|↵|#fun| |bar|#:| |unit| |=>| |anything|↵|#fun| |nu|#:| |null| |=>| |null|↵|#fun| |un|#:| |undefined| |=>| |undefined|↵|#fun| |fail|#:| |unit| |=>| |nothing|↵|#fun| |create|#:| |unit| |=>| |object|↵|#fun| |pa|#:| |number| |=>| |number|↵|#fun| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|#:| |Foooooo| |=>| |unit|↵|#fun| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#fun| |out2|#:| |unit| |=>| |Barrrrrrrrr|
+//│ |#fun| |hello|#:| |unit| |=>| |unit|↵|#fun| |add|#:| |number| |=>| |number| |=>| |number|↵|#fun| |sub|#:| |number| |=>| |number| |=>| |number|↵|#fun| |foo|#:| |unit| |=>| |number|↵|#fun| |id|#:| |anything| |=>| |anything|↵|#fun| |odd|#:| |number| |=>| |bool|↵|#fun| |isnull|#:| |anything| |=>| |bool|↵|#fun| |bar|#:| |unit| |=>| |anything|↵|#fun| |nu|#:| |null| |=>| |null|↵|#fun| |un|#:| |undefined| |=>| |undefined|↵|#fun| |fail|#:| |unit| |=>| |nothing|↵|#fun| |create|#:| |unit| |=>| |object|↵|#fun| |pa|#:| |number| |=>| |number|↵|#fun| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|#:| |Foooooo| |=>| |unit|↵|#fun| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#fun| |out2|#:| |unit| |=>| |Barrrrrrrrr|
 //│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index a1a3a805a5..302e622f68 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,25 +1,25 @@
 :NewParser
 :ParseOnly
-class Student {
+class Student(_: string, _: number) {
   let name: string
   fun isFriend: Student => bool
   fun addScore: string => number => unit
   fun getID: unit => number
 }
-class Foo<T> {
+class Foo<T>() {
   fun bar: T => unit
 }
-class EZ {
+class EZ() {
   fun inc: number => number
 }
-class Outer {
-  class Inner {
+class Outer() {
+  class Inner() {
     let a: number
   }
 }
-class TTT<T> {
+class TTT<T>() {
   fun ttt: T => T
   fun ttt2: T => T
 }
-//│ |#class| |Student| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|#:| |Student| |=>| |bool|↵|#fun| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#fun| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›| |{|→|#fun| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ| |{|→|#fun| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer| |{|→|#class| |Inner| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›| |{|→|#fun| |ttt|#:| |T| |=>| |T|↵|#fun| |ttt2|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {class Student() {let name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}
+//│ |#class| |Student|(|_|#:| |string|,| |_|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|#:| |Student| |=>| |bool|↵|#fun| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#fun| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|#:| |T| |=>| |T|↵|#fun| |ttt2|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {class Student(_: string, _: number,) {let name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 67ed2b87b3..d85f181432 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -1,15 +1,15 @@
 :NewParser
 :ParseOnly
-class A {
+class A() {
   fun foo: unit => unit
 }
 class B(): A {}
-class C<T> {
+class C<T>() {
   fun set: T => unit
   fun get: unit => T
 }
 class D(): C<number> {}
-trait Wu {
+trait Wu() {
   let x: bool
 }
 class WuWu(): Wu {
@@ -21,24 +21,24 @@ trait WuWuWu(): WuWu {
 trait Never(): WuWuWu {
   fun w: unit => nothing
 }
-class VG<T> {
+class VG<T>() {
   let x: T
 }
 class Home<T>(): VG<string> {
   let y: T
 }
-trait O<I> {
+trait O<I>() {
   fun xx: I => I
 }
 class OR<R>(): O<R> {
   fun xx: R => R
 }
 namespace Five {
-  class ROTK {
+  class ROTK() {
     let wu: string
   }
   class Y(): Five'ROTK {}
 }
 class Y(): Five'ROTK {}
-//│ |#class| |A| |{|→|#fun| |foo|#:| |unit| |=>| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›| |{|→|#fun| |set|#:| |T| |=>| |unit|↵|#fun| |get|#:| |unit| |=>| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|#:| |unit| |=>| |nothing|←|↵|}|↵|#class| |VG|‹|T|›| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›| |{|→|#fun| |xx|#:| |I| |=>| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|#:| |R| |=>| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
+//│ |#class| |A|(||)| |{|→|#fun| |foo|#:| |unit| |=>| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|#:| |T| |=>| |unit|↵|#fun| |get|#:| |unit| |=>| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|#:| |unit| |=>| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|#:| |I| |=>| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|#:| |R| |=>| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
 //│ Parsed: {class A() {fun foo: [] -> unit -> unit}; class B(): A {}; class C[T]() {fun set: [] -> T -> unit; fun get: [] -> unit -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> unit -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> I -> I}; class OR[R](): O‹R› {fun xx: [] -> R -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 2a9d7572d7..5c3b2bcc42 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -1,40 +1,40 @@
 :NewParser
 :ParseOnly
-trait IFoo {
+trait IFoo() {
   let a: string
   fun b: number => number
   fun c: unit => bool
   fun d: string => unit
 }
-trait II<T> {
+trait II<T>() {
   fun test: T => number
 }
 fun create: unit => (v: number,)
 fun get: (t: string,) => string
-trait IEvent {
+trait IEvent() {
   fun callback: unit => number => unit
 }
-trait SearchFunc {
+trait SearchFunc() {
   fun __call: string => string => bool
 }
-trait StringArray {
+trait StringArray() {
   fun __index: number => string
 }
-trait Counter {
+trait Counter() {
   fun __call: number => string
   let interval: number
   fun reset: unit => unit
 }
-trait Simple {
+trait Simple() {
   let a: number
   fun b: bool => string
 }
-trait Simple2<T> {
+trait Simple2<T>() {
   let abc: T
 }
 trait Next(): Simple {}
-trait TTT<T> {
+trait TTT<T>() {
   fun ttt: T => T
 }
-//│ |#trait| |IFoo| |{|→|#let| |a|#:| |string|↵|#fun| |b|#:| |number| |=>| |number|↵|#fun| |c|#:| |unit| |=>| |bool|↵|#fun| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›| |{|→|#fun| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#fun| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent| |{|→|#fun| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc| |{|→|#fun| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray| |{|→|#fun| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter| |{|→|#fun| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple| |{|→|#let| |a|#:| |number|↵|#fun| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›| |{|→|#fun| |ttt|#:| |T| |=>| |T|←|↵|}|
+//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|#:| |number| |=>| |number|↵|#fun| |c|#:| |unit| |=>| |bool|↵|#fun| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#fun| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|#:| |T| |=>| |T|←|↵|}|
 //│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> number -> number; fun c: [] -> unit -> bool; fun d: [] -> string -> unit}; trait II[T](): {fun test: [] -> T -> number}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(): {fun callback: [] -> unit -> number -> unit}; trait SearchFunc(): {fun __call: [] -> string -> string -> bool}; trait StringArray(): {fun __index: [] -> number -> string}; trait Counter(): {fun __call: [] -> number -> string; let interval: [] -> number; fun reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index e2e2d6ae54..9f45236fe8 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -3,10 +3,10 @@
 fun extend: T => U => (T) & (U)
 fun foo: (T) & (U) => unit
 fun over: (number => string) & (object => string) => string
-trait IA {
+trait IA() {
   let x: number
 }
-trait IB {
+trait IB() {
   let y: number
 }
 fun iii: (IA) & (IB) => (IA) & (IB)
@@ -14,8 +14,8 @@ fun uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T
 fun iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
 fun arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
 fun tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
-class A {}
-class B {}
+class A() {}
+class B() {}
 fun inter: (A) & (B) => (A) & (B)
-//│ |#fun| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#fun| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#fun| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A| |{||}|↵|#class| |B| |{||}|↵|#fun| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
+//│ |#fun| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#fun| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#fun| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
 //│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index 921304da1f..71fc7526f6 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -3,7 +3,7 @@
 fun multi1: number => number
 fun multi3: unit => unit
 class Foo(): Base {}
-trait AnotherBase {
+trait AnotherBase() {
   let y: string
 }
 namespace N {
@@ -13,10 +13,10 @@ namespace N {
 }
 fun multi2: string => string
 fun multi4: unit => unit
-trait Base {
+trait Base() {
   let a: number
 }
 class AnotherFoo(): AnotherBase {}
 fun multi5: unit => unit
-//│ |#fun| |multi1|#:| |number| |=>| |number|↵|#fun| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|#:| |unit| |=>| |unit|↵|#fun| |g|#:| |unit| |=>| |unit|↵|#fun| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#fun| |multi2|#:| |string| |=>| |string|↵|#fun| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|#:| |unit| |=>| |unit|
+//│ |#fun| |multi1|#:| |number| |=>| |number|↵|#fun| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|#:| |unit| |=>| |unit|↵|#fun| |g|#:| |unit| |=>| |unit|↵|#fun| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#fun| |multi2|#:| |string| |=>| |string|↵|#fun| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|#:| |unit| |=>| |unit|
 //│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 08df8b8182..16d945ae26 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -3,10 +3,10 @@
 namespace N1 {
   fun f: anything => number
   fun ff: anything => number
-  class C {
+  class C() {
     fun f: unit => unit
   }
-  trait I {
+  trait I() {
     fun f: unit => number
   }
   namespace N2 {
@@ -17,10 +17,10 @@ namespace N1 {
 }
 namespace AA {
   fun f: anything => string
-  class C {
+  class C() {
     fun f: unit => unit
   }
-  trait I {
+  trait I() {
     fun f: unit => number
   }
   namespace N2 {
@@ -28,5 +28,5 @@ namespace AA {
 }
 fun f1: N1'C => N1'C
 fun f2: AA'C => AA'C
-//│ |#namespace| |N1| |{|→|#fun| |f|#:| |anything| |=>| |number|↵|#fun| |ff|#:| |anything| |=>| |number|↵|#class| |C| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|#:| |bool| |=>| |number|↵|#fun| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|#:| |anything| |=>| |string|↵|#class| |C| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|#:| |N1'C| |=>| |N1'C|↵|#fun| |f2|#:| |AA'C| |=>| |AA'C|
+//│ |#namespace| |N1| |{|→|#fun| |f|#:| |anything| |=>| |number|↵|#fun| |ff|#:| |anything| |=>| |number|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|#:| |bool| |=>| |number|↵|#fun| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|#:| |anything| |=>| |string|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|#:| |N1'C| |=>| |N1'C|↵|#fun| |f2|#:| |AA'C| |=>| |AA'C|
 //│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 3b5053ba8a..5ff5ddaeb4 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -4,21 +4,21 @@ fun buildName: string => (string) | (undefined) => string
 fun buildName2: string => (string) | (undefined) => string
 fun buildName3: string => MutArray<string> => string
 fun buildName4: string => MutArray<anything> => string
-trait SquareConfig {
+trait SquareConfig() {
   let color: (string) | (undefined)
   let width: (number) | (undefined)
 }
 fun did: number => (number => number) | (undefined) => number
 fun getOrElse: (MutArray<object>) | (undefined) => object
-class ABC {}
+class ABC() {}
 fun testABC: (ABC) | (undefined) => unit
 fun testSquareConfig: (SquareConfig) | (undefined) => unit
 fun err: ((number, string, )) | (undefined) => unit
 fun toStr: ((number) | (bool)) | (undefined) => string
 fun boo: ((T) & (U)) | (undefined) => unit
-class B<T> {
+class B<T>() {
   let b: T
 }
 fun boom: (B<nothing>) | (undefined) => anything
-//│ |#fun| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#fun| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#fun| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC| |{||}|↵|#fun| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
+//│ |#fun| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#fun| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#fun| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
 //│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 7f038398bc..86431a5f01 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,14 +1,14 @@
 :NewParser
 :ParseOnly
 fun f: (number => string) & (string => string)
-class M {
+class M() {
   let foo: (number => string) & (string => string)
 }
 fun app: ((string => unit) => number => unit) & ((string => unit) => string => unit)
 fun create: (number => unit => bool) & (bool => unit => bool)
 fun g0: (MutArray<string> => string) & (MutArray<object> => string)
 fun db: (number => MutArray<number>) & (object => MutArray<number>)
-class N {}
+class N() {}
 fun id: (M => unit) & (N => unit)
 fun tst: ((z: number,) => (y: string,)) & ((z: bool,) => (y: string,))
 fun op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
@@ -18,9 +18,9 @@ fun doSome: anything => unit /* warning: the overload of function doSome is not
 namespace XX {
   fun f: T => anything => string /* warning: the overload of function f is not supported yet. */
 }
-class WWW {
+class WWW() {
   fun F: T => anything /* warning: the overload of function F is not supported yet. */
 }
 fun baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW| |{|→|#fun| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
+//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
 //│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> unit; namespace XX(): {fun f: [] -> T -> anything -> string}; class WWW() {fun F: [] -> T -> anything}; fun baz: [] -> unit -> anything}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 1f9ea8ebba..06cfb5e58a 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -11,10 +11,10 @@ fun s2: (bool, (string) | (number), ) => (string) | (number)
 fun ex: T => U => (T, U, (T) & (U), )
 fun foo: ((T) & (U), ) => unit
 fun conv: (y: number,) => ((y: number,), (z: string,), )
-class A {
+class A() {
   let x: number
 }
-class B {}
+class B() {}
 fun swap: (A, B, ) => (B, A, )
-//│ |#fun| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#fun| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#fun| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#fun| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#fun| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#fun| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#fun| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#fun| |conv|#:| |(|y|#:| |number|,|)| |=>| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B| |{||}|↵|#fun| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
+//│ |#fun| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#fun| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#fun| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#fun| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#fun| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#fun| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#fun| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#fun| |conv|#:| |(|y|#:| |number|,|)| |=>| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
 //│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index a949273357..b67e9db3b4 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,29 +1,29 @@
 :NewParser
 :ParseOnly
 fun inc: T => number
-class CC<T> {
+class CC<T>() {
   fun print: T => unit
 }
 fun con: T => U
-class Printer<T> {
+class Printer<T>() {
   fun print: T => unit
 }
 fun setStringPrinter: Printer<string> => unit
 fun getStringPrinter: unit => Printer<string>
 fun foo: Printer<T> => T => T
 fun foo2: Printer<T> => T => T
-class F<T> {
+class F<T>() {
   let x: T
   fun GG: U => T
 }
-trait I<T> {
+trait I<T>() {
   let x: T
   fun GG: U => T
 }
-class FFF<T> {
+class FFF<T>() {
   fun fff: T => unit
 }
 fun fff: FFF<string> => string => unit
 fun getFFF: unit => FFF<number>
-//│ |#fun| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#fun| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#fun| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#fun| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›| |{|→|#fun| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#fun| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
+//│ |#fun| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#fun| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#fun| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#fun| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#fun| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
 //│ Parsed: {fun inc: [] -> T -> number; class CC[T]() {fun print: [] -> T -> unit}; fun con: [] -> T -> U; class Printer[T]() {fun print: [] -> T -> unit}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T]() {let x: [] -> T; fun GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> U -> T}; class FFF[T]() {fun fff: [] -> T -> unit}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
diff --git a/ts2mls/js/src/test/typescript/ClassMember.ts b/ts2mls/js/src/test/typescript/ClassMember.ts
index 26d669f166..da45f741b0 100644
--- a/ts2mls/js/src/test/typescript/ClassMember.ts
+++ b/ts2mls/js/src/test/typescript/ClassMember.ts
@@ -1,7 +1,7 @@
 class Student {
   name: string
 
-  constructor() {}
+  constructor(s: string, age: number) {}
 
   
   getID() { return 114514; }

From 90738e27ed9b0c724b9e6a60b5af87cbc90bf7b9 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Fri, 16 Sep 2022 09:50:31 +0800
Subject: [PATCH 23/40] Add tparams for fun

---
 shared/src/main/scala/mlscript/NewParser.scala | 15 +++++++++++++--
 shared/src/test/diff/parser/TypeParams.mls     | 11 +++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala
index a40598ba47..0c1cf9d7df 100644
--- a/shared/src/main/scala/mlscript/NewParser.scala
+++ b/shared/src/main/scala/mlscript/NewParser.scala
@@ -311,6 +311,17 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
                 (Var("<error>").withLoc(curLoc.map(_.left)), false)
             }
             foundErr || !success pipe { implicit fe =>
+              val tparams = yeetSpaces match {
+                case (br @ BRACKETS(Angle, toks), loc) :: _ =>
+                  consume
+                  val ts = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map {
+                    case (N, Fld(false, false, v @ Var(nme))) =>
+                      TypeName(nme).withLocOf(v)
+                    case _ => ???
+                  }
+                  ts
+                case _ => Nil
+              }
               val ps = funParams
               val asc = yeetSpaces match {
                 case (KEYWORD(":"), _) :: _ =>
@@ -323,11 +334,11 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
                   consume
                   val body = expr(0)
                   val annotatedBody = asc.fold(body)(ty => Asc(body, ty))
-                  R(NuFunDef(isLetRec, v, Nil, L(ps.foldRight(annotatedBody)((i, acc) => Lam(i, acc)))))
+                  R(NuFunDef(isLetRec, v, tparams, L(ps.foldRight(annotatedBody)((i, acc) => Lam(i, acc)))))
                 case c =>
                   asc match {
                     case S(ty) =>
-                      R(NuFunDef(isLetRec, v, Nil, R(PolyType(Nil, ps.foldRight(ty)((p, r) => Function(p.toType match {
+                      R(NuFunDef(isLetRec, v, tparams, R(PolyType(Nil, ps.foldRight(ty)((p, r) => Function(p.toType match {
                         case L(diag) => raise(diag); Top // TODO better
                         case R(tp) => tp
                       }, r)))))) // TODO rm PolyType after FCP is merged
diff --git a/shared/src/test/diff/parser/TypeParams.mls b/shared/src/test/diff/parser/TypeParams.mls
index d93402b47b..ab6918b6ad 100644
--- a/shared/src/test/diff/parser/TypeParams.mls
+++ b/shared/src/test/diff/parser/TypeParams.mls
@@ -115,3 +115,14 @@ foo[S, T](1, 2, 3) & Bar[U]("ok")
 //│ ╙──       	     ^
 //│ Parsed: {& ((foo)[S] (1, 2, 3,),) ((Bar)[U] ("ok",),)}
 
+class Foo<T> {}
+//│ |#class| |Foo|‹|T|›| |{||}|
+//│ Parsed: {class Foo[T]() {}}
+
+fun foo<T>(x: T): string = "rua"
+//│ |#fun| |foo|‹|T|›|(|x|#:| |T|)|#:| |string| |#=| |"rua"|
+//│ Parsed: {fun foo = x: T, => "rua" : TypeName(string)}
+
+foo<int>(42)
+//│ |foo|‹|int|›|(|42|)|
+//│ Parsed: {foo‹int› (42,)}

From 4e5fc5e5fb50528842ddd019df281f0d078badcc Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Fri, 16 Sep 2022 10:10:09 +0800
Subject: [PATCH 24/40] Add typeparameters

---
 .../src/main/scala/ts2mls/TSNamespace.scala   |  4 +-
 .../main/scala/ts2mls/types/Converter.scala   |  9 +++++
 ts2mls/js/src/test/diff/Array.d.mls           | 28 ++++++-------
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  | 40 +++++++++----------
 ts2mls/js/src/test/diff/Enum.d.mls            | 10 ++---
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   | 10 ++---
 ts2mls/js/src/test/diff/InterfaceMember.d.mls |  8 ++--
 ts2mls/js/src/test/diff/Intersection.d.mls    | 22 +++++-----
 ts2mls/js/src/test/diff/MultiFiles.d.mls      | 20 +++++-----
 ts2mls/js/src/test/diff/Namespace.d.mls       | 18 ++++-----
 ts2mls/js/src/test/diff/Optional.d.mls        | 28 ++++++-------
 ts2mls/js/src/test/diff/Tuple.d.mls           | 28 ++++++-------
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 20 +++++-----
 ts2mls/js/src/test/diff/Union.d.mls           | 18 ++++-----
 14 files changed, 136 insertions(+), 127 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index 92ad84a197..ad54f7f147 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -49,7 +49,7 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
           case inter: TSIntersectionType => // overloaded functions
             writer.writeln(s"${indent}fun ${name}: ${Converter.convert(inter)}")
           case f: TSFunctionType =>
-            writer.writeln(s"${indent}fun ${name}: ${Converter.convert(f)}")
+            writer.writeln(Converter.generateFunDeclaration(f, name)(indent))
           // {
           //   val typeParams = f.typeVars.map((t) => t.name)
           //   if (typeParams.isEmpty)
@@ -67,7 +67,7 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
           //       writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(overload)}")
           // }
           case _: TSClassType => writer.writeln(Converter.convert(mem)(indent))
-          case _ @ TSInterfaceType(name, _, _, _) if (name =/= "") =>
+          case TSInterfaceType(name, _, _, _) if (name =/= "") =>
             writer.writeln(Converter.convert(mem)(indent))
           case _ => writer.writeln(Converter.convert(mem))
         }
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 4b84939bde..2302f882fb 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -18,6 +18,15 @@ object Converter {
     "false" -> "" // will not appear individually
   )
 
+  def generateFunDeclaration(tsType: TSType, name: String)(implicit indent: String = ""): String = tsType match {
+    case TSFunctionType(params, res, typeVars) => {
+      val pList = if (params.isEmpty) "" else params.map(p => "_: " + convert(p)("")).reduceLeft((r, p) => s"$r, $p")
+      val tpList = if (typeVars.isEmpty) "" else s"<${typeVars.map(p => convert(p)("")).reduceLeft((r, p) => s"$r, $p")}>"
+      s"${indent}fun $name$tpList($pList): ${convert(res)("")}"
+    }
+    case _ => convert(tsType) // TODO: overload
+  }
+
   def convert(tsType: TSType)(implicit indent: String = ""): String = tsType match {
     case TSPrimitiveType(typeName) => primitiveName(typeName)
     case TSReferenceType(name) => name
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 59b3d5b55a..1f2ca1f3fa 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,23 +1,23 @@
 :NewParser
 :ParseOnly
-fun first: MutArray<string> => string
-fun getZero3: unit => MutArray<number>
-fun first2: MutArray<number => number> => number => number
-fun doEs: MutArray<int> => MutArray<int>
+fun first(_: MutArray<string>): string
+fun getZero3(): MutArray<number>
+fun first2(_: MutArray<number => number>): number => number
+fun doEs(_: MutArray<int>): MutArray<int>
 class C() {}
 trait I() {
   let i: number
 }
-fun doCs: MutArray<C> => MutArray<C>
-fun doIs: MutArray<I> => MutArray<I>
-fun inter: MutArray<(U) & (T)> => MutArray<(U) & (T)>
-fun clean: MutArray<(string, number, )> => MutArray<(string, number, )>
-fun translate: MutArray<T> => MutArray<U>
-fun uu: MutArray<(number) | (bool)> => MutArray<(number) | (bool)>
+fun doCs(_: MutArray<C>): MutArray<C>
+fun doIs(_: MutArray<I>): MutArray<I>
+fun inter<U, T>(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
+fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
+fun translate<T, U>(_: MutArray<T>): MutArray<U>
+fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
 class Temp<T>() {
   let x: T
 }
-fun ta: MutArray<Temp<bool>> => MutArray<Temp<bool>>
-fun tat: MutArray<Temp<T>> => MutArray<Temp<T>>
-//│ |#fun| |first|#:| |MutArray|‹|string|›| |=>| |string|↵|#fun| |getZero3|#:| |unit| |=>| |MutArray|‹|number|›|↵|#fun| |first2|#:| |MutArray|‹|number| |=>| |number|›| |=>| |number| |=>| |number|↵|#fun| |doEs|#:| |MutArray|‹|int|›| |=>| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|#:| |MutArray|‹|C|›| |=>| |MutArray|‹|C|›|↵|#fun| |doIs|#:| |MutArray|‹|I|›| |=>| |MutArray|‹|I|›|↵|#fun| |inter|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›| |=>| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|#:| |MutArray|‹|(|string|,| |number|,| |)|›| |=>| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|#:| |MutArray|‹|T|›| |=>| |MutArray|‹|U|›|↵|#fun| |uu|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›| |=>| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|#:| |MutArray|‹|Temp|‹|bool|›|›| |=>| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|#:| |MutArray|‹|Temp|‹|T|›|›| |=>| |MutArray|‹|Temp|‹|T|›|›|
-//│ Parsed: {fun first: [] -> MutArray[string] -> string; fun getZero3: [] -> unit -> MutArray[number]; fun first2: [] -> MutArray[number -> number] -> number -> number; fun doEs: [] -> MutArray[int] -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> MutArray[C] -> MutArray[C]; fun doIs: [] -> MutArray[I] -> MutArray[I]; fun inter: [] -> MutArray[(U,) & (T,)] -> MutArray[(U,) & (T,)]; fun clean: [] -> MutArray[(string, number,)] -> MutArray[(string, number,)]; fun translate: [] -> MutArray[T] -> MutArray[U]; fun uu: [] -> MutArray[(number,) | (bool,)] -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> MutArray[Temp[bool]] -> MutArray[Temp[bool]]; fun tat: [] -> MutArray[Temp[T]] -> MutArray[Temp[T]]}
+fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
+fun tat<T>(_: MutArray<Temp<T>>): MutArray<Temp<T>>
+//│ |#fun| |first|(|_|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|_|#:| |MutArray|‹|number| |=>| |number|›|)|#:| |number| |=>| |number|↵|#fun| |doEs|(|_|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|_|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|_|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|_|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|_|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|_|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|_|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|)|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|_|#:| |MutArray|‹|Temp|‹|bool|›|›|)|#:| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|‹|T|›|(|_|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|
+//│ Parsed: {fun first: [] -> (_: MutArray[string],) -> string; fun getZero3: [] -> () -> MutArray[number]; fun first2: [] -> (_: MutArray[number -> number],) -> number -> number; fun doEs: [] -> (_: MutArray[int],) -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> (_: MutArray[C],) -> MutArray[C]; fun doIs: [] -> (_: MutArray[I],) -> MutArray[I]; fun inter: [] -> (_: MutArray[(U,) & (T,)],) -> MutArray[(U,) & (T,)]; fun clean: [] -> (_: MutArray[(string, number,)],) -> MutArray[(string, number,)]; fun translate: [] -> (_: MutArray[T],) -> MutArray[U]; fun uu: [] -> (_: MutArray[(number,) | (bool,)],) -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> (_: MutArray[Temp[bool]],) -> MutArray[Temp[bool]]; fun tat: [] -> (_: MutArray[Temp[T]],) -> MutArray[Temp[T]]}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 8c5e6e7efb..66f25c245a 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,28 +1,28 @@
 :NewParser
 :ParseOnly
-fun hello: unit => unit
-fun add: number => number => number
-fun sub: number => number => number
-fun foo: unit => number
-fun id: anything => anything
-fun odd: number => bool
-fun isnull: anything => bool
-fun bar: unit => anything
-fun nu: null => null
-fun un: undefined => undefined
-fun fail: unit => nothing
-fun create: unit => object
-fun pa: number => number
-fun wtf: anything => unit
+fun hello(): unit
+fun add(_: number, _: number): number
+fun sub(_: number, _: number): number
+fun foo(): number
+fun id(_: anything): anything
+fun odd(_: number): bool
+fun isnull(_: anything): bool
+fun bar(): anything
+fun nu(_: null): null
+fun un(_: undefined): undefined
+fun fail(): nothing
+fun create(): object
+fun pa(_: number): number
+fun wtf(_: anything): unit
 class Foooooo() {
   let ooooooo: number
 }
-fun inn: Foooooo => unit
-fun out: unit => Foooooo
+fun inn(_: Foooooo): unit
+fun out(): Foooooo
 trait Barrrrrrrrr() {
   let rrrrrrr: number
 }
-fun inn2: Barrrrrrrrr => unit
-fun out2: unit => Barrrrrrrrr
-//│ |#fun| |hello|#:| |unit| |=>| |unit|↵|#fun| |add|#:| |number| |=>| |number| |=>| |number|↵|#fun| |sub|#:| |number| |=>| |number| |=>| |number|↵|#fun| |foo|#:| |unit| |=>| |number|↵|#fun| |id|#:| |anything| |=>| |anything|↵|#fun| |odd|#:| |number| |=>| |bool|↵|#fun| |isnull|#:| |anything| |=>| |bool|↵|#fun| |bar|#:| |unit| |=>| |anything|↵|#fun| |nu|#:| |null| |=>| |null|↵|#fun| |un|#:| |undefined| |=>| |undefined|↵|#fun| |fail|#:| |unit| |=>| |nothing|↵|#fun| |create|#:| |unit| |=>| |object|↵|#fun| |pa|#:| |number| |=>| |number|↵|#fun| |wtf|#:| |anything| |=>| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|#:| |Foooooo| |=>| |unit|↵|#fun| |out|#:| |unit| |=>| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|#:| |Barrrrrrrrr| |=>| |unit|↵|#fun| |out2|#:| |unit| |=>| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> unit -> unit; fun add: [] -> number -> number -> number; fun sub: [] -> number -> number -> number; fun foo: [] -> unit -> number; fun id: [] -> anything -> anything; fun odd: [] -> number -> bool; fun isnull: [] -> anything -> bool; fun bar: [] -> unit -> anything; fun nu: [] -> null -> null; fun un: [] -> undefined -> undefined; fun fail: [] -> unit -> nothing; fun create: [] -> unit -> object; fun pa: [] -> number -> number; fun wtf: [] -> anything -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> Foooooo -> unit; fun out: [] -> unit -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> Barrrrrrrrr -> unit; fun out2: [] -> unit -> Barrrrrrrrr}
+fun inn2(_: Barrrrrrrrr): unit
+fun out2(): Barrrrrrrrr
+//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |sub|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|_|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|_|#:| |number|)|#:| |bool|↵|#fun| |isnull|(|_|#:| |anything|)|#:| |bool|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|_|#:| |null|)|#:| |null|↵|#fun| |un|(|_|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|_|#:| |number|)|#:| |number|↵|#fun| |wtf|(|_|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|_|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|_|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (_: number, _: number,) -> number; fun sub: [] -> (_: number, _: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (_: anything,) -> anything; fun odd: [] -> (_: number,) -> bool; fun isnull: [] -> (_: anything,) -> bool; fun bar: [] -> () -> anything; fun nu: [] -> (_: null,) -> null; fun un: [] -> (_: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (_: number,) -> number; fun wtf: [] -> (_: anything,) -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> (_: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> (_: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index ab520f2345..57dcd7a5d2 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun pass: int => bool
-fun stop: unit => int
-fun g: int => int
-//│ |#fun| |pass|#:| |int| |=>| |bool|↵|#fun| |stop|#:| |unit| |=>| |int|↵|#fun| |g|#:| |int| |=>| |int|
-//│ Parsed: {fun pass: [] -> int -> bool; fun stop: [] -> unit -> int; fun g: [] -> int -> int}
+fun pass(_: int): bool
+fun stop(): int
+fun g(_: int): int
+//│ |#fun| |pass|(|_|#:| |int|)|#:| |bool|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|_|#:| |int|)|#:| |int|
+//│ Parsed: {fun pass: [] -> (_: int,) -> bool; fun stop: [] -> () -> int; fun g: [] -> (_: int,) -> int}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index ef4fc55d59..347a47434d 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun h1: (number => number) => number => number
-fun h2: string => unit => string
-fun h3: (number => number) => (number => number) => number => number
-//│ |#fun| |h1|#:| |(|number| |=>| |number|)| |=>| |number| |=>| |number|↵|#fun| |h2|#:| |string| |=>| |unit| |=>| |string|↵|#fun| |h3|#:| |(|number| |=>| |number|)| |=>| |(|number| |=>| |number|)| |=>| |number| |=>| |number|
-//│ Parsed: {fun h1: [] -> (number -> number) -> number -> number; fun h2: [] -> string -> unit -> string; fun h3: [] -> (number -> number) -> (number -> number) -> number -> number}
+fun h1(_: number => number, _: number): number
+fun h2(_: string): unit => string
+fun h3(_: number => number, _: number => number): number => number
+//│ |#fun| |h1|(|_|#:| |number| |=>| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |h2|(|_|#:| |string|)|#:| |unit| |=>| |string|↵|#fun| |h3|(|_|#:| |number| |=>| |number|,| |_|#:| |number| |=>| |number|)|#:| |number| |=>| |number|
+//│ Parsed: {fun h1: [] -> (_: number -> number, _: number,) -> number; fun h2: [] -> (_: string,) -> unit -> string; fun h3: [] -> (_: number -> number, _: number -> number,) -> number -> number}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 5c3b2bcc42..3687aa8955 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -9,8 +9,8 @@ trait IFoo() {
 trait II<T>() {
   fun test: T => number
 }
-fun create: unit => (v: number,)
-fun get: (t: string,) => string
+fun create(): (v: number,)
+fun get(_: (t: string,)): string
 trait IEvent() {
   fun callback: unit => number => unit
 }
@@ -36,5 +36,5 @@ trait Next(): Simple {}
 trait TTT<T>() {
   fun ttt: T => T
 }
-//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|#:| |number| |=>| |number|↵|#fun| |c|#:| |unit| |=>| |bool|↵|#fun| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|#:| |unit| |=>| |(|v|#:| |number|,|)|↵|#fun| |get|#:| |(|t|#:| |string|,|)| |=>| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> number -> number; fun c: [] -> unit -> bool; fun d: [] -> string -> unit}; trait II[T](): {fun test: [] -> T -> number}; fun create: [] -> unit -> (v: number,); fun get: [] -> (t: string,) -> string; trait IEvent(): {fun callback: [] -> unit -> number -> unit}; trait SearchFunc(): {fun __call: [] -> string -> string -> bool}; trait StringArray(): {fun __index: [] -> number -> string}; trait Counter(): {fun __call: [] -> number -> string; let interval: [] -> number; fun reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> T -> T}}
+//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|#:| |number| |=>| |number|↵|#fun| |c|#:| |unit| |=>| |bool|↵|#fun| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|_|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|#:| |T| |=>| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> number -> number; fun c: [] -> unit -> bool; fun d: [] -> string -> unit}; trait II[T](): {fun test: [] -> T -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (_: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> unit -> number -> unit}; trait SearchFunc(): {fun __call: [] -> string -> string -> bool}; trait StringArray(): {fun __index: [] -> number -> string}; trait Counter(): {fun __call: [] -> number -> string; let interval: [] -> number; fun reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> T -> T}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index 9f45236fe8..f8a7f862de 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,21 +1,21 @@
 :NewParser
 :ParseOnly
-fun extend: T => U => (T) & (U)
-fun foo: (T) & (U) => unit
-fun over: (number => string) & (object => string) => string
+fun extend<T, U>(_: T, _: U): (T) & (U)
+fun foo<T, U>(_: (T) & (U)): unit
+fun over(_: (number => string) & (object => string)): string
 trait IA() {
   let x: number
 }
 trait IB() {
   let y: number
 }
-fun iii: (IA) & (IB) => (IA) & (IB)
-fun uu: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P)) => ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
-fun iiii: ((U) & (T)) & (V) => ((U) & (T)) & (V)
-fun arr: (MutArray<U>) & (MutArray<T>) => (MutArray<U>) & (MutArray<T>)
-fun tt: ((U, T, )) & ((V, V, )) => ((U, T, )) & ((V, V, ))
+fun iii(_: (IA) & (IB)): (IA) & (IB)
+fun uu<U, V, T, P>(_: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
+fun iiii<U, T, V>(_: ((U) & (T)) & (V)): ((U) & (T)) & (V)
+fun arr<U, T>(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
+fun tt<U, T, V>(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
 class A() {}
 class B() {}
-fun inter: (A) & (B) => (A) & (B)
-//│ |#fun| |extend|#:| |T| |=>| |U| |=>| |(|T|)| |&| |(|U|)|↵|#fun| |foo|#:| |(|T|)| |&| |(|U|)| |=>| |unit|↵|#fun| |over|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)| |=>| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|#:| |(|IA|)| |&| |(|IB|)| |=>| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)| |=>| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)| |=>| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)| |=>| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)| |=>| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|#:| |(|A|)| |&| |(|B|)| |=>| |(|A|)| |&| |(|B|)|
-//│ Parsed: {fun extend: [] -> T -> U -> ((T,) & (U,)); fun foo: [] -> ((T,) & (U,)) -> unit; fun over: [] -> ((number -> string,) & (object -> string,)) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> ((IA,) & (IB,)) -> ((IA,) & (IB,)); fun uu: [] -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (((U,) & (T,),) & (V,)) -> (((U,) & (T,),) & (V,)); fun arr: [] -> ((MutArray[U],) & (MutArray[T],)) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (((U, T,),) & ((V, V,),)) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> ((A,) & (B,)) -> ((A,) & (B,))}
+fun inter(_: (A) & (B)): (A) & (B)
+//│ |#fun| |extend|‹|T|,| |U|›|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|‹|T|,| |U|›|(|_|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|_|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)|)|#:| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|(|_|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|‹|U|,| |V|,| |T|,| |P|›|(|_|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|‹|U|,| |T|,| |V|›|(|_|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|‹|U|,| |T|›|(|_|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|‹|U|,| |T|,| |V|›|(|_|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|(|_|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
+//│ Parsed: {fun extend: [] -> (_: T, _: U,) -> ((T,) & (U,)); fun foo: [] -> (_: (T,) & (U,),) -> unit; fun over: [] -> (_: (number -> string,) & (object -> string,),) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> (_: (IA,) & (IB,),) -> ((IA,) & (IB,)); fun uu: [] -> (_: ((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (_: ((U,) & (T,),) & (V,),) -> (((U,) & (T,),) & (V,)); fun arr: [] -> (_: (MutArray[U],) & (MutArray[T],),) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (_: ((U, T,),) & ((V, V,),),) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> (_: (A,) & (B,),) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index 71fc7526f6..f00c3ec11e 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,22 +1,22 @@
 :NewParser
 :ParseOnly
-fun multi1: number => number
-fun multi3: unit => unit
+fun multi1(_: number): number
+fun multi3(): unit
 class Foo(): Base {}
 trait AnotherBase() {
   let y: string
 }
 namespace N {
-  fun f: unit => unit
-  fun g: unit => unit
-  fun h: unit => unit
+  fun f(): unit
+  fun g(): unit
+  fun h(): unit
 }
-fun multi2: string => string
-fun multi4: unit => unit
+fun multi2(_: string): string
+fun multi4(): unit
 trait Base() {
   let a: number
 }
 class AnotherFoo(): AnotherBase {}
-fun multi5: unit => unit
-//│ |#fun| |multi1|#:| |number| |=>| |number|↵|#fun| |multi3|#:| |unit| |=>| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|#:| |unit| |=>| |unit|↵|#fun| |g|#:| |unit| |=>| |unit|↵|#fun| |h|#:| |unit| |=>| |unit|←|↵|}|↵|#fun| |multi2|#:| |string| |=>| |string|↵|#fun| |multi4|#:| |unit| |=>| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|#:| |unit| |=>| |unit|
-//│ Parsed: {fun multi1: [] -> number -> number; fun multi3: [] -> unit -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> unit -> unit; fun g: [] -> unit -> unit; fun h: [] -> unit -> unit}; fun multi2: [] -> string -> string; fun multi4: [] -> unit -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> unit -> unit}
+fun multi5(): unit
+//│ |#fun| |multi1|(|_|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|_|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit|
+//│ Parsed: {fun multi1: [] -> (_: number,) -> number; fun multi3: [] -> () -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> () -> unit; fun g: [] -> () -> unit; fun h: [] -> () -> unit}; fun multi2: [] -> (_: string,) -> string; fun multi4: [] -> () -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> () -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 16d945ae26..b804b89df7 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,8 +1,8 @@
 :NewParser
 :ParseOnly
 namespace N1 {
-  fun f: anything => number
-  fun ff: anything => number
+  fun f(_: anything): number
+  fun ff(_: anything): number
   class C() {
     fun f: unit => unit
   }
@@ -10,13 +10,13 @@ namespace N1 {
     fun f: unit => number
   }
   namespace N2 {
-    fun fff: bool => number
-    fun gg: N1'C => N1'C
+    fun fff(_: bool): number
+    fun gg(_: N1'C): N1'C
     class BBB(): N1'C {}
   }
 }
 namespace AA {
-  fun f: anything => string
+  fun f(_: anything): string
   class C() {
     fun f: unit => unit
   }
@@ -26,7 +26,7 @@ namespace AA {
   namespace N2 {
   }
 }
-fun f1: N1'C => N1'C
-fun f2: AA'C => AA'C
-//│ |#namespace| |N1| |{|→|#fun| |f|#:| |anything| |=>| |number|↵|#fun| |ff|#:| |anything| |=>| |number|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|#:| |bool| |=>| |number|↵|#fun| |gg|#:| |N1'C| |=>| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|#:| |anything| |=>| |string|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|#:| |N1'C| |=>| |N1'C|↵|#fun| |f2|#:| |AA'C| |=>| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> anything -> number; fun ff: [] -> anything -> number; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> bool -> number; fun gg: [] -> N1'C -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> anything -> string; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> N1'C -> N1'C; fun f2: [] -> AA'C -> AA'C}
+fun f1(_: N1'C): N1'C
+fun f2(_: AA'C): AA'C
+//│ |#namespace| |N1| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |number|↵|#fun| |ff|(|_|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|_|#:| |bool|)|#:| |number|↵|#fun| |gg|(|_|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|_|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|_|#:| |AA'C|)|#:| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> (_: anything,) -> number; fun ff: [] -> (_: anything,) -> number; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> (_: bool,) -> number; fun gg: [] -> (_: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (_: anything,) -> string; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> (_: N1'C,) -> N1'C; fun f2: [] -> (_: AA'C,) -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 5ff5ddaeb4..098b9dacdd 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
-fun buildName: string => (string) | (undefined) => string
-fun buildName2: string => (string) | (undefined) => string
-fun buildName3: string => MutArray<string> => string
-fun buildName4: string => MutArray<anything> => string
+fun buildName(_: string, _: (string) | (undefined)): string
+fun buildName2(_: string, _: (string) | (undefined)): string
+fun buildName3(_: string, _: MutArray<string>): string
+fun buildName4(_: string, _: MutArray<anything>): string
 trait SquareConfig() {
   let color: (string) | (undefined)
   let width: (number) | (undefined)
 }
-fun did: number => (number => number) | (undefined) => number
-fun getOrElse: (MutArray<object>) | (undefined) => object
+fun did(_: number, _: (number => number) | (undefined)): number
+fun getOrElse(_: (MutArray<object>) | (undefined)): object
 class ABC() {}
-fun testABC: (ABC) | (undefined) => unit
-fun testSquareConfig: (SquareConfig) | (undefined) => unit
-fun err: ((number, string, )) | (undefined) => unit
-fun toStr: ((number) | (bool)) | (undefined) => string
-fun boo: ((T) & (U)) | (undefined) => unit
+fun testABC(_: (ABC) | (undefined)): unit
+fun testSquareConfig(_: (SquareConfig) | (undefined)): unit
+fun err(_: ((number, string, )) | (undefined)): unit
+fun toStr(_: ((number) | (bool)) | (undefined)): string
+fun boo<T, U>(_: ((T) & (U)) | (undefined)): unit
 class B<T>() {
   let b: T
 }
-fun boom: (B<nothing>) | (undefined) => anything
-//│ |#fun| |buildName|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName2|#:| |string| |=>| |(|string|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |buildName3|#:| |string| |=>| |MutArray|‹|string|›| |=>| |string|↵|#fun| |buildName4|#:| |string| |=>| |MutArray|‹|anything|›| |=>| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|#:| |number| |=>| |(|number| |=>| |number|)| ||| |(|undefined|)| |=>| |number|↵|#fun| |getOrElse|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)| |=>| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|#:| |(|ABC|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |testSquareConfig|#:| |(|SquareConfig|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |err|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)| |=>| |unit|↵|#fun| |toStr|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)| |=>| |string|↵|#fun| |boo|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)| |=>| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)| |=>| |anything|
-//│ Parsed: {fun buildName: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName2: [] -> string -> ((string,) | (undefined,)) -> string; fun buildName3: [] -> string -> MutArray[string] -> string; fun buildName4: [] -> string -> MutArray[anything] -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> number -> ((number -> number,) | (undefined,)) -> number; fun getOrElse: [] -> ((MutArray[object],) | (undefined,)) -> object; class ABC() {}; fun testABC: [] -> ((ABC,) | (undefined,)) -> unit; fun testSquareConfig: [] -> ((SquareConfig,) | (undefined,)) -> unit; fun err: [] -> (((number, string,),) | (undefined,)) -> unit; fun toStr: [] -> (((number,) | (bool,),) | (undefined,)) -> string; fun boo: [] -> (((T,) & (U,),) | (undefined,)) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> ((B[nothing],) | (undefined,)) -> anything}
+fun boom(_: (B<nothing>) | (undefined)): anything
+//│ |#fun| |buildName|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|_|#:| |string|,| |_|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|_|#:| |string|,| |_|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|(|_|#:| |number|,| |_|#:| |(|number| |=>| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|_|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|_|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|_|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|_|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|_|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|_|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|_|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
+//│ Parsed: {fun buildName: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName2: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName3: [] -> (_: string, _: MutArray[string],) -> string; fun buildName4: [] -> (_: string, _: MutArray[anything],) -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> (_: number, _: (number -> number,) | (undefined,),) -> number; fun getOrElse: [] -> (_: (MutArray[object],) | (undefined,),) -> object; class ABC() {}; fun testABC: [] -> (_: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (_: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> (_: ((number, string,),) | (undefined,),) -> unit; fun toStr: [] -> (_: ((number,) | (bool,),) | (undefined,),) -> string; fun boo: [] -> (_: ((T,) & (U,),) | (undefined,),) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> (_: (B[nothing],) | (undefined,),) -> anything}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 06cfb5e58a..67ab4f93bc 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,20 +1,20 @@
 :NewParser
 :ParseOnly
-fun key: (string, bool, ) => string
-fun value: (string, bool, ) => bool
-fun third: (number, number, number, ) => number
-fun vec2: number => number => (number, number, )
-fun twoFunctions: (number => number, number => number, ) => number => number
-fun tupleIt: string => (unit => string, )
-fun s: bool => ((string) | (number), (number) | (bool), )
-fun s2: (bool, (string) | (number), ) => (string) | (number)
-fun ex: T => U => (T, U, (T) & (U), )
-fun foo: ((T) & (U), ) => unit
-fun conv: (y: number,) => ((y: number,), (z: string,), )
+fun key(_: (string, bool, )): string
+fun value(_: (string, bool, )): bool
+fun third(_: (number, number, number, )): number
+fun vec2(_: number, _: number): (number, number, )
+fun twoFunctions(_: (number => number, number => number, ), _: number): number
+fun tupleIt(_: string): (unit => string, )
+fun s(_: bool): ((string) | (number), (number) | (bool), )
+fun s2(_: (bool, (string) | (number), )): (string) | (number)
+fun ex<T, U>(_: T, _: U): (T, U, (T) & (U), )
+fun foo<T, U>(_: ((T) & (U), )): unit
+fun conv(_: (y: number,)): ((y: number,), (z: string,), )
 class A() {
   let x: number
 }
 class B() {}
-fun swap: (A, B, ) => (B, A, )
-//│ |#fun| |key|#:| |(|string|,| |bool|,| |)| |=>| |string|↵|#fun| |value|#:| |(|string|,| |bool|,| |)| |=>| |bool|↵|#fun| |third|#:| |(|number|,| |number|,| |number|,| |)| |=>| |number|↵|#fun| |vec2|#:| |number| |=>| |number| |=>| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)| |=>| |number| |=>| |number|↵|#fun| |tupleIt|#:| |string| |=>| |(|unit| |=>| |string|,| |)|↵|#fun| |s|#:| |bool| |=>| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)| |=>| |(|string|)| ||| |(|number|)|↵|#fun| |ex|#:| |T| |=>| |U| |=>| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|#:| |(|(|T|)| |&| |(|U|)|,| |)| |=>| |unit|↵|#fun| |conv|#:| |(|y|#:| |number|,|)| |=>| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|#:| |(|A|,| |B|,| |)| |=>| |(|B|,| |A|,| |)|
-//│ Parsed: {fun key: [] -> (string, bool,) -> string; fun value: [] -> (string, bool,) -> bool; fun third: [] -> (number, number, number,) -> number; fun vec2: [] -> number -> number -> (number, number,); fun twoFunctions: [] -> (number -> number, number -> number,) -> number -> number; fun tupleIt: [] -> string -> (unit -> string,); fun s: [] -> bool -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (bool, (string,) | (number,),) -> ((string,) | (number,)); fun ex: [] -> T -> U -> (T, U, (T,) & (U,),); fun foo: [] -> ((T,) & (U,)) -> unit; fun conv: [] -> (y: number,) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (A, B,) -> (B, A,)}
+fun swap(_: (A, B, )): (B, A, )
+//│ |#fun| |key|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |string|↵|#fun| |value|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |bool|↵|#fun| |third|(|_|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|_|#:| |number|,| |_|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|_|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)|,| |_|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|_|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|_|#:| |bool|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|(|_|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|_|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|_|#:| |(|y|#:| |number|,|)|)|#:| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|_|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
+//│ Parsed: {fun key: [] -> (_: (string, bool,),) -> string; fun value: [] -> (_: (string, bool,),) -> bool; fun third: [] -> (_: (number, number, number,),) -> number; fun vec2: [] -> (_: number, _: number,) -> (number, number,); fun twoFunctions: [] -> (_: (number -> number, number -> number,), _: number,) -> number; fun tupleIt: [] -> (_: string,) -> (unit -> string,); fun s: [] -> (_: bool,) -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (_: (bool, (string,) | (number,),),) -> ((string,) | (number,)); fun ex: [] -> (_: T, _: U,) -> (T, U, (T,) & (U,),); fun foo: [] -> (_: ((T,) & (U,),),) -> unit; fun conv: [] -> (_: (y: number,),) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (_: (A, B,),) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index b67e9db3b4..17294c418f 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,17 +1,17 @@
 :NewParser
 :ParseOnly
-fun inc: T => number
+fun inc<T>(_: T): number
 class CC<T>() {
   fun print: T => unit
 }
-fun con: T => U
+fun con<U, T>(_: T): U
 class Printer<T>() {
   fun print: T => unit
 }
-fun setStringPrinter: Printer<string> => unit
-fun getStringPrinter: unit => Printer<string>
-fun foo: Printer<T> => T => T
-fun foo2: Printer<T> => T => T
+fun setStringPrinter(_: Printer<string>): unit
+fun getStringPrinter(): Printer<string>
+fun foo<T>(_: Printer<T>, _: T): T
+fun foo2<T>(_: Printer<T>, _: T): T
 class F<T>() {
   let x: T
   fun GG: U => T
@@ -23,7 +23,7 @@ trait I<T>() {
 class FFF<T>() {
   fun fff: T => unit
 }
-fun fff: FFF<string> => string => unit
-fun getFFF: unit => FFF<number>
-//│ |#fun| |inc|#:| |T| |=>| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|#:| |T| |=>| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|#:| |Printer|‹|string|›| |=>| |unit|↵|#fun| |getStringPrinter|#:| |unit| |=>| |Printer|‹|string|›|↵|#fun| |foo|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#fun| |foo2|#:| |Printer|‹|T|›| |=>| |T| |=>| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|#:| |FFF|‹|string|›| |=>| |string| |=>| |unit|↵|#fun| |getFFF|#:| |unit| |=>| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> T -> number; class CC[T]() {fun print: [] -> T -> unit}; fun con: [] -> T -> U; class Printer[T]() {fun print: [] -> T -> unit}; fun setStringPrinter: [] -> Printer[string] -> unit; fun getStringPrinter: [] -> unit -> Printer[string]; fun foo: [] -> Printer[T] -> T -> T; fun foo2: [] -> Printer[T] -> T -> T; class F[T]() {let x: [] -> T; fun GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> U -> T}; class FFF[T]() {fun fff: [] -> T -> unit}; fun fff: [] -> FFF[string] -> string -> unit; fun getFFF: [] -> unit -> FFF[number]}
+fun fff(_: FFF<string>, _: string): unit
+fun getFFF(): FFF<number>
+//│ |#fun| |inc|‹|T|›|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|_|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|(|_|#:| |FFF|‹|string|›|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> (_: T,) -> number; class CC[T]() {fun print: [] -> T -> unit}; fun con: [] -> (_: T,) -> U; class Printer[T]() {fun print: [] -> T -> unit}; fun setStringPrinter: [] -> (_: Printer[string],) -> unit; fun getStringPrinter: [] -> () -> Printer[string]; fun foo: [] -> (_: Printer[T], _: T,) -> T; fun foo2: [] -> (_: Printer[T], _: T,) -> T; class F[T]() {let x: [] -> T; fun GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> U -> T}; class FFF[T]() {fun fff: [] -> T -> unit}; fun fff: [] -> (_: FFF[string], _: string,) -> unit; fun getFFF: [] -> () -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index ff94527d83..c798c7163e 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,11 +1,11 @@
 :NewParser
 :ParseOnly
-fun getString: ((string) | (number)) | (bool) => string
-fun test: bool => (string) | (number)
-fun run: (number => number) | (number => string) => anything
-fun get: (MutArray<number>) | (MutArray<string>) => unit
-fun get2: ((string, string, )) | ((number, string, )) => string
-fun typeVar: (T) | (U) => (T) | (U)
-fun uuuu: ((string) | (number)) | (bool) => ((string) | (number)) | (bool)
-//│ |#fun| |getString|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |string|↵|#fun| |test|#:| |bool| |=>| |(|string|)| ||| |(|number|)|↵|#fun| |run|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)| |=>| |anything|↵|#fun| |get|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)| |=>| |unit|↵|#fun| |get2|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)| |=>| |string|↵|#fun| |typeVar|#:| |(|T|)| ||| |(|U|)| |=>| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)| |=>| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ Parsed: {fun getString: [] -> (((string,) | (number,),) | (bool,)) -> string; fun test: [] -> bool -> ((string,) | (number,)); fun run: [] -> ((number -> number,) | (number -> string,)) -> anything; fun get: [] -> ((MutArray[number],) | (MutArray[string],)) -> unit; fun get2: [] -> (((string, string,),) | ((number, string,),)) -> string; fun typeVar: [] -> ((T,) | (U,)) -> ((T,) | (U,)); fun uuuu: [] -> (((string,) | (number,),) | (bool,)) -> (((string,) | (number,),) | (bool,))}
+fun getString(_: ((string) | (number)) | (bool)): string
+fun test(_: bool): (string) | (number)
+fun run(_: (number => number) | (number => string)): anything
+fun get(_: (MutArray<number>) | (MutArray<string>)): unit
+fun get2(_: ((string, string, )) | ((number, string, ))): string
+fun typeVar<T, U>(_: (T) | (U)): (T) | (U)
+fun uuuu(_: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
+//│ |#fun| |getString|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|_|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|_|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|_|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|_|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|_|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
+//│ Parsed: {fun getString: [] -> (_: ((string,) | (number,),) | (bool,),) -> string; fun test: [] -> (_: bool,) -> ((string,) | (number,)); fun run: [] -> (_: (number -> number,) | (number -> string,),) -> anything; fun get: [] -> (_: (MutArray[number],) | (MutArray[string],),) -> unit; fun get2: [] -> (_: ((string, string,),) | ((number, string,),),) -> string; fun typeVar: [] -> (_: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (_: ((string,) | (number,),) | (bool,),) -> (((string,) | (number,),) | (bool,))}

From 3b1401e0825fe0e06c1c11d82ef0223560b13e47 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Fri, 16 Sep 2022 10:14:30 +0800
Subject: [PATCH 25/40] Fix record func

---
 .../main/scala/ts2mls/types/Converter.scala   |  2 +-
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 18 ++++++-------
 ts2mls/js/src/test/diff/Heritage.d.mls        | 16 ++++++------
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 26 +++++++++----------
 ts2mls/js/src/test/diff/Namespace.d.mls       | 12 ++++-----
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 14 +++++-----
 6 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 2302f882fb..368842271a 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -66,7 +66,7 @@ object Converter {
       case Public =>
         if (typeName === "trait ") s"${m._1}: ${convert(m._2)},"
         else m._2.base match {
-          case _: TSFunctionType => s"${indent}  fun ${m._1}: ${convert(m._2)}\n"
+          case _: TSFunctionType => s"${generateFunDeclaration(m._2.base, m._1)(indent + "  ")}\n"
           case _: TSIgnoredOverload => s"${indent}  fun ${m._1}: ${convert(m._2)}\n"
           case _ => s"${indent}  let ${m._1}: ${convert(m._2)}\n"
         }
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index 302e622f68..6254134156 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -2,15 +2,15 @@
 :ParseOnly
 class Student(_: string, _: number) {
   let name: string
-  fun isFriend: Student => bool
-  fun addScore: string => number => unit
-  fun getID: unit => number
+  fun isFriend(_: Student): bool
+  fun addScore(_: string, _: number): unit
+  fun getID(): number
 }
 class Foo<T>() {
-  fun bar: T => unit
+  fun bar(_: T): unit
 }
 class EZ() {
-  fun inc: number => number
+  fun inc(_: number): number
 }
 class Outer() {
   class Inner() {
@@ -18,8 +18,8 @@ class Outer() {
   }
 }
 class TTT<T>() {
-  fun ttt: T => T
-  fun ttt2: T => T
+  fun ttt(_: T): T
+  fun ttt2(_: T): T
 }
-//│ |#class| |Student|(|_|#:| |string|,| |_|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|#:| |Student| |=>| |bool|↵|#fun| |addScore|#:| |string| |=>| |number| |=>| |unit|↵|#fun| |getID|#:| |unit| |=>| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|#:| |T| |=>| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|#:| |number| |=>| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|#:| |T| |=>| |T|↵|#fun| |ttt2|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {class Student(_: string, _: number,) {let name: [] -> string; fun isFriend: [] -> Student -> bool; fun addScore: [] -> string -> number -> unit; fun getID: [] -> unit -> number}; class Foo[T]() {fun bar: [] -> T -> unit}; class EZ() {fun inc: [] -> number -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> T -> T; fun ttt2: [] -> T -> T}}
+//│ |#class| |Student|(|_|#:| |string|,| |_|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|_|#:| |Student|)|#:| |bool|↵|#fun| |addScore|(|_|#:| |string|,| |_|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|_|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|_|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|_|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {class Student(_: string, _: number,) {let name: [] -> string; fun isFriend: [] -> (_: Student,) -> bool; fun addScore: [] -> (_: string, _: number,) -> unit; fun getID: [] -> () -> number}; class Foo[T]() {fun bar: [] -> (_: T,) -> unit}; class EZ() {fun inc: [] -> (_: number,) -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> (_: T,) -> T; fun ttt2: [] -> (_: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index d85f181432..c753f4982e 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -1,12 +1,12 @@
 :NewParser
 :ParseOnly
 class A() {
-  fun foo: unit => unit
+  fun foo(): unit
 }
 class B(): A {}
 class C<T>() {
-  fun set: T => unit
-  fun get: unit => T
+  fun set(_: T): unit
+  fun get(): T
 }
 class D(): C<number> {}
 trait Wu() {
@@ -19,7 +19,7 @@ trait WuWuWu(): WuWu {
   let z: bool
 }
 trait Never(): WuWuWu {
-  fun w: unit => nothing
+  fun w(): nothing
 }
 class VG<T>() {
   let x: T
@@ -28,10 +28,10 @@ class Home<T>(): VG<string> {
   let y: T
 }
 trait O<I>() {
-  fun xx: I => I
+  fun xx(_: I): I
 }
 class OR<R>(): O<R> {
-  fun xx: R => R
+  fun xx(_: R): R
 }
 namespace Five {
   class ROTK() {
@@ -40,5 +40,5 @@ namespace Five {
   class Y(): Five'ROTK {}
 }
 class Y(): Five'ROTK {}
-//│ |#class| |A|(||)| |{|→|#fun| |foo|#:| |unit| |=>| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|#:| |T| |=>| |unit|↵|#fun| |get|#:| |unit| |=>| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|#:| |unit| |=>| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|#:| |I| |=>| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|#:| |R| |=>| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
-//│ Parsed: {class A() {fun foo: [] -> unit -> unit}; class B(): A {}; class C[T]() {fun set: [] -> T -> unit; fun get: [] -> unit -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> unit -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> I -> I}; class OR[R](): O‹R› {fun xx: [] -> R -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|_|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|_|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|_|#:| |R|)|#:| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
+//│ Parsed: {class A() {fun foo: [] -> () -> unit}; class B(): A {}; class C[T]() {fun set: [] -> (_: T,) -> unit; fun get: [] -> () -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> () -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> (_: I,) -> I}; class OR[R](): O‹R› {fun xx: [] -> (_: R,) -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 3687aa8955..e8aa36144c 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -2,39 +2,39 @@
 :ParseOnly
 trait IFoo() {
   let a: string
-  fun b: number => number
-  fun c: unit => bool
-  fun d: string => unit
+  fun b(_: number): number
+  fun c(): bool
+  fun d(_: string): unit
 }
 trait II<T>() {
-  fun test: T => number
+  fun test(_: T): number
 }
 fun create(): (v: number,)
 fun get(_: (t: string,)): string
 trait IEvent() {
-  fun callback: unit => number => unit
+  fun callback(_: unit): number => unit
 }
 trait SearchFunc() {
-  fun __call: string => string => bool
+  fun __call(_: string, _: string): bool
 }
 trait StringArray() {
-  fun __index: number => string
+  fun __index(_: number): string
 }
 trait Counter() {
-  fun __call: number => string
+  fun __call(_: number): string
   let interval: number
-  fun reset: unit => unit
+  fun reset(): unit
 }
 trait Simple() {
   let a: number
-  fun b: bool => string
+  fun b(_: bool): string
 }
 trait Simple2<T>() {
   let abc: T
 }
 trait Next(): Simple {}
 trait TTT<T>() {
-  fun ttt: T => T
+  fun ttt(_: T): T
 }
-//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|#:| |number| |=>| |number|↵|#fun| |c|#:| |unit| |=>| |bool|↵|#fun| |d|#:| |string| |=>| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|#:| |T| |=>| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|_|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|#:| |unit| |=>| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|#:| |string| |=>| |string| |=>| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|#:| |number| |=>| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|#:| |number| |=>| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|#:| |bool| |=>| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|#:| |T| |=>| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> number -> number; fun c: [] -> unit -> bool; fun d: [] -> string -> unit}; trait II[T](): {fun test: [] -> T -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (_: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> unit -> number -> unit}; trait SearchFunc(): {fun __call: [] -> string -> string -> bool}; trait StringArray(): {fun __index: [] -> number -> string}; trait Counter(): {fun __call: [] -> number -> string; let interval: [] -> number; fun reset: [] -> unit -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> bool -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> T -> T}}
+//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|_|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |bool|↵|#fun| |d|(|_|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|_|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|_|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(|_|#:| |unit|)|#:| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|_|#:| |string|,| |_|#:| |string|)|#:| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|_|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|_|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|_|#:| |bool|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|_|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (_: number,) -> number; fun c: [] -> () -> bool; fun d: [] -> (_: string,) -> unit}; trait II[T](): {fun test: [] -> (_: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (_: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> (_: unit,) -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (_: string, _: string,) -> bool}; trait StringArray(): {fun __index: [] -> (_: number,) -> string}; trait Counter(): {fun __call: [] -> (_: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (_: bool,) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (_: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index b804b89df7..07c9588e34 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -4,10 +4,10 @@ namespace N1 {
   fun f(_: anything): number
   fun ff(_: anything): number
   class C() {
-    fun f: unit => unit
+    fun f(): unit
   }
   trait I() {
-    fun f: unit => number
+    fun f(): number
   }
   namespace N2 {
     fun fff(_: bool): number
@@ -18,15 +18,15 @@ namespace N1 {
 namespace AA {
   fun f(_: anything): string
   class C() {
-    fun f: unit => unit
+    fun f(): unit
   }
   trait I() {
-    fun f: unit => number
+    fun f(): number
   }
   namespace N2 {
   }
 }
 fun f1(_: N1'C): N1'C
 fun f2(_: AA'C): AA'C
-//│ |#namespace| |N1| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |number|↵|#fun| |ff|(|_|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|_|#:| |bool|)|#:| |number|↵|#fun| |gg|(|_|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|#:| |unit| |=>| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|#:| |unit| |=>| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|_|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|_|#:| |AA'C|)|#:| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> (_: anything,) -> number; fun ff: [] -> (_: anything,) -> number; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {fun fff: [] -> (_: bool,) -> number; fun gg: [] -> (_: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (_: anything,) -> string; class C() {fun f: [] -> unit -> unit}; trait I(): {fun f: [] -> unit -> number}; namespace N2(): {}}; fun f1: [] -> (_: N1'C,) -> N1'C; fun f2: [] -> (_: AA'C,) -> AA'C}
+//│ |#namespace| |N1| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |number|↵|#fun| |ff|(|_|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|_|#:| |bool|)|#:| |number|↵|#fun| |gg|(|_|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|_|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|_|#:| |AA'C|)|#:| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> (_: anything,) -> number; fun ff: [] -> (_: anything,) -> number; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {fun fff: [] -> (_: bool,) -> number; fun gg: [] -> (_: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (_: anything,) -> string; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {}}; fun f1: [] -> (_: N1'C,) -> N1'C; fun f2: [] -> (_: AA'C,) -> AA'C}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index 17294c418f..e41d58fc8a 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -2,11 +2,11 @@
 :ParseOnly
 fun inc<T>(_: T): number
 class CC<T>() {
-  fun print: T => unit
+  fun print(_: T): unit
 }
 fun con<U, T>(_: T): U
 class Printer<T>() {
-  fun print: T => unit
+  fun print(_: T): unit
 }
 fun setStringPrinter(_: Printer<string>): unit
 fun getStringPrinter(): Printer<string>
@@ -14,16 +14,16 @@ fun foo<T>(_: Printer<T>, _: T): T
 fun foo2<T>(_: Printer<T>, _: T): T
 class F<T>() {
   let x: T
-  fun GG: U => T
+  fun GG<U>(_: U): T
 }
 trait I<T>() {
   let x: T
-  fun GG: U => T
+  fun GG<U>(_: U): T
 }
 class FFF<T>() {
-  fun fff: T => unit
+  fun fff(_: T): unit
 }
 fun fff(_: FFF<string>, _: string): unit
 fun getFFF(): FFF<number>
-//│ |#fun| |inc|‹|T|›|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|_|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|#:| |U| |=>| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|#:| |T| |=>| |unit|←|↵|}|↵|#fun| |fff|(|_|#:| |FFF|‹|string|›|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> (_: T,) -> number; class CC[T]() {fun print: [] -> T -> unit}; fun con: [] -> (_: T,) -> U; class Printer[T]() {fun print: [] -> T -> unit}; fun setStringPrinter: [] -> (_: Printer[string],) -> unit; fun getStringPrinter: [] -> () -> Printer[string]; fun foo: [] -> (_: Printer[T], _: T,) -> T; fun foo2: [] -> (_: Printer[T], _: T,) -> T; class F[T]() {let x: [] -> T; fun GG: [] -> U -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> U -> T}; class FFF[T]() {fun fff: [] -> T -> unit}; fun fff: [] -> (_: FFF[string], _: string,) -> unit; fun getFFF: [] -> () -> FFF[number]}
+//│ |#fun| |inc|‹|T|›|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|_|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|_|#:| |U|)|#:| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|_|#:| |U|)|#:| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |fff|(|_|#:| |FFF|‹|string|›|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> (_: T,) -> number; class CC[T]() {fun print: [] -> (_: T,) -> unit}; fun con: [] -> (_: T,) -> U; class Printer[T]() {fun print: [] -> (_: T,) -> unit}; fun setStringPrinter: [] -> (_: Printer[string],) -> unit; fun getStringPrinter: [] -> () -> Printer[string]; fun foo: [] -> (_: Printer[T], _: T,) -> T; fun foo2: [] -> (_: Printer[T], _: T,) -> T; class F[T]() {let x: [] -> T; fun GG: [] -> (_: U,) -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> (_: U,) -> T}; class FFF[T]() {fun fff: [] -> (_: T,) -> unit}; fun fff: [] -> (_: FFF[string], _: string,) -> unit; fun getFFF: [] -> () -> FFF[number]}

From 0ac1384ed6cc0fb3903ee2ac91be2d3dd0876e8b Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Mon, 19 Sep 2022 15:04:15 +0800
Subject: [PATCH 26/40] Name parameters

---
 .../main/scala/ts2mls/types/Converter.scala   |  5 ++--
 ts2mls/js/src/test/diff/Array.d.mls           | 26 ++++++++---------
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  | 26 ++++++++---------
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 18 ++++++------
 ts2mls/js/src/test/diff/Enum.d.mls            |  8 +++---
 ts2mls/js/src/test/diff/Heritage.d.mls        | 10 +++----
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   | 10 +++----
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 24 ++++++++--------
 ts2mls/js/src/test/diff/Intersection.d.mls    | 22 +++++++--------
 ts2mls/js/src/test/diff/MultiFiles.d.mls      |  8 +++---
 ts2mls/js/src/test/diff/Namespace.d.mls       | 18 ++++++------
 ts2mls/js/src/test/diff/Optional.d.mls        | 28 +++++++++----------
 ts2mls/js/src/test/diff/Tuple.d.mls           | 28 +++++++++----------
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 26 ++++++++---------
 ts2mls/js/src/test/diff/Union.d.mls           | 18 ++++++------
 15 files changed, 138 insertions(+), 137 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 368842271a..1787790ef0 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -1,6 +1,7 @@
 package ts2mls.types
 
 import mlscript.utils._
+import scala.runtime.Statics
 
 object Converter {
   private val primitiveName = Map[String, String](
@@ -20,7 +21,7 @@ object Converter {
 
   def generateFunDeclaration(tsType: TSType, name: String)(implicit indent: String = ""): String = tsType match {
     case TSFunctionType(params, res, typeVars) => {
-      val pList = if (params.isEmpty) "" else params.map(p => "_: " + convert(p)("")).reduceLeft((r, p) => s"$r, $p")
+      val pList = if (params.isEmpty) "" else params.zipWithIndex.map(p => s"v${p._2}: ${convert(p._1)("")}").reduceLeft((r, p) => s"$r, $p")
       val tpList = if (typeVars.isEmpty) "" else s"<${typeVars.map(p => convert(p)("")).reduceLeft((r, p) => s"$r, $p")}>"
       s"${indent}fun $name$tpList($pList): ${convert(res)("")}"
     }
@@ -107,7 +108,7 @@ object Converter {
     else { // named interfaces and classes
       val constructor =
         if (constructorList.isEmpty) "()"
-        else s"(${constructorList.map(p => "_: " + convert(p)).reduceLeft((res, p) => s"$res, $p")})"
+        else s"(${constructorList.zipWithIndex.map(p => s"v${p._2}: ${convert(p._1)("")}").reduceLeft((res, p) => s"$res, $p")})"
 
       val inheritance =
         if (parents.isEmpty) constructor
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 1f2ca1f3fa..4eb1a9788d 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,23 +1,23 @@
 :NewParser
 :ParseOnly
-fun first(_: MutArray<string>): string
+fun first(v0: MutArray<string>): string
 fun getZero3(): MutArray<number>
-fun first2(_: MutArray<number => number>): number => number
-fun doEs(_: MutArray<int>): MutArray<int>
+fun first2(v0: MutArray<number => number>): number => number
+fun doEs(v0: MutArray<int>): MutArray<int>
 class C() {}
 trait I() {
   let i: number
 }
-fun doCs(_: MutArray<C>): MutArray<C>
-fun doIs(_: MutArray<I>): MutArray<I>
-fun inter<U, T>(_: MutArray<(U) & (T)>): MutArray<(U) & (T)>
-fun clean(_: MutArray<(string, number, )>): MutArray<(string, number, )>
-fun translate<T, U>(_: MutArray<T>): MutArray<U>
-fun uu(_: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
+fun doCs(v0: MutArray<C>): MutArray<C>
+fun doIs(v0: MutArray<I>): MutArray<I>
+fun inter<U, T>(v0: MutArray<(U) & (T)>): MutArray<(U) & (T)>
+fun clean(v0: MutArray<(string, number, )>): MutArray<(string, number, )>
+fun translate<T, U>(v0: MutArray<T>): MutArray<U>
+fun uu(v0: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
 class Temp<T>() {
   let x: T
 }
-fun ta(_: MutArray<Temp<bool>>): MutArray<Temp<bool>>
-fun tat<T>(_: MutArray<Temp<T>>): MutArray<Temp<T>>
-//│ |#fun| |first|(|_|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|_|#:| |MutArray|‹|number| |=>| |number|›|)|#:| |number| |=>| |number|↵|#fun| |doEs|(|_|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|_|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|_|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|_|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|_|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|_|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|_|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|)|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|_|#:| |MutArray|‹|Temp|‹|bool|›|›|)|#:| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|‹|T|›|(|_|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|
-//│ Parsed: {fun first: [] -> (_: MutArray[string],) -> string; fun getZero3: [] -> () -> MutArray[number]; fun first2: [] -> (_: MutArray[number -> number],) -> number -> number; fun doEs: [] -> (_: MutArray[int],) -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> (_: MutArray[C],) -> MutArray[C]; fun doIs: [] -> (_: MutArray[I],) -> MutArray[I]; fun inter: [] -> (_: MutArray[(U,) & (T,)],) -> MutArray[(U,) & (T,)]; fun clean: [] -> (_: MutArray[(string, number,)],) -> MutArray[(string, number,)]; fun translate: [] -> (_: MutArray[T],) -> MutArray[U]; fun uu: [] -> (_: MutArray[(number,) | (bool,)],) -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> (_: MutArray[Temp[bool]],) -> MutArray[Temp[bool]]; fun tat: [] -> (_: MutArray[Temp[T]],) -> MutArray[Temp[T]]}
+fun ta(v0: MutArray<Temp<bool>>): MutArray<Temp<bool>>
+fun tat<T>(v0: MutArray<Temp<T>>): MutArray<Temp<T>>
+//│ |#fun| |first|(|v0|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|v0|#:| |MutArray|‹|number| |=>| |number|›|)|#:| |number| |=>| |number|↵|#fun| |doEs|(|v0|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|v0|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|v0|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|v0|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|v0|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|v0|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|v0|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|)|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|v0|#:| |MutArray|‹|Temp|‹|bool|›|›|)|#:| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|‹|T|›|(|v0|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|
+//│ Parsed: {fun first: [] -> (v0: MutArray[string],) -> string; fun getZero3: [] -> () -> MutArray[number]; fun first2: [] -> (v0: MutArray[number -> number],) -> number -> number; fun doEs: [] -> (v0: MutArray[int],) -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> (v0: MutArray[C],) -> MutArray[C]; fun doIs: [] -> (v0: MutArray[I],) -> MutArray[I]; fun inter: [] -> (v0: MutArray[(U,) & (T,)],) -> MutArray[(U,) & (T,)]; fun clean: [] -> (v0: MutArray[(string, number,)],) -> MutArray[(string, number,)]; fun translate: [] -> (v0: MutArray[T],) -> MutArray[U]; fun uu: [] -> (v0: MutArray[(number,) | (bool,)],) -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> (v0: MutArray[Temp[bool]],) -> MutArray[Temp[bool]]; fun tat: [] -> (v0: MutArray[Temp[T]],) -> MutArray[Temp[T]]}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 66f25c245a..f741b86bc4 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,28 +1,28 @@
 :NewParser
 :ParseOnly
 fun hello(): unit
-fun add(_: number, _: number): number
-fun sub(_: number, _: number): number
+fun add(v0: number, v1: number): number
+fun sub(v0: number, v1: number): number
 fun foo(): number
-fun id(_: anything): anything
-fun odd(_: number): bool
-fun isnull(_: anything): bool
+fun id(v0: anything): anything
+fun odd(v0: number): bool
+fun isnull(v0: anything): bool
 fun bar(): anything
-fun nu(_: null): null
-fun un(_: undefined): undefined
+fun nu(v0: null): null
+fun un(v0: undefined): undefined
 fun fail(): nothing
 fun create(): object
-fun pa(_: number): number
-fun wtf(_: anything): unit
+fun pa(v0: number): number
+fun wtf(v0: anything): unit
 class Foooooo() {
   let ooooooo: number
 }
-fun inn(_: Foooooo): unit
+fun inn(v0: Foooooo): unit
 fun out(): Foooooo
 trait Barrrrrrrrr() {
   let rrrrrrr: number
 }
-fun inn2(_: Barrrrrrrrr): unit
+fun inn2(v0: Barrrrrrrrr): unit
 fun out2(): Barrrrrrrrr
-//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |sub|(|_|#:| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|_|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|_|#:| |number|)|#:| |bool|↵|#fun| |isnull|(|_|#:| |anything|)|#:| |bool|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|_|#:| |null|)|#:| |null|↵|#fun| |un|(|_|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|_|#:| |number|)|#:| |number|↵|#fun| |wtf|(|_|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|_|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|_|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (_: number, _: number,) -> number; fun sub: [] -> (_: number, _: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (_: anything,) -> anything; fun odd: [] -> (_: number,) -> bool; fun isnull: [] -> (_: anything,) -> bool; fun bar: [] -> () -> anything; fun nu: [] -> (_: null,) -> null; fun un: [] -> (_: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (_: number,) -> number; fun wtf: [] -> (_: anything,) -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> (_: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> (_: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
+//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |sub|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|v0|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|v0|#:| |number|)|#:| |bool|↵|#fun| |isnull|(|v0|#:| |anything|)|#:| |bool|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|v0|#:| |null|)|#:| |null|↵|#fun| |un|(|v0|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|v0|#:| |number|)|#:| |number|↵|#fun| |wtf|(|v0|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|v0|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|v0|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (v0: number, v1: number,) -> number; fun sub: [] -> (v0: number, v1: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (v0: anything,) -> anything; fun odd: [] -> (v0: number,) -> bool; fun isnull: [] -> (v0: anything,) -> bool; fun bar: [] -> () -> anything; fun nu: [] -> (v0: null,) -> null; fun un: [] -> (v0: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (v0: number,) -> number; fun wtf: [] -> (v0: anything,) -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> (v0: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> (v0: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index 6254134156..fa731d36e1 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,16 +1,16 @@
 :NewParser
 :ParseOnly
-class Student(_: string, _: number) {
+class Student(v0: string, v1: number) {
   let name: string
-  fun isFriend(_: Student): bool
-  fun addScore(_: string, _: number): unit
+  fun isFriend(v0: Student): bool
+  fun addScore(v0: string, v1: number): unit
   fun getID(): number
 }
 class Foo<T>() {
-  fun bar(_: T): unit
+  fun bar(v0: T): unit
 }
 class EZ() {
-  fun inc(_: number): number
+  fun inc(v0: number): number
 }
 class Outer() {
   class Inner() {
@@ -18,8 +18,8 @@ class Outer() {
   }
 }
 class TTT<T>() {
-  fun ttt(_: T): T
-  fun ttt2(_: T): T
+  fun ttt(v0: T): T
+  fun ttt2(v0: T): T
 }
-//│ |#class| |Student|(|_|#:| |string|,| |_|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|_|#:| |Student|)|#:| |bool|↵|#fun| |addScore|(|_|#:| |string|,| |_|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|_|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|_|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|_|#:| |T|)|#:| |T|←|↵|}|
-//│ Parsed: {class Student(_: string, _: number,) {let name: [] -> string; fun isFriend: [] -> (_: Student,) -> bool; fun addScore: [] -> (_: string, _: number,) -> unit; fun getID: [] -> () -> number}; class Foo[T]() {fun bar: [] -> (_: T,) -> unit}; class EZ() {fun inc: [] -> (_: number,) -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> (_: T,) -> T; fun ttt2: [] -> (_: T,) -> T}}
+//│ |#class| |Student|(|v0|#:| |string|,| |v1|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|v0|#:| |Student|)|#:| |bool|↵|#fun| |addScore|(|v0|#:| |string|,| |v1|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|v0|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|v0|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {class Student(v0: string, v1: number,) {let name: [] -> string; fun isFriend: [] -> (v0: Student,) -> bool; fun addScore: [] -> (v0: string, v1: number,) -> unit; fun getID: [] -> () -> number}; class Foo[T]() {fun bar: [] -> (v0: T,) -> unit}; class EZ() {fun inc: [] -> (v0: number,) -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> (v0: T,) -> T; fun ttt2: [] -> (v0: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index 57dcd7a5d2..8b284c0f73 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun pass(_: int): bool
+fun pass(v0: int): bool
 fun stop(): int
-fun g(_: int): int
-//│ |#fun| |pass|(|_|#:| |int|)|#:| |bool|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|_|#:| |int|)|#:| |int|
-//│ Parsed: {fun pass: [] -> (_: int,) -> bool; fun stop: [] -> () -> int; fun g: [] -> (_: int,) -> int}
+fun g(v0: int): int
+//│ |#fun| |pass|(|v0|#:| |int|)|#:| |bool|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|v0|#:| |int|)|#:| |int|
+//│ Parsed: {fun pass: [] -> (v0: int,) -> bool; fun stop: [] -> () -> int; fun g: [] -> (v0: int,) -> int}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index c753f4982e..2f1413d896 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -5,7 +5,7 @@ class A() {
 }
 class B(): A {}
 class C<T>() {
-  fun set(_: T): unit
+  fun set(v0: T): unit
   fun get(): T
 }
 class D(): C<number> {}
@@ -28,10 +28,10 @@ class Home<T>(): VG<string> {
   let y: T
 }
 trait O<I>() {
-  fun xx(_: I): I
+  fun xx(v0: I): I
 }
 class OR<R>(): O<R> {
-  fun xx(_: R): R
+  fun xx(v0: R): R
 }
 namespace Five {
   class ROTK() {
@@ -40,5 +40,5 @@ namespace Five {
   class Y(): Five'ROTK {}
 }
 class Y(): Five'ROTK {}
-//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|_|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|_|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|_|#:| |R|)|#:| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
-//│ Parsed: {class A() {fun foo: [] -> () -> unit}; class B(): A {}; class C[T]() {fun set: [] -> (_: T,) -> unit; fun get: [] -> () -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> () -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> (_: I,) -> I}; class OR[R](): O‹R› {fun xx: [] -> (_: R,) -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|v0|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|v0|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|v0|#:| |R|)|#:| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
+//│ Parsed: {class A() {fun foo: [] -> () -> unit}; class B(): A {}; class C[T]() {fun set: [] -> (v0: T,) -> unit; fun get: [] -> () -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> () -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> (v0: I,) -> I}; class OR[R](): O‹R› {fun xx: [] -> (v0: R,) -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index 347a47434d..031845828d 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun h1(_: number => number, _: number): number
-fun h2(_: string): unit => string
-fun h3(_: number => number, _: number => number): number => number
-//│ |#fun| |h1|(|_|#:| |number| |=>| |number|,| |_|#:| |number|)|#:| |number|↵|#fun| |h2|(|_|#:| |string|)|#:| |unit| |=>| |string|↵|#fun| |h3|(|_|#:| |number| |=>| |number|,| |_|#:| |number| |=>| |number|)|#:| |number| |=>| |number|
-//│ Parsed: {fun h1: [] -> (_: number -> number, _: number,) -> number; fun h2: [] -> (_: string,) -> unit -> string; fun h3: [] -> (_: number -> number, _: number -> number,) -> number -> number}
+fun h1(v0: number => number, v1: number): number
+fun h2(v0: string): unit => string
+fun h3(v0: number => number, v1: number => number): number => number
+//│ |#fun| |h1|(|v0|#:| |number| |=>| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |h2|(|v0|#:| |string|)|#:| |unit| |=>| |string|↵|#fun| |h3|(|v0|#:| |number| |=>| |number|,| |v1|#:| |number| |=>| |number|)|#:| |number| |=>| |number|
+//│ Parsed: {fun h1: [] -> (v0: number -> number, v1: number,) -> number; fun h2: [] -> (v0: string,) -> unit -> string; fun h3: [] -> (v0: number -> number, v1: number -> number,) -> number -> number}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index e8aa36144c..c945208d5a 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -2,39 +2,39 @@
 :ParseOnly
 trait IFoo() {
   let a: string
-  fun b(_: number): number
+  fun b(v0: number): number
   fun c(): bool
-  fun d(_: string): unit
+  fun d(v0: string): unit
 }
 trait II<T>() {
-  fun test(_: T): number
+  fun test(v0: T): number
 }
 fun create(): (v: number,)
-fun get(_: (t: string,)): string
+fun get(v0: (t: string,)): string
 trait IEvent() {
-  fun callback(_: unit): number => unit
+  fun callback(v0: unit): number => unit
 }
 trait SearchFunc() {
-  fun __call(_: string, _: string): bool
+  fun __call(v0: string, v1: string): bool
 }
 trait StringArray() {
-  fun __index(_: number): string
+  fun __index(v0: number): string
 }
 trait Counter() {
-  fun __call(_: number): string
+  fun __call(v0: number): string
   let interval: number
   fun reset(): unit
 }
 trait Simple() {
   let a: number
-  fun b(_: bool): string
+  fun b(v0: bool): string
 }
 trait Simple2<T>() {
   let abc: T
 }
 trait Next(): Simple {}
 trait TTT<T>() {
-  fun ttt(_: T): T
+  fun ttt(v0: T): T
 }
-//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|_|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |bool|↵|#fun| |d|(|_|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|_|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|_|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(|_|#:| |unit|)|#:| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|_|#:| |string|,| |_|#:| |string|)|#:| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|_|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|_|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|_|#:| |bool|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|_|#:| |T|)|#:| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (_: number,) -> number; fun c: [] -> () -> bool; fun d: [] -> (_: string,) -> unit}; trait II[T](): {fun test: [] -> (_: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (_: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> (_: unit,) -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (_: string, _: string,) -> bool}; trait StringArray(): {fun __index: [] -> (_: number,) -> string}; trait Counter(): {fun __call: [] -> (_: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (_: bool,) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (_: T,) -> T}}
+//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|v0|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |bool|↵|#fun| |d|(|v0|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|v0|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|v0|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(|v0|#:| |unit|)|#:| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|v0|#:| |string|,| |v1|#:| |string|)|#:| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|v0|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|v0|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|v0|#:| |bool|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (v0: number,) -> number; fun c: [] -> () -> bool; fun d: [] -> (v0: string,) -> unit}; trait II[T](): {fun test: [] -> (v0: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (v0: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> (v0: unit,) -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (v0: string, v1: string,) -> bool}; trait StringArray(): {fun __index: [] -> (v0: number,) -> string}; trait Counter(): {fun __call: [] -> (v0: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (v0: bool,) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (v0: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index f8a7f862de..c9f7599e87 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,21 +1,21 @@
 :NewParser
 :ParseOnly
-fun extend<T, U>(_: T, _: U): (T) & (U)
-fun foo<T, U>(_: (T) & (U)): unit
-fun over(_: (number => string) & (object => string)): string
+fun extend<T, U>(v0: T, v1: U): (T) & (U)
+fun foo<T, U>(v0: (T) & (U)): unit
+fun over(v0: (number => string) & (object => string)): string
 trait IA() {
   let x: number
 }
 trait IB() {
   let y: number
 }
-fun iii(_: (IA) & (IB)): (IA) & (IB)
-fun uu<U, V, T, P>(_: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
-fun iiii<U, T, V>(_: ((U) & (T)) & (V)): ((U) & (T)) & (V)
-fun arr<U, T>(_: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
-fun tt<U, T, V>(_: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
+fun iii(v0: (IA) & (IB)): (IA) & (IB)
+fun uu<U, V, T, P>(v0: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
+fun iiii<U, T, V>(v0: ((U) & (T)) & (V)): ((U) & (T)) & (V)
+fun arr<U, T>(v0: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
+fun tt<U, T, V>(v0: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
 class A() {}
 class B() {}
-fun inter(_: (A) & (B)): (A) & (B)
-//│ |#fun| |extend|‹|T|,| |U|›|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|‹|T|,| |U|›|(|_|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|_|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)|)|#:| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|(|_|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|‹|U|,| |V|,| |T|,| |P|›|(|_|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|‹|U|,| |T|,| |V|›|(|_|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|‹|U|,| |T|›|(|_|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|‹|U|,| |T|,| |V|›|(|_|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|(|_|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
-//│ Parsed: {fun extend: [] -> (_: T, _: U,) -> ((T,) & (U,)); fun foo: [] -> (_: (T,) & (U,),) -> unit; fun over: [] -> (_: (number -> string,) & (object -> string,),) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> (_: (IA,) & (IB,),) -> ((IA,) & (IB,)); fun uu: [] -> (_: ((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (_: ((U,) & (T,),) & (V,),) -> (((U,) & (T,),) & (V,)); fun arr: [] -> (_: (MutArray[U],) & (MutArray[T],),) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (_: ((U, T,),) & ((V, V,),),) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> (_: (A,) & (B,),) -> ((A,) & (B,))}
+fun inter(v0: (A) & (B)): (A) & (B)
+//│ |#fun| |extend|‹|T|,| |U|›|(|v0|#:| |T|,| |v1|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|‹|T|,| |U|›|(|v0|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|v0|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)|)|#:| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|(|v0|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|‹|U|,| |V|,| |T|,| |P|›|(|v0|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|‹|U|,| |T|,| |V|›|(|v0|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|‹|U|,| |T|›|(|v0|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|‹|U|,| |T|,| |V|›|(|v0|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|(|v0|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
+//│ Parsed: {fun extend: [] -> (v0: T, v1: U,) -> ((T,) & (U,)); fun foo: [] -> (v0: (T,) & (U,),) -> unit; fun over: [] -> (v0: (number -> string,) & (object -> string,),) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> (v0: (IA,) & (IB,),) -> ((IA,) & (IB,)); fun uu: [] -> (v0: ((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (v0: ((U,) & (T,),) & (V,),) -> (((U,) & (T,),) & (V,)); fun arr: [] -> (v0: (MutArray[U],) & (MutArray[T],),) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (v0: ((U, T,),) & ((V, V,),),) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> (v0: (A,) & (B,),) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index f00c3ec11e..7af92a7a38 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,6 +1,6 @@
 :NewParser
 :ParseOnly
-fun multi1(_: number): number
+fun multi1(v0: number): number
 fun multi3(): unit
 class Foo(): Base {}
 trait AnotherBase() {
@@ -11,12 +11,12 @@ namespace N {
   fun g(): unit
   fun h(): unit
 }
-fun multi2(_: string): string
+fun multi2(v0: string): string
 fun multi4(): unit
 trait Base() {
   let a: number
 }
 class AnotherFoo(): AnotherBase {}
 fun multi5(): unit
-//│ |#fun| |multi1|(|_|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|_|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit|
-//│ Parsed: {fun multi1: [] -> (_: number,) -> number; fun multi3: [] -> () -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> () -> unit; fun g: [] -> () -> unit; fun h: [] -> () -> unit}; fun multi2: [] -> (_: string,) -> string; fun multi4: [] -> () -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> () -> unit}
+//│ |#fun| |multi1|(|v0|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|v0|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit|
+//│ Parsed: {fun multi1: [] -> (v0: number,) -> number; fun multi3: [] -> () -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> () -> unit; fun g: [] -> () -> unit; fun h: [] -> () -> unit}; fun multi2: [] -> (v0: string,) -> string; fun multi4: [] -> () -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> () -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 07c9588e34..5bf302a3c1 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,8 +1,8 @@
 :NewParser
 :ParseOnly
 namespace N1 {
-  fun f(_: anything): number
-  fun ff(_: anything): number
+  fun f(v0: anything): number
+  fun ff(v0: anything): number
   class C() {
     fun f(): unit
   }
@@ -10,13 +10,13 @@ namespace N1 {
     fun f(): number
   }
   namespace N2 {
-    fun fff(_: bool): number
-    fun gg(_: N1'C): N1'C
+    fun fff(v0: bool): number
+    fun gg(v0: N1'C): N1'C
     class BBB(): N1'C {}
   }
 }
 namespace AA {
-  fun f(_: anything): string
+  fun f(v0: anything): string
   class C() {
     fun f(): unit
   }
@@ -26,7 +26,7 @@ namespace AA {
   namespace N2 {
   }
 }
-fun f1(_: N1'C): N1'C
-fun f2(_: AA'C): AA'C
-//│ |#namespace| |N1| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |number|↵|#fun| |ff|(|_|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|_|#:| |bool|)|#:| |number|↵|#fun| |gg|(|_|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|_|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|_|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|_|#:| |AA'C|)|#:| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> (_: anything,) -> number; fun ff: [] -> (_: anything,) -> number; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {fun fff: [] -> (_: bool,) -> number; fun gg: [] -> (_: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (_: anything,) -> string; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {}}; fun f1: [] -> (_: N1'C,) -> N1'C; fun f2: [] -> (_: AA'C,) -> AA'C}
+fun f1(v0: N1'C): N1'C
+fun f2(v0: AA'C): AA'C
+//│ |#namespace| |N1| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |number|↵|#fun| |ff|(|v0|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|v0|#:| |bool|)|#:| |number|↵|#fun| |gg|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|v0|#:| |AA'C|)|#:| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> (v0: anything,) -> number; fun ff: [] -> (v0: anything,) -> number; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {fun fff: [] -> (v0: bool,) -> number; fun gg: [] -> (v0: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (v0: anything,) -> string; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {}}; fun f1: [] -> (v0: N1'C,) -> N1'C; fun f2: [] -> (v0: AA'C,) -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 098b9dacdd..66deab5c00 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
-fun buildName(_: string, _: (string) | (undefined)): string
-fun buildName2(_: string, _: (string) | (undefined)): string
-fun buildName3(_: string, _: MutArray<string>): string
-fun buildName4(_: string, _: MutArray<anything>): string
+fun buildName(v0: string, v1: (string) | (undefined)): string
+fun buildName2(v0: string, v1: (string) | (undefined)): string
+fun buildName3(v0: string, v1: MutArray<string>): string
+fun buildName4(v0: string, v1: MutArray<anything>): string
 trait SquareConfig() {
   let color: (string) | (undefined)
   let width: (number) | (undefined)
 }
-fun did(_: number, _: (number => number) | (undefined)): number
-fun getOrElse(_: (MutArray<object>) | (undefined)): object
+fun did(v0: number, v1: (number => number) | (undefined)): number
+fun getOrElse(v0: (MutArray<object>) | (undefined)): object
 class ABC() {}
-fun testABC(_: (ABC) | (undefined)): unit
-fun testSquareConfig(_: (SquareConfig) | (undefined)): unit
-fun err(_: ((number, string, )) | (undefined)): unit
-fun toStr(_: ((number) | (bool)) | (undefined)): string
-fun boo<T, U>(_: ((T) & (U)) | (undefined)): unit
+fun testABC(v0: (ABC) | (undefined)): unit
+fun testSquareConfig(v0: (SquareConfig) | (undefined)): unit
+fun err(v0: ((number, string, )) | (undefined)): unit
+fun toStr(v0: ((number) | (bool)) | (undefined)): string
+fun boo<T, U>(v0: ((T) & (U)) | (undefined)): unit
 class B<T>() {
   let b: T
 }
-fun boom(_: (B<nothing>) | (undefined)): anything
-//│ |#fun| |buildName|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|_|#:| |string|,| |_|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|_|#:| |string|,| |_|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|_|#:| |string|,| |_|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|(|_|#:| |number|,| |_|#:| |(|number| |=>| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|_|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|_|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|_|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|_|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|_|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|_|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|_|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
-//│ Parsed: {fun buildName: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName2: [] -> (_: string, _: (string,) | (undefined,),) -> string; fun buildName3: [] -> (_: string, _: MutArray[string],) -> string; fun buildName4: [] -> (_: string, _: MutArray[anything],) -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> (_: number, _: (number -> number,) | (undefined,),) -> number; fun getOrElse: [] -> (_: (MutArray[object],) | (undefined,),) -> object; class ABC() {}; fun testABC: [] -> (_: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (_: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> (_: ((number, string,),) | (undefined,),) -> unit; fun toStr: [] -> (_: ((number,) | (bool,),) | (undefined,),) -> string; fun boo: [] -> (_: ((T,) & (U,),) | (undefined,),) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> (_: (B[nothing],) | (undefined,),) -> anything}
+fun boom(v0: (B<nothing>) | (undefined)): anything
+//│ |#fun| |buildName|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|(|v0|#:| |number|,| |v1|#:| |(|number| |=>| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|v0|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|v0|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|v0|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|v0|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|v0|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|v0|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
+//│ Parsed: {fun buildName: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName2: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName3: [] -> (v0: string, v1: MutArray[string],) -> string; fun buildName4: [] -> (v0: string, v1: MutArray[anything],) -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> (v0: number, v1: (number -> number,) | (undefined,),) -> number; fun getOrElse: [] -> (v0: (MutArray[object],) | (undefined,),) -> object; class ABC() {}; fun testABC: [] -> (v0: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (v0: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> (v0: ((number, string,),) | (undefined,),) -> unit; fun toStr: [] -> (v0: ((number,) | (bool,),) | (undefined,),) -> string; fun boo: [] -> (v0: ((T,) & (U,),) | (undefined,),) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> (v0: (B[nothing],) | (undefined,),) -> anything}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 67ab4f93bc..1529b0f9e9 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,20 +1,20 @@
 :NewParser
 :ParseOnly
-fun key(_: (string, bool, )): string
-fun value(_: (string, bool, )): bool
-fun third(_: (number, number, number, )): number
-fun vec2(_: number, _: number): (number, number, )
-fun twoFunctions(_: (number => number, number => number, ), _: number): number
-fun tupleIt(_: string): (unit => string, )
-fun s(_: bool): ((string) | (number), (number) | (bool), )
-fun s2(_: (bool, (string) | (number), )): (string) | (number)
-fun ex<T, U>(_: T, _: U): (T, U, (T) & (U), )
-fun foo<T, U>(_: ((T) & (U), )): unit
-fun conv(_: (y: number,)): ((y: number,), (z: string,), )
+fun key(v0: (string, bool, )): string
+fun value(v0: (string, bool, )): bool
+fun third(v0: (number, number, number, )): number
+fun vec2(v0: number, v1: number): (number, number, )
+fun twoFunctions(v0: (number => number, number => number, ), v1: number): number
+fun tupleIt(v0: string): (unit => string, )
+fun s(v0: bool): ((string) | (number), (number) | (bool), )
+fun s2(v0: (bool, (string) | (number), )): (string) | (number)
+fun ex<T, U>(v0: T, v1: U): (T, U, (T) & (U), )
+fun foo<T, U>(v0: ((T) & (U), )): unit
+fun conv(v0: (y: number,)): ((y: number,), (z: string,), )
 class A() {
   let x: number
 }
 class B() {}
-fun swap(_: (A, B, )): (B, A, )
-//│ |#fun| |key|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |string|↵|#fun| |value|(|_|#:| |(|string|,| |bool|,| |)|)|#:| |bool|↵|#fun| |third|(|_|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|_|#:| |number|,| |_|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|_|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)|,| |_|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|_|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|_|#:| |bool|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|(|_|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|_|#:| |T|,| |_|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|_|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|_|#:| |(|y|#:| |number|,|)|)|#:| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|_|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
-//│ Parsed: {fun key: [] -> (_: (string, bool,),) -> string; fun value: [] -> (_: (string, bool,),) -> bool; fun third: [] -> (_: (number, number, number,),) -> number; fun vec2: [] -> (_: number, _: number,) -> (number, number,); fun twoFunctions: [] -> (_: (number -> number, number -> number,), _: number,) -> number; fun tupleIt: [] -> (_: string,) -> (unit -> string,); fun s: [] -> (_: bool,) -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (_: (bool, (string,) | (number,),),) -> ((string,) | (number,)); fun ex: [] -> (_: T, _: U,) -> (T, U, (T,) & (U,),); fun foo: [] -> (_: ((T,) & (U,),),) -> unit; fun conv: [] -> (_: (y: number,),) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (_: (A, B,),) -> (B, A,)}
+fun swap(v0: (A, B, )): (B, A, )
+//│ |#fun| |key|(|v0|#:| |(|string|,| |bool|,| |)|)|#:| |string|↵|#fun| |value|(|v0|#:| |(|string|,| |bool|,| |)|)|#:| |bool|↵|#fun| |third|(|v0|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|v0|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)|,| |v1|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|v0|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|v0|#:| |bool|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|(|v0|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|v0|#:| |T|,| |v1|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|v0|#:| |(|y|#:| |number|,|)|)|#:| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|v0|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
+//│ Parsed: {fun key: [] -> (v0: (string, bool,),) -> string; fun value: [] -> (v0: (string, bool,),) -> bool; fun third: [] -> (v0: (number, number, number,),) -> number; fun vec2: [] -> (v0: number, v1: number,) -> (number, number,); fun twoFunctions: [] -> (v0: (number -> number, number -> number,), v1: number,) -> number; fun tupleIt: [] -> (v0: string,) -> (unit -> string,); fun s: [] -> (v0: bool,) -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (v0: (bool, (string,) | (number,),),) -> ((string,) | (number,)); fun ex: [] -> (v0: T, v1: U,) -> (T, U, (T,) & (U,),); fun foo: [] -> (v0: ((T,) & (U,),),) -> unit; fun conv: [] -> (v0: (y: number,),) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (v0: (A, B,),) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index e41d58fc8a..7b97da7b33 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,29 +1,29 @@
 :NewParser
 :ParseOnly
-fun inc<T>(_: T): number
+fun inc<T>(v0: T): number
 class CC<T>() {
-  fun print(_: T): unit
+  fun print(v0: T): unit
 }
-fun con<U, T>(_: T): U
+fun con<U, T>(v0: T): U
 class Printer<T>() {
-  fun print(_: T): unit
+  fun print(v0: T): unit
 }
-fun setStringPrinter(_: Printer<string>): unit
+fun setStringPrinter(v0: Printer<string>): unit
 fun getStringPrinter(): Printer<string>
-fun foo<T>(_: Printer<T>, _: T): T
-fun foo2<T>(_: Printer<T>, _: T): T
+fun foo<T>(v0: Printer<T>, v1: T): T
+fun foo2<T>(v0: Printer<T>, v1: T): T
 class F<T>() {
   let x: T
-  fun GG<U>(_: U): T
+  fun GG<U>(v0: U): T
 }
 trait I<T>() {
   let x: T
-  fun GG<U>(_: U): T
+  fun GG<U>(v0: U): T
 }
 class FFF<T>() {
-  fun fff(_: T): unit
+  fun fff(v0: T): unit
 }
-fun fff(_: FFF<string>, _: string): unit
+fun fff(v0: FFF<string>, v1: string): unit
 fun getFFF(): FFF<number>
-//│ |#fun| |inc|‹|T|›|(|_|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|_|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|_|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|_|#:| |Printer|‹|T|›|,| |_|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|_|#:| |U|)|#:| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|_|#:| |U|)|#:| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|(|_|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |fff|(|_|#:| |FFF|‹|string|›|,| |_|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> (_: T,) -> number; class CC[T]() {fun print: [] -> (_: T,) -> unit}; fun con: [] -> (_: T,) -> U; class Printer[T]() {fun print: [] -> (_: T,) -> unit}; fun setStringPrinter: [] -> (_: Printer[string],) -> unit; fun getStringPrinter: [] -> () -> Printer[string]; fun foo: [] -> (_: Printer[T], _: T,) -> T; fun foo2: [] -> (_: Printer[T], _: T,) -> T; class F[T]() {let x: [] -> T; fun GG: [] -> (_: U,) -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> (_: U,) -> T}; class FFF[T]() {fun fff: [] -> (_: T,) -> unit}; fun fff: [] -> (_: FFF[string], _: string,) -> unit; fun getFFF: [] -> () -> FFF[number]}
+//│ |#fun| |inc|‹|T|›|(|v0|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|v0|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|v0|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|v0|#:| |Printer|‹|T|›|,| |v1|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|v0|#:| |Printer|‹|T|›|,| |v1|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|v0|#:| |U|)|#:| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|v0|#:| |U|)|#:| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |fff|(|v0|#:| |FFF|‹|string|›|,| |v1|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> (v0: T,) -> number; class CC[T]() {fun print: [] -> (v0: T,) -> unit}; fun con: [] -> (v0: T,) -> U; class Printer[T]() {fun print: [] -> (v0: T,) -> unit}; fun setStringPrinter: [] -> (v0: Printer[string],) -> unit; fun getStringPrinter: [] -> () -> Printer[string]; fun foo: [] -> (v0: Printer[T], v1: T,) -> T; fun foo2: [] -> (v0: Printer[T], v1: T,) -> T; class F[T]() {let x: [] -> T; fun GG: [] -> (v0: U,) -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> (v0: U,) -> T}; class FFF[T]() {fun fff: [] -> (v0: T,) -> unit}; fun fff: [] -> (v0: FFF[string], v1: string,) -> unit; fun getFFF: [] -> () -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index c798c7163e..6cbed5c6da 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,11 +1,11 @@
 :NewParser
 :ParseOnly
-fun getString(_: ((string) | (number)) | (bool)): string
-fun test(_: bool): (string) | (number)
-fun run(_: (number => number) | (number => string)): anything
-fun get(_: (MutArray<number>) | (MutArray<string>)): unit
-fun get2(_: ((string, string, )) | ((number, string, ))): string
-fun typeVar<T, U>(_: (T) | (U)): (T) | (U)
-fun uuuu(_: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
-//│ |#fun| |getString|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|_|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|_|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|_|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|_|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|_|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|_|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ Parsed: {fun getString: [] -> (_: ((string,) | (number,),) | (bool,),) -> string; fun test: [] -> (_: bool,) -> ((string,) | (number,)); fun run: [] -> (_: (number -> number,) | (number -> string,),) -> anything; fun get: [] -> (_: (MutArray[number],) | (MutArray[string],),) -> unit; fun get2: [] -> (_: ((string, string,),) | ((number, string,),),) -> string; fun typeVar: [] -> (_: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (_: ((string,) | (number,),) | (bool,),) -> (((string,) | (number,),) | (bool,))}
+fun getString(v0: ((string) | (number)) | (bool)): string
+fun test(v0: bool): (string) | (number)
+fun run(v0: (number => number) | (number => string)): anything
+fun get(v0: (MutArray<number>) | (MutArray<string>)): unit
+fun get2(v0: ((string, string, )) | ((number, string, ))): string
+fun typeVar<T, U>(v0: (T) | (U)): (T) | (U)
+fun uuuu(v0: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
+//│ |#fun| |getString|(|v0|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|v0|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|v0|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|v0|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|v0|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|v0|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|v0|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
+//│ Parsed: {fun getString: [] -> (v0: ((string,) | (number,),) | (bool,),) -> string; fun test: [] -> (v0: bool,) -> ((string,) | (number,)); fun run: [] -> (v0: (number -> number,) | (number -> string,),) -> anything; fun get: [] -> (v0: (MutArray[number],) | (MutArray[string],),) -> unit; fun get2: [] -> (v0: ((string, string,),) | ((number, string,),),) -> string; fun typeVar: [] -> (v0: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (v0: ((string,) | (number,),) | (bool,),) -> (((string,) | (number,),) | (bool,))}

From af5f657eaf20ef182a215617a1ad6dbc61b00620 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Mon, 19 Sep 2022 16:29:14 +0800
Subject: [PATCH 27/40] Fix ignored overloading

---
 .../js/src/main/scala/ts2mls/TSNamespace.scala |  4 ++--
 .../main/scala/ts2mls/types/Converter.scala    |  7 ++++---
 ts2mls/js/src/test/diff/Array.d.mls            |  8 ++++----
 ts2mls/js/src/test/diff/BasicFunctions.d.mls   |  8 ++++----
 ts2mls/js/src/test/diff/ClassMember.d.mls      |  6 +++---
 ts2mls/js/src/test/diff/Enum.d.mls             |  6 +++---
 ts2mls/js/src/test/diff/Heritage.d.mls         | 10 +++++-----
 ts2mls/js/src/test/diff/InterfaceMember.d.mls  | 10 +++++-----
 ts2mls/js/src/test/diff/Namespace.d.mls        |  6 +++---
 ts2mls/js/src/test/diff/Optional.d.mls         |  6 +++---
 ts2mls/js/src/test/diff/Overload.d.mls         | 18 +++++++++---------
 ts2mls/js/src/test/diff/Tuple.d.mls            | 12 ++++++------
 ts2mls/js/src/test/diff/Union.d.mls            | 10 +++++-----
 13 files changed, 56 insertions(+), 55 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index ad54f7f147..2e25488543 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -57,8 +57,8 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
           //   else // TODO: add constraints
           //     writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(f)}")
           // }
-          case overload @ TSIgnoredOverload(base, _) =>
-            writer.writeln(s"${indent}fun ${name}: ${Converter.convert(overload)}")
+          case overload: TSIgnoredOverload =>
+            writer.writeln(Converter.generateFunDeclaration(overload, name)(indent))
           // {
           //   val typeParams = base.typeVars.map((t) => t.name)
           //     if (typeParams.isEmpty)
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 1787790ef0..23562a02bf 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -15,8 +15,8 @@ object Converter {
     "undefined" -> "undefined",
     "never" -> "nothing",
     "object" -> "object",
-    "true" -> "bool", // will not appear individually
-    "false" -> "" // will not appear individually
+    "true" -> "true", // will not appear individually
+    "false" -> "false" // will not appear individually
   )
 
   def generateFunDeclaration(tsType: TSType, name: String)(implicit indent: String = ""): String = tsType match {
@@ -25,7 +25,8 @@ object Converter {
       val tpList = if (typeVars.isEmpty) "" else s"<${typeVars.map(p => convert(p)("")).reduceLeft((r, p) => s"$r, $p")}>"
       s"${indent}fun $name$tpList($pList): ${convert(res)("")}"
     }
-    case _ => convert(tsType) // TODO: overload
+    case overload @ TSIgnoredOverload(base, _) => s"${generateFunDeclaration(base, name)} ${overload.warning}"
+    case _ => throw new Exception("non-function type is not allowed.")
   }
 
   def convert(tsType: TSType)(implicit indent: String = ""): String = tsType match {
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 4eb1a9788d..5691fbe475 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -13,11 +13,11 @@ fun doIs(v0: MutArray<I>): MutArray<I>
 fun inter<U, T>(v0: MutArray<(U) & (T)>): MutArray<(U) & (T)>
 fun clean(v0: MutArray<(string, number, )>): MutArray<(string, number, )>
 fun translate<T, U>(v0: MutArray<T>): MutArray<U>
-fun uu(v0: MutArray<(number) | (bool)>): MutArray<(number) | (bool)>
+fun uu(v0: MutArray<((number) | (false)) | (true)>): MutArray<((number) | (false)) | (true)>
 class Temp<T>() {
   let x: T
 }
-fun ta(v0: MutArray<Temp<bool>>): MutArray<Temp<bool>>
+fun ta(v0: MutArray<Temp<(false) | (true)>>): MutArray<Temp<(false) | (true)>>
 fun tat<T>(v0: MutArray<Temp<T>>): MutArray<Temp<T>>
-//│ |#fun| |first|(|v0|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|v0|#:| |MutArray|‹|number| |=>| |number|›|)|#:| |number| |=>| |number|↵|#fun| |doEs|(|v0|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|v0|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|v0|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|v0|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|v0|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|v0|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|v0|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|)|#:| |MutArray|‹|(|number|)| ||| |(|bool|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|v0|#:| |MutArray|‹|Temp|‹|bool|›|›|)|#:| |MutArray|‹|Temp|‹|bool|›|›|↵|#fun| |tat|‹|T|›|(|v0|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|
-//│ Parsed: {fun first: [] -> (v0: MutArray[string],) -> string; fun getZero3: [] -> () -> MutArray[number]; fun first2: [] -> (v0: MutArray[number -> number],) -> number -> number; fun doEs: [] -> (v0: MutArray[int],) -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> (v0: MutArray[C],) -> MutArray[C]; fun doIs: [] -> (v0: MutArray[I],) -> MutArray[I]; fun inter: [] -> (v0: MutArray[(U,) & (T,)],) -> MutArray[(U,) & (T,)]; fun clean: [] -> (v0: MutArray[(string, number,)],) -> MutArray[(string, number,)]; fun translate: [] -> (v0: MutArray[T],) -> MutArray[U]; fun uu: [] -> (v0: MutArray[(number,) | (bool,)],) -> MutArray[(number,) | (bool,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> (v0: MutArray[Temp[bool]],) -> MutArray[Temp[bool]]; fun tat: [] -> (v0: MutArray[Temp[T]],) -> MutArray[Temp[T]]}
+//│ |#fun| |first|(|v0|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|v0|#:| |MutArray|‹|number| |=>| |number|›|)|#:| |number| |=>| |number|↵|#fun| |doEs|(|v0|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|v0|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|v0|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|v0|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|v0|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|v0|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|v0|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|)|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|v0|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|)|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|↵|#fun| |tat|‹|T|›|(|v0|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|
+//│ Parsed: {fun first: [] -> (v0: MutArray[string],) -> string; fun getZero3: [] -> () -> MutArray[number]; fun first2: [] -> (v0: MutArray[number -> number],) -> number -> number; fun doEs: [] -> (v0: MutArray[int],) -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> (v0: MutArray[C],) -> MutArray[C]; fun doIs: [] -> (v0: MutArray[I],) -> MutArray[I]; fun inter: [] -> (v0: MutArray[(U,) & (T,)],) -> MutArray[(U,) & (T,)]; fun clean: [] -> (v0: MutArray[(string, number,)],) -> MutArray[(string, number,)]; fun translate: [] -> (v0: MutArray[T],) -> MutArray[U]; fun uu: [] -> (v0: MutArray[((number,) | (false,),) | (true,)],) -> MutArray[((number,) | (false,),) | (true,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> (v0: MutArray[Temp[(false,) | (true,)]],) -> MutArray[Temp[(false,) | (true,)]]; fun tat: [] -> (v0: MutArray[Temp[T]],) -> MutArray[Temp[T]]}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index f741b86bc4..3bf0b93143 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -5,8 +5,8 @@ fun add(v0: number, v1: number): number
 fun sub(v0: number, v1: number): number
 fun foo(): number
 fun id(v0: anything): anything
-fun odd(v0: number): bool
-fun isnull(v0: anything): bool
+fun odd(v0: number): (false) | (true)
+fun isnull(v0: anything): (false) | (true)
 fun bar(): anything
 fun nu(v0: null): null
 fun un(v0: undefined): undefined
@@ -24,5 +24,5 @@ trait Barrrrrrrrr() {
 }
 fun inn2(v0: Barrrrrrrrr): unit
 fun out2(): Barrrrrrrrr
-//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |sub|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|v0|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|v0|#:| |number|)|#:| |bool|↵|#fun| |isnull|(|v0|#:| |anything|)|#:| |bool|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|v0|#:| |null|)|#:| |null|↵|#fun| |un|(|v0|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|v0|#:| |number|)|#:| |number|↵|#fun| |wtf|(|v0|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|v0|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|v0|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (v0: number, v1: number,) -> number; fun sub: [] -> (v0: number, v1: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (v0: anything,) -> anything; fun odd: [] -> (v0: number,) -> bool; fun isnull: [] -> (v0: anything,) -> bool; fun bar: [] -> () -> anything; fun nu: [] -> (v0: null,) -> null; fun un: [] -> (v0: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (v0: number,) -> number; fun wtf: [] -> (v0: anything,) -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> (v0: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> (v0: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
+//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |sub|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|v0|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|v0|#:| |number|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |isnull|(|v0|#:| |anything|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|v0|#:| |null|)|#:| |null|↵|#fun| |un|(|v0|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|v0|#:| |number|)|#:| |number|↵|#fun| |wtf|(|v0|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|v0|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|v0|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (v0: number, v1: number,) -> number; fun sub: [] -> (v0: number, v1: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (v0: anything,) -> anything; fun odd: [] -> (v0: number,) -> ((false,) | (true,)); fun isnull: [] -> (v0: anything,) -> ((false,) | (true,)); fun bar: [] -> () -> anything; fun nu: [] -> (v0: null,) -> null; fun un: [] -> (v0: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (v0: number,) -> number; fun wtf: [] -> (v0: anything,) -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> (v0: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> (v0: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index fa731d36e1..a834b60b76 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -2,7 +2,7 @@
 :ParseOnly
 class Student(v0: string, v1: number) {
   let name: string
-  fun isFriend(v0: Student): bool
+  fun isFriend(v0: Student): (false) | (true)
   fun addScore(v0: string, v1: number): unit
   fun getID(): number
 }
@@ -21,5 +21,5 @@ class TTT<T>() {
   fun ttt(v0: T): T
   fun ttt2(v0: T): T
 }
-//│ |#class| |Student|(|v0|#:| |string|,| |v1|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|v0|#:| |Student|)|#:| |bool|↵|#fun| |addScore|(|v0|#:| |string|,| |v1|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|v0|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|v0|#:| |T|)|#:| |T|←|↵|}|
-//│ Parsed: {class Student(v0: string, v1: number,) {let name: [] -> string; fun isFriend: [] -> (v0: Student,) -> bool; fun addScore: [] -> (v0: string, v1: number,) -> unit; fun getID: [] -> () -> number}; class Foo[T]() {fun bar: [] -> (v0: T,) -> unit}; class EZ() {fun inc: [] -> (v0: number,) -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> (v0: T,) -> T; fun ttt2: [] -> (v0: T,) -> T}}
+//│ |#class| |Student|(|v0|#:| |string|,| |v1|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|v0|#:| |Student|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |addScore|(|v0|#:| |string|,| |v1|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|v0|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|v0|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {class Student(v0: string, v1: number,) {let name: [] -> string; fun isFriend: [] -> (v0: Student,) -> ((false,) | (true,)); fun addScore: [] -> (v0: string, v1: number,) -> unit; fun getID: [] -> () -> number}; class Foo[T]() {fun bar: [] -> (v0: T,) -> unit}; class EZ() {fun inc: [] -> (v0: number,) -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> (v0: T,) -> T; fun ttt2: [] -> (v0: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index 8b284c0f73..b5c36e52a0 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun pass(v0: int): bool
+fun pass(v0: int): (false) | (true)
 fun stop(): int
 fun g(v0: int): int
-//│ |#fun| |pass|(|v0|#:| |int|)|#:| |bool|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|v0|#:| |int|)|#:| |int|
-//│ Parsed: {fun pass: [] -> (v0: int,) -> bool; fun stop: [] -> () -> int; fun g: [] -> (v0: int,) -> int}
+//│ |#fun| |pass|(|v0|#:| |int|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|v0|#:| |int|)|#:| |int|
+//│ Parsed: {fun pass: [] -> (v0: int,) -> ((false,) | (true,)); fun stop: [] -> () -> int; fun g: [] -> (v0: int,) -> int}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 2f1413d896..8e9250a30d 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -10,13 +10,13 @@ class C<T>() {
 }
 class D(): C<number> {}
 trait Wu() {
-  let x: bool
+  let x: (false) | (true)
 }
 class WuWu(): Wu {
-  let y: bool
+  let y: (false) | (true)
 }
 trait WuWuWu(): WuWu {
-  let z: bool
+  let z: (false) | (true)
 }
 trait Never(): WuWuWu {
   fun w(): nothing
@@ -40,5 +40,5 @@ namespace Five {
   class Y(): Five'ROTK {}
 }
 class Y(): Five'ROTK {}
-//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|v0|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |bool|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |bool|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |bool|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|v0|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|v0|#:| |R|)|#:| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
-//│ Parsed: {class A() {fun foo: [] -> () -> unit}; class B(): A {}; class C[T]() {fun set: [] -> (v0: T,) -> unit; fun get: [] -> () -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> bool}; class WuWu(): Wu {let y: [] -> bool}; trait WuWuWu(): WuWu: {let z: [] -> bool}; trait Never(): WuWuWu: {fun w: [] -> () -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> (v0: I,) -> I}; class OR[R](): O‹R› {fun xx: [] -> (v0: R,) -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|v0|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|v0|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|v0|#:| |R|)|#:| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
+//│ Parsed: {class A() {fun foo: [] -> () -> unit}; class B(): A {}; class C[T]() {fun set: [] -> (v0: T,) -> unit; fun get: [] -> () -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> (false,) | (true,)}; class WuWu(): Wu {let y: [] -> (false,) | (true,)}; trait WuWuWu(): WuWu: {let z: [] -> (false,) | (true,)}; trait Never(): WuWuWu: {fun w: [] -> () -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> (v0: I,) -> I}; class OR[R](): O‹R› {fun xx: [] -> (v0: R,) -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index c945208d5a..312ba2ea79 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -3,7 +3,7 @@
 trait IFoo() {
   let a: string
   fun b(v0: number): number
-  fun c(): bool
+  fun c(): (false) | (true)
   fun d(v0: string): unit
 }
 trait II<T>() {
@@ -15,7 +15,7 @@ trait IEvent() {
   fun callback(v0: unit): number => unit
 }
 trait SearchFunc() {
-  fun __call(v0: string, v1: string): bool
+  fun __call(v0: string, v1: string): (false) | (true)
 }
 trait StringArray() {
   fun __index(v0: number): string
@@ -27,7 +27,7 @@ trait Counter() {
 }
 trait Simple() {
   let a: number
-  fun b(v0: bool): string
+  fun b(v0: (false) | (true)): string
 }
 trait Simple2<T>() {
   let abc: T
@@ -36,5 +36,5 @@ trait Next(): Simple {}
 trait TTT<T>() {
   fun ttt(v0: T): T
 }
-//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|v0|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |bool|↵|#fun| |d|(|v0|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|v0|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|v0|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(|v0|#:| |unit|)|#:| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|v0|#:| |string|,| |v1|#:| |string|)|#:| |bool|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|v0|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|v0|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|v0|#:| |bool|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (v0: number,) -> number; fun c: [] -> () -> bool; fun d: [] -> (v0: string,) -> unit}; trait II[T](): {fun test: [] -> (v0: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (v0: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> (v0: unit,) -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (v0: string, v1: string,) -> bool}; trait StringArray(): {fun __index: [] -> (v0: number,) -> string}; trait Counter(): {fun __call: [] -> (v0: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (v0: bool,) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (v0: T,) -> T}}
+//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|v0|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |d|(|v0|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|v0|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|v0|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(|v0|#:| |unit|)|#:| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|v0|#:| |string|,| |v1|#:| |string|)|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|v0|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|v0|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (v0: number,) -> number; fun c: [] -> () -> ((false,) | (true,)); fun d: [] -> (v0: string,) -> unit}; trait II[T](): {fun test: [] -> (v0: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (v0: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> (v0: unit,) -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (v0: string, v1: string,) -> ((false,) | (true,))}; trait StringArray(): {fun __index: [] -> (v0: number,) -> string}; trait Counter(): {fun __call: [] -> (v0: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (v0: (false,) | (true,),) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (v0: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 5bf302a3c1..33cc534960 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -10,7 +10,7 @@ namespace N1 {
     fun f(): number
   }
   namespace N2 {
-    fun fff(v0: bool): number
+    fun fff(v0: (false) | (true)): number
     fun gg(v0: N1'C): N1'C
     class BBB(): N1'C {}
   }
@@ -28,5 +28,5 @@ namespace AA {
 }
 fun f1(v0: N1'C): N1'C
 fun f2(v0: AA'C): AA'C
-//│ |#namespace| |N1| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |number|↵|#fun| |ff|(|v0|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|v0|#:| |bool|)|#:| |number|↵|#fun| |gg|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|v0|#:| |AA'C|)|#:| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> (v0: anything,) -> number; fun ff: [] -> (v0: anything,) -> number; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {fun fff: [] -> (v0: bool,) -> number; fun gg: [] -> (v0: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (v0: anything,) -> string; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {}}; fun f1: [] -> (v0: N1'C,) -> N1'C; fun f2: [] -> (v0: AA'C,) -> AA'C}
+//│ |#namespace| |N1| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |number|↵|#fun| |ff|(|v0|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |number|↵|#fun| |gg|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|v0|#:| |AA'C|)|#:| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> (v0: anything,) -> number; fun ff: [] -> (v0: anything,) -> number; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {fun fff: [] -> (v0: (false,) | (true,),) -> number; fun gg: [] -> (v0: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (v0: anything,) -> string; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {}}; fun f1: [] -> (v0: N1'C,) -> N1'C; fun f2: [] -> (v0: AA'C,) -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 66deab5c00..822d3b5625 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -14,11 +14,11 @@ class ABC() {}
 fun testABC(v0: (ABC) | (undefined)): unit
 fun testSquareConfig(v0: (SquareConfig) | (undefined)): unit
 fun err(v0: ((number, string, )) | (undefined)): unit
-fun toStr(v0: ((number) | (bool)) | (undefined)): string
+fun toStr(v0: (((number) | (false)) | (true)) | (undefined)): string
 fun boo<T, U>(v0: ((T) & (U)) | (undefined)): unit
 class B<T>() {
   let b: T
 }
 fun boom(v0: (B<nothing>) | (undefined)): anything
-//│ |#fun| |buildName|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|(|v0|#:| |number|,| |v1|#:| |(|number| |=>| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|v0|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|v0|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|v0|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|v0|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|v0|#:| |(|(|number|)| ||| |(|bool|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|v0|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
-//│ Parsed: {fun buildName: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName2: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName3: [] -> (v0: string, v1: MutArray[string],) -> string; fun buildName4: [] -> (v0: string, v1: MutArray[anything],) -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> (v0: number, v1: (number -> number,) | (undefined,),) -> number; fun getOrElse: [] -> (v0: (MutArray[object],) | (undefined,),) -> object; class ABC() {}; fun testABC: [] -> (v0: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (v0: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> (v0: ((number, string,),) | (undefined,),) -> unit; fun toStr: [] -> (v0: ((number,) | (bool,),) | (undefined,),) -> string; fun boo: [] -> (v0: ((T,) & (U,),) | (undefined,),) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> (v0: (B[nothing],) | (undefined,),) -> anything}
+//│ |#fun| |buildName|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|(|v0|#:| |number|,| |v1|#:| |(|number| |=>| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|v0|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|v0|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|v0|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|v0|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|v0|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|v0|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
+//│ Parsed: {fun buildName: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName2: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName3: [] -> (v0: string, v1: MutArray[string],) -> string; fun buildName4: [] -> (v0: string, v1: MutArray[anything],) -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> (v0: number, v1: (number -> number,) | (undefined,),) -> number; fun getOrElse: [] -> (v0: (MutArray[object],) | (undefined,),) -> object; class ABC() {}; fun testABC: [] -> (v0: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (v0: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> (v0: ((number, string,),) | (undefined,),) -> unit; fun toStr: [] -> (v0: (((number,) | (false,),) | (true,),) | (undefined,),) -> string; fun boo: [] -> (v0: ((T,) & (U,),) | (undefined,),) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> (v0: (B[nothing],) | (undefined,),) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 86431a5f01..129faf354a 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -5,22 +5,22 @@ class M() {
   let foo: (number => string) & (string => string)
 }
 fun app: ((string => unit) => number => unit) & ((string => unit) => string => unit)
-fun create: (number => unit => bool) & (bool => unit => bool)
+fun create: (number => unit => (false) | (true)) & ((false) | (true) => unit => (false) | (true))
 fun g0: (MutArray<string> => string) & (MutArray<object> => string)
 fun db: (number => MutArray<number>) & (object => MutArray<number>)
 class N() {}
 fun id: (M => unit) & (N => unit)
-fun tst: ((z: number,) => (y: string,)) & ((z: bool,) => (y: string,))
-fun op: (number => (number) | (undefined) => unit) & (number => (bool) | (undefined) => unit)
+fun tst: ((z: number,) => (y: string,)) & ((z: (false) | (true),) => (y: string,))
+fun op: (number => (number) | (undefined) => unit) & (number => ((false) | (true)) | (undefined) => unit)
 fun swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
-fun u: ((number) | (bool) => string) & (object => string)
-fun doSome: anything => unit /* warning: the overload of function doSome is not supported yet. */
+fun u: (((number) | (false)) | (true) => string) & (object => string)
+fun doSome<T, U>(v0: anything): unit /* warning: the overload of function doSome is not supported yet. */
 namespace XX {
-  fun f: T => anything => string /* warning: the overload of function f is not supported yet. */
+  fun f<T>(v0: T, v1: anything): string /* warning: the overload of function f is not supported yet. */
 }
 class WWW() {
   fun F: T => anything /* warning: the overload of function F is not supported yet. */
 }
-fun baz: unit => anything /* warning: the overload of function baz is not supported yet. */
-//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |bool|)| |&| |(|bool| |=>| |unit| |=>| |bool|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |bool|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|bool|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|number|)| ||| |(|bool|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|#:| |anything| |=>| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|#:| |T| |=>| |anything| |=>| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|#:| |unit| |=>| |anything| |/* warning: the overload of function baz is not supported yet. */|
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> bool,) & (bool -> unit -> bool,); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: bool,) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> ((bool,) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> (((number,) | (bool,)) -> string,) & (object -> string,); fun doSome: [] -> anything -> unit; namespace XX(): {fun f: [] -> T -> anything -> string}; class WWW() {fun F: [] -> T -> anything}; fun baz: [] -> unit -> anything}
+fun baz(): anything /* warning: the overload of function baz is not supported yet. */
+//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|false|)| ||| |(|true|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |(|false|)| ||| |(|true|)|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|(|false|)| ||| |(|true|)|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|v0|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|‹|T|›|(|v0|#:| |T|,| |v1|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> ((false,) | (true,)),) & (((false,) | (true,)) -> unit -> ((false,) | (true,)),); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: (false,) | (true,),) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> (((false,) | (true,),) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> ((((number,) | (false,),) | (true,)) -> string,) & (object -> string,); fun doSome: [] -> (v0: anything,) -> unit; namespace XX(): {fun f: [] -> (v0: T, v1: anything,) -> string}; class WWW() {fun F: [] -> T -> anything}; fun baz: [] -> () -> anything}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 1529b0f9e9..3d4709090b 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,13 +1,13 @@
 :NewParser
 :ParseOnly
-fun key(v0: (string, bool, )): string
-fun value(v0: (string, bool, )): bool
+fun key(v0: (string, (false) | (true), )): string
+fun value(v0: (string, (false) | (true), )): (false) | (true)
 fun third(v0: (number, number, number, )): number
 fun vec2(v0: number, v1: number): (number, number, )
 fun twoFunctions(v0: (number => number, number => number, ), v1: number): number
 fun tupleIt(v0: string): (unit => string, )
-fun s(v0: bool): ((string) | (number), (number) | (bool), )
-fun s2(v0: (bool, (string) | (number), )): (string) | (number)
+fun s(v0: (false) | (true)): ((string) | (number), ((number) | (false)) | (true), )
+fun s2(v0: ((false) | (true), (string) | (number), )): (string) | (number)
 fun ex<T, U>(v0: T, v1: U): (T, U, (T) & (U), )
 fun foo<T, U>(v0: ((T) & (U), )): unit
 fun conv(v0: (y: number,)): ((y: number,), (z: string,), )
@@ -16,5 +16,5 @@ class A() {
 }
 class B() {}
 fun swap(v0: (A, B, )): (B, A, )
-//│ |#fun| |key|(|v0|#:| |(|string|,| |bool|,| |)|)|#:| |string|↵|#fun| |value|(|v0|#:| |(|string|,| |bool|,| |)|)|#:| |bool|↵|#fun| |third|(|v0|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|v0|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)|,| |v1|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|v0|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|v0|#:| |bool|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|number|)| ||| |(|bool|)|,| |)|↵|#fun| |s2|(|v0|#:| |(|bool|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|v0|#:| |T|,| |v1|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|v0|#:| |(|y|#:| |number|,|)|)|#:| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|v0|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
-//│ Parsed: {fun key: [] -> (v0: (string, bool,),) -> string; fun value: [] -> (v0: (string, bool,),) -> bool; fun third: [] -> (v0: (number, number, number,),) -> number; fun vec2: [] -> (v0: number, v1: number,) -> (number, number,); fun twoFunctions: [] -> (v0: (number -> number, number -> number,), v1: number,) -> number; fun tupleIt: [] -> (v0: string,) -> (unit -> string,); fun s: [] -> (v0: bool,) -> ((string,) | (number,), (number,) | (bool,),); fun s2: [] -> (v0: (bool, (string,) | (number,),),) -> ((string,) | (number,)); fun ex: [] -> (v0: T, v1: U,) -> (T, U, (T,) & (U,),); fun foo: [] -> (v0: ((T,) & (U,),),) -> unit; fun conv: [] -> (v0: (y: number,),) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (v0: (A, B,),) -> (B, A,)}
+//│ |#fun| |key|(|v0|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |string|↵|#fun| |value|(|v0|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |third|(|v0|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|v0|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)|,| |v1|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|v0|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|,| |)|↵|#fun| |s2|(|v0|#:| |(|(|false|)| ||| |(|true|)|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|v0|#:| |T|,| |v1|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|v0|#:| |(|y|#:| |number|,|)|)|#:| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|v0|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
+//│ Parsed: {fun key: [] -> (v0: (string, (false,) | (true,),),) -> string; fun value: [] -> (v0: (string, (false,) | (true,),),) -> ((false,) | (true,)); fun third: [] -> (v0: (number, number, number,),) -> number; fun vec2: [] -> (v0: number, v1: number,) -> (number, number,); fun twoFunctions: [] -> (v0: (number -> number, number -> number,), v1: number,) -> number; fun tupleIt: [] -> (v0: string,) -> (unit -> string,); fun s: [] -> (v0: (false,) | (true,),) -> ((string,) | (number,), ((number,) | (false,),) | (true,),); fun s2: [] -> (v0: ((false,) | (true,), (string,) | (number,),),) -> ((string,) | (number,)); fun ex: [] -> (v0: T, v1: U,) -> (T, U, (T,) & (U,),); fun foo: [] -> (v0: ((T,) & (U,),),) -> unit; fun conv: [] -> (v0: (y: number,),) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (v0: (A, B,),) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 6cbed5c6da..2d01aa7aa6 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,11 +1,11 @@
 :NewParser
 :ParseOnly
-fun getString(v0: ((string) | (number)) | (bool)): string
-fun test(v0: bool): (string) | (number)
+fun getString(v0: (((string) | (number)) | (false)) | (true)): string
+fun test(v0: (false) | (true)): (string) | (number)
 fun run(v0: (number => number) | (number => string)): anything
 fun get(v0: (MutArray<number>) | (MutArray<string>)): unit
 fun get2(v0: ((string, string, )) | ((number, string, ))): string
 fun typeVar<T, U>(v0: (T) | (U)): (T) | (U)
-fun uuuu(v0: ((string) | (number)) | (bool)): ((string) | (number)) | (bool)
-//│ |#fun| |getString|(|v0|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |string|↵|#fun| |test|(|v0|#:| |bool|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|v0|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|v0|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|v0|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|v0|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|v0|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|)|#:| |(|(|string|)| ||| |(|number|)|)| ||| |(|bool|)|
-//│ Parsed: {fun getString: [] -> (v0: ((string,) | (number,),) | (bool,),) -> string; fun test: [] -> (v0: bool,) -> ((string,) | (number,)); fun run: [] -> (v0: (number -> number,) | (number -> string,),) -> anything; fun get: [] -> (v0: (MutArray[number],) | (MutArray[string],),) -> unit; fun get2: [] -> (v0: ((string, string,),) | ((number, string,),),) -> string; fun typeVar: [] -> (v0: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (v0: ((string,) | (number,),) | (bool,),) -> (((string,) | (number,),) | (bool,))}
+fun uuuu(v0: (((string) | (number)) | (false)) | (true)): (((string) | (number)) | (false)) | (true)
+//│ |#fun| |getString|(|v0|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |string|↵|#fun| |test|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|v0|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|v0|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|v0|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|v0|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|v0|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|
+//│ Parsed: {fun getString: [] -> (v0: (((string,) | (number,),) | (false,),) | (true,),) -> string; fun test: [] -> (v0: (false,) | (true,),) -> ((string,) | (number,)); fun run: [] -> (v0: (number -> number,) | (number -> string,),) -> anything; fun get: [] -> (v0: (MutArray[number],) | (MutArray[string],),) -> unit; fun get2: [] -> (v0: ((string, string,),) | ((number, string,),),) -> string; fun typeVar: [] -> (v0: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (v0: (((string,) | (number,),) | (false,),) | (true,),) -> ((((string,) | (number,),) | (false,),) | (true,))}

From 218e6b8ffb36a02339c0355635ea246c4c2f3fb5 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Mon, 19 Sep 2022 16:39:30 +0800
Subject: [PATCH 28/40] Fix ignored overloading in classes

---
 .../src/main/scala/ts2mls/TSNamespace.scala   | 24 +------------------
 .../main/scala/ts2mls/types/Converter.scala   | 19 ++-------------
 ts2mls/js/src/test/diff/Overload.d.mls        |  6 ++---
 3 files changed, 6 insertions(+), 43 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
index 2e25488543..4546290287 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
@@ -44,28 +44,13 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
       }
       case Right(name) => {
         val mem = members(name)
-        // val fullName = getFullPath(name)
         mem match {
           case inter: TSIntersectionType => // overloaded functions
-            writer.writeln(s"${indent}fun ${name}: ${Converter.convert(inter)}")
+            writer.writeln(Converter.generateFunDeclaration(inter, name)(indent))
           case f: TSFunctionType =>
             writer.writeln(Converter.generateFunDeclaration(f, name)(indent))
-          // {
-          //   val typeParams = f.typeVars.map((t) => t.name)
-          //   if (typeParams.isEmpty)
-          //     writer.writeln(s"def ${fullName}: ${Converter.convert(f)}")
-          //   else // TODO: add constraints
-          //     writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(f)}")
-          // }
           case overload: TSIgnoredOverload =>
             writer.writeln(Converter.generateFunDeclaration(overload, name)(indent))
-          // {
-          //   val typeParams = base.typeVars.map((t) => t.name)
-          //     if (typeParams.isEmpty)
-          //       writer.writeln(s"def ${fullName}: ${Converter.convert(overload)}")
-          //     else // TODO: add constraints
-          //       writer.writeln(s"def ${fullName}[${typeParams.reduceLeft((r, s) => s"$r, $s")}]: ${Converter.convert(overload)}")
-          // }
           case _: TSClassType => writer.writeln(Converter.convert(mem)(indent))
           case TSInterfaceType(name, _, _, _) if (name =/= "") =>
             writer.writeln(Converter.convert(mem)(indent))
@@ -73,13 +58,6 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
         }
       }
     })
-
-  // generate full path with namespaces' names
-  // e.g. f => Namespace1.Namespace2.f
-  // def getFullPath(nm: String): String = parent match {
-  //   case Some(p) => p.getFullPath(s"$name'$nm")
-  //   case _ => nm
-  // }
 }
 
 object TSNamespace {
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 23562a02bf..f3a818f791 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -26,6 +26,7 @@ object Converter {
       s"${indent}fun $name$tpList($pList): ${convert(res)("")}"
     }
     case overload @ TSIgnoredOverload(base, _) => s"${generateFunDeclaration(base, name)} ${overload.warning}"
+    case inter: TSIntersectionType => s"${indent}fun ${name}: ${Converter.convert(inter)}"
     case _ => throw new Exception("non-function type is not allowed.")
   }
 
@@ -69,20 +70,9 @@ object Converter {
         if (typeName === "trait ") s"${m._1}: ${convert(m._2)},"
         else m._2.base match {
           case _: TSFunctionType => s"${generateFunDeclaration(m._2.base, m._1)(indent + "  ")}\n"
-          case _: TSIgnoredOverload => s"${indent}  fun ${m._1}: ${convert(m._2)}\n"
+          case _: TSIgnoredOverload => s"${generateFunDeclaration(m._2.base, m._1)(indent + "  ")}\n"
           case _ => s"${indent}  let ${m._1}: ${convert(m._2)}\n"
         }
-      // case Public => {
-      //   m._2.base match { // methods
-      //     case f @ TSFunctionType(_, _, typeVars) if (!typeVars.isEmpty) =>
-      //       s"  method ${m._1}[${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}]: ${convert(f)}" // TODO: add constraints
-      //     case overload @ TSIgnoredOverload(base, _) =>
-      //       if (!base.typeVars.isEmpty)
-      //         s"  method ${m._1}[${base.typeVars.map((tv) => tv.name).reduceLeft((p, s) => s"$p, $s")}]: ${convert(overload)}" // TODO: add constraints
-      //       else s"${m._1}: ${convert(overload)}"
-      //     case _ => s"${m._1}: ${convert(m._2)}" // other type members
-      //   }
-      // }
       case _ => "" // TODO: deal with private/protected members
     }) :::
       statics.toList.map((s) => s._2.modifier match {
@@ -99,11 +89,6 @@ object Converter {
       else if (typeName === "trait ") s"(${lst.reduceLeft((bd, m) => s"$bd$m")})"
       else s"{\n${lst.reduceLeft((bd, m) => s"$bd$m")}$indent}"
     }
-    // val methods = { // members with independent type parameters, use methods instead
-    //   val lst = allRecs.filter(_.startsWith("  "))
-    //   if (lst.isEmpty) ""
-    //   else "\n" + lst.reduceLeft((bd, m) => s"$bd\n$m")
-    // }
     
     if (typeName === "trait ") body // anonymous interfaces
     else { // named interfaces and classes
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index 129faf354a..caead665dc 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -19,8 +19,8 @@ namespace XX {
   fun f<T>(v0: T, v1: anything): string /* warning: the overload of function f is not supported yet. */
 }
 class WWW() {
-  fun F: T => anything /* warning: the overload of function F is not supported yet. */
+  fun F<T>(v0: T): anything /* warning: the overload of function F is not supported yet. */
 }
 fun baz(): anything /* warning: the overload of function baz is not supported yet. */
-//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|false|)| ||| |(|true|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |(|false|)| ||| |(|true|)|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|(|false|)| ||| |(|true|)|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|v0|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|‹|T|›|(|v0|#:| |T|,| |v1|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|#:| |T| |=>| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> ((false,) | (true,)),) & (((false,) | (true,)) -> unit -> ((false,) | (true,)),); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: (false,) | (true,),) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> (((false,) | (true,),) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> ((((number,) | (false,),) | (true,)) -> string,) & (object -> string,); fun doSome: [] -> (v0: anything,) -> unit; namespace XX(): {fun f: [] -> (v0: T, v1: anything,) -> string}; class WWW() {fun F: [] -> T -> anything}; fun baz: [] -> () -> anything}
+//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|false|)| ||| |(|true|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |(|false|)| ||| |(|true|)|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|(|false|)| ||| |(|true|)|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|v0|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|‹|T|›|(|v0|#:| |T|,| |v1|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|‹|T|›|(|v0|#:| |T|)|#:| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> ((false,) | (true,)),) & (((false,) | (true,)) -> unit -> ((false,) | (true,)),); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: (false,) | (true,),) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> (((false,) | (true,),) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> ((((number,) | (false,),) | (true,)) -> string,) & (object -> string,); fun doSome: [] -> (v0: anything,) -> unit; namespace XX(): {fun f: [] -> (v0: T, v1: anything,) -> string}; class WWW() {fun F: [] -> (v0: T,) -> anything}; fun baz: [] -> () -> anything}

From e916a40ac14012001dd01c243d7c4b67efc37946 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Tue, 20 Sep 2022 09:35:24 +0800
Subject: [PATCH 29/40] Fix parameter names

---
 .../src/main/scala/ts2mls/TSSourceFile.scala  | 16 ++++++----
 .../main/scala/ts2mls/types/Converter.scala   | 11 +++----
 .../src/main/scala/ts2mls/types/TSType.scala  |  5 +--
 ts2mls/js/src/test/diff/Array.d.mls           | 26 +++++++--------
 ts2mls/js/src/test/diff/BasicFunctions.d.mls  | 26 +++++++--------
 ts2mls/js/src/test/diff/ClassMember.d.mls     | 18 +++++------
 ts2mls/js/src/test/diff/Enum.d.mls            |  8 ++---
 ts2mls/js/src/test/diff/Heritage.d.mls        | 10 +++---
 ts2mls/js/src/test/diff/HighOrderFunc.d.mls   | 10 +++---
 ts2mls/js/src/test/diff/InterfaceMember.d.mls | 24 +++++++-------
 ts2mls/js/src/test/diff/Intersection.d.mls    | 22 ++++++-------
 ts2mls/js/src/test/diff/MultiFiles.d.mls      |  8 ++---
 ts2mls/js/src/test/diff/Namespace.d.mls       | 18 +++++------
 ts2mls/js/src/test/diff/Optional.d.mls        | 28 ++++++++--------
 ts2mls/js/src/test/diff/Overload.d.mls        | 32 +++++++++----------
 ts2mls/js/src/test/diff/Tuple.d.mls           | 28 ++++++++--------
 ts2mls/js/src/test/diff/TypeParameter.d.mls   | 26 +++++++--------
 ts2mls/js/src/test/diff/Union.d.mls           | 18 +++++------
 18 files changed, 167 insertions(+), 167 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala b/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
index 6d0be40b12..90fca4398f 100644
--- a/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
@@ -49,12 +49,13 @@ object TSSourceFile {
     )
 
   private def getFunctionType(node: TSNodeObject): TSFunctionType = {
-    val pList = node.parameters.foldLeft(List[TSType]())((lst, p) => lst :+ (
+    val pList = node.parameters.foldLeft(List[TSParameterType]())((lst, p) => (
       // in typescript, you can use `this` to explicitly specifies the callee
       // but it never appears in the final javascript file
-      if (p.symbol.escapedName === "this") TSPrimitiveType("void")
-      else if (p.isOptionalParameter) TSUnionType(getObjectType(p.symbolType), TSPrimitiveType("undefined"))
-      else getObjectType(p.symbolType))
+      if (p.symbol.escapedName === "this") lst
+      else if (p.isOptionalParameter)
+        lst :+ TSParameterType(p.symbol.escapedName, TSUnionType(getObjectType(p.symbolType), TSPrimitiveType("undefined")))
+      else lst :+ TSParameterType(p.symbol.escapedName, getObjectType(p.symbolType)))
     )
     TSFunctionType(pList, getObjectType(node.returnType), getTypeParametes(node))
   }
@@ -110,12 +111,13 @@ object TSSourceFile {
       else mp
     })
 
-  private def getConstructorList(members: TSNodeArray): List[TSType] =
-    members.foldLeft(List[TSType]())((lst, mem) => {
+  private def getConstructorList(members: TSNodeArray): List[TSParameterType] =
+    members.foldLeft(List[TSParameterType]())((lst, mem) => {
       val name = mem.symbol.escapedName
 
       if (name =/= "__constructor") lst
-      else mem.parameters.foldLeft(List[TSType]())((res, p) => res :+ getMemberType(p))
+      else mem.parameters.foldLeft(List[TSParameterType]())((res, p) =>
+        res :+ TSParameterType(p.symbol.escapedName, getMemberType(p)))
     })
 
   private def getInterfacePropertiesType(list: TSNodeArray): Map[String, TSMemberType] =
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index f3a818f791..7044c8315b 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -21,7 +21,7 @@ object Converter {
 
   def generateFunDeclaration(tsType: TSType, name: String)(implicit indent: String = ""): String = tsType match {
     case TSFunctionType(params, res, typeVars) => {
-      val pList = if (params.isEmpty) "" else params.zipWithIndex.map(p => s"v${p._2}: ${convert(p._1)("")}").reduceLeft((r, p) => s"$r, $p")
+      val pList = if (params.isEmpty) "" else params.map(p => s"${convert(p)("")}").reduceLeft((r, p) => s"$r, $p")
       val tpList = if (typeVars.isEmpty) "" else s"<${typeVars.map(p => convert(p)("")).reduceLeft((r, p) => s"$r, $p")}>"
       s"${indent}fun $name$tpList($pList): ${convert(res)("")}"
     }
@@ -34,13 +34,9 @@ object Converter {
     case TSPrimitiveType(typeName) => primitiveName(typeName)
     case TSReferenceType(name) => name
     case TSFunctionType(params, res, _) =>
-      // since functions can be defined by both `def` and `method`, it only returns the type of functions
       if (params.length == 0) s"${primitiveName("void")} => ${convert(res)}"
       else
-        params.foldRight(convert(res))((p, f) => p match {
-          case _: TSFunctionType => s"(${convert(p)}) => $f"
-          case _ => s"${convert(p)} => $f"
-        })
+        params.foldRight(convert(res))((p, f) => s"(${convert(p.tp)}) => $f")
     case TSUnionType(lhs, rhs) => {
       val lres = convert(lhs)
       val rres = convert(rhs)
@@ -61,6 +57,7 @@ object Converter {
       convertRecord(s"class $name", members, typeVars, parents, statics, cons)(indent)
     case TSSubstitutionType(base, applied) => s"${base}<${applied.map((app) => convert(app)).reduceLeft((res, s) => s"$res, $s")}>"
     case overload @ TSIgnoredOverload(base, _) => s"${convert(base)} ${overload.warning}"
+    case TSParameterType(name, tp) => s"${name}: ${convert(tp)}"
   }
 
   private def convertRecord(typeName: String, members: Map[String, TSMemberType], typeVars: List[TSTypeParameter],
@@ -94,7 +91,7 @@ object Converter {
     else { // named interfaces and classes
       val constructor =
         if (constructorList.isEmpty) "()"
-        else s"(${constructorList.zipWithIndex.map(p => s"v${p._2}: ${convert(p._1)("")}").reduceLeft((res, p) => s"$res, $p")})"
+        else s"(${constructorList.map(p => s"${convert(p)("")}").reduceLeft((res, p) => s"$res, $p")})"
 
       val inheritance =
         if (parents.isEmpty) constructor
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala b/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
index fa1746687e..da371b0cf5 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
@@ -6,13 +6,14 @@ case object Private extends TSAccessModifier
 case object Protected extends TSAccessModifier
 
 sealed abstract class TSType
+case class TSParameterType(name: String, val tp: TSType) extends TSType // name: tp
 case class TSMemberType(val base: TSType, val modifier: TSAccessModifier = Public) extends TSType
 case class TSTypeParameter(val name: String, constraint: Option[TSType] = None) extends TSType
 case class TSPrimitiveType(typeName: String) extends TSType
 case class TSReferenceType(name: String) extends TSType
 case object TSEnumType extends TSType
 case class TSTupleType(types: List[TSType]) extends TSType
-case class TSFunctionType(params: List[TSType], res: TSType, val typeVars: List[TSTypeParameter]) extends TSType
+case class TSFunctionType(params: List[TSParameterType], res: TSType, val typeVars: List[TSTypeParameter]) extends TSType
 case class TSArrayType(eleType: TSType) extends TSType
 case class TSSubstitutionType(base: String, applied: List[TSType]) extends TSType
 
@@ -22,7 +23,7 @@ case class TSClassType(
     statics: Map[String, TSMemberType],
     typeVars: List[TSTypeParameter],
     parents: List[TSType],
-    constructor: List[TSType]
+    constructor: List[TSParameterType]
   ) extends TSType
 
 case class TSInterfaceType(
diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls
index 5691fbe475..2feabb0aba 100644
--- a/ts2mls/js/src/test/diff/Array.d.mls
+++ b/ts2mls/js/src/test/diff/Array.d.mls
@@ -1,23 +1,23 @@
 :NewParser
 :ParseOnly
-fun first(v0: MutArray<string>): string
+fun first(x: MutArray<string>): string
 fun getZero3(): MutArray<number>
-fun first2(v0: MutArray<number => number>): number => number
-fun doEs(v0: MutArray<int>): MutArray<int>
+fun first2(fs: MutArray<(number) => number>): (number) => number
+fun doEs(e: MutArray<int>): MutArray<int>
 class C() {}
 trait I() {
   let i: number
 }
-fun doCs(v0: MutArray<C>): MutArray<C>
-fun doIs(v0: MutArray<I>): MutArray<I>
-fun inter<U, T>(v0: MutArray<(U) & (T)>): MutArray<(U) & (T)>
-fun clean(v0: MutArray<(string, number, )>): MutArray<(string, number, )>
-fun translate<T, U>(v0: MutArray<T>): MutArray<U>
-fun uu(v0: MutArray<((number) | (false)) | (true)>): MutArray<((number) | (false)) | (true)>
+fun doCs(c: MutArray<C>): MutArray<C>
+fun doIs(i: MutArray<I>): MutArray<I>
+fun inter<U, T>(x: MutArray<(U) & (T)>): MutArray<(U) & (T)>
+fun clean(x: MutArray<(string, number, )>): MutArray<(string, number, )>
+fun translate<T, U>(x: MutArray<T>): MutArray<U>
+fun uu(x: MutArray<((number) | (false)) | (true)>): MutArray<((number) | (false)) | (true)>
 class Temp<T>() {
   let x: T
 }
-fun ta(v0: MutArray<Temp<(false) | (true)>>): MutArray<Temp<(false) | (true)>>
-fun tat<T>(v0: MutArray<Temp<T>>): MutArray<Temp<T>>
-//│ |#fun| |first|(|v0|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|v0|#:| |MutArray|‹|number| |=>| |number|›|)|#:| |number| |=>| |number|↵|#fun| |doEs|(|v0|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|v0|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|v0|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|v0|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|v0|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|v0|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|v0|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|)|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|v0|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|)|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|↵|#fun| |tat|‹|T|›|(|v0|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|
-//│ Parsed: {fun first: [] -> (v0: MutArray[string],) -> string; fun getZero3: [] -> () -> MutArray[number]; fun first2: [] -> (v0: MutArray[number -> number],) -> number -> number; fun doEs: [] -> (v0: MutArray[int],) -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> (v0: MutArray[C],) -> MutArray[C]; fun doIs: [] -> (v0: MutArray[I],) -> MutArray[I]; fun inter: [] -> (v0: MutArray[(U,) & (T,)],) -> MutArray[(U,) & (T,)]; fun clean: [] -> (v0: MutArray[(string, number,)],) -> MutArray[(string, number,)]; fun translate: [] -> (v0: MutArray[T],) -> MutArray[U]; fun uu: [] -> (v0: MutArray[((number,) | (false,),) | (true,)],) -> MutArray[((number,) | (false,),) | (true,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> (v0: MutArray[Temp[(false,) | (true,)]],) -> MutArray[Temp[(false,) | (true,)]]; fun tat: [] -> (v0: MutArray[Temp[T]],) -> MutArray[Temp[T]]}
+fun ta(ts: MutArray<Temp<(false) | (true)>>): MutArray<Temp<(false) | (true)>>
+fun tat<T>(ts: MutArray<Temp<T>>): MutArray<Temp<T>>
+//│ |#fun| |first|(|x|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|fs|#:| |MutArray|‹|(|number|)| |=>| |number|›|)|#:| |(|number|)| |=>| |number|↵|#fun| |doEs|(|e|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|c|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|i|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|x|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|x|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|x|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|x|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|)|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|ts|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|)|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|↵|#fun| |tat|‹|T|›|(|ts|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|
+//│ Parsed: {fun first: [] -> (x: MutArray[string],) -> string; fun getZero3: [] -> () -> MutArray[number]; fun first2: [] -> (fs: MutArray[number -> number],) -> number -> number; fun doEs: [] -> (e: MutArray[int],) -> MutArray[int]; class C() {}; trait I(): {let i: [] -> number}; fun doCs: [] -> (c: MutArray[C],) -> MutArray[C]; fun doIs: [] -> (i: MutArray[I],) -> MutArray[I]; fun inter: [] -> (x: MutArray[(U,) & (T,)],) -> MutArray[(U,) & (T,)]; fun clean: [] -> (x: MutArray[(string, number,)],) -> MutArray[(string, number,)]; fun translate: [] -> (x: MutArray[T],) -> MutArray[U]; fun uu: [] -> (x: MutArray[((number,) | (false,),) | (true,)],) -> MutArray[((number,) | (false,),) | (true,)]; class Temp[T]() {let x: [] -> T}; fun ta: [] -> (ts: MutArray[Temp[(false,) | (true,)]],) -> MutArray[Temp[(false,) | (true,)]]; fun tat: [] -> (ts: MutArray[Temp[T]],) -> MutArray[Temp[T]]}
diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
index 3bf0b93143..eaf33b9e39 100644
--- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls
+++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls
@@ -1,28 +1,28 @@
 :NewParser
 :ParseOnly
 fun hello(): unit
-fun add(v0: number, v1: number): number
-fun sub(v0: number, v1: number): number
+fun add(x: number, y: number): number
+fun sub(x: number, y: number): number
 fun foo(): number
-fun id(v0: anything): anything
-fun odd(v0: number): (false) | (true)
-fun isnull(v0: anything): (false) | (true)
+fun id(x: anything): anything
+fun odd(x: number): (false) | (true)
+fun isnull(x: anything): (false) | (true)
 fun bar(): anything
-fun nu(v0: null): null
-fun un(v0: undefined): undefined
+fun nu(n: null): null
+fun un(n: undefined): undefined
 fun fail(): nothing
 fun create(): object
-fun pa(v0: number): number
-fun wtf(v0: anything): unit
+fun pa(x: number): number
+fun wtf(x: anything): unit
 class Foooooo() {
   let ooooooo: number
 }
-fun inn(v0: Foooooo): unit
+fun inn(f: Foooooo): unit
 fun out(): Foooooo
 trait Barrrrrrrrr() {
   let rrrrrrr: number
 }
-fun inn2(v0: Barrrrrrrrr): unit
+fun inn2(b: Barrrrrrrrr): unit
 fun out2(): Barrrrrrrrr
-//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |sub|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|v0|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|v0|#:| |number|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |isnull|(|v0|#:| |anything|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|v0|#:| |null|)|#:| |null|↵|#fun| |un|(|v0|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|v0|#:| |number|)|#:| |number|↵|#fun| |wtf|(|v0|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|v0|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|v0|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
-//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (v0: number, v1: number,) -> number; fun sub: [] -> (v0: number, v1: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (v0: anything,) -> anything; fun odd: [] -> (v0: number,) -> ((false,) | (true,)); fun isnull: [] -> (v0: anything,) -> ((false,) | (true,)); fun bar: [] -> () -> anything; fun nu: [] -> (v0: null,) -> null; fun un: [] -> (v0: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (v0: number,) -> number; fun wtf: [] -> (v0: anything,) -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> (v0: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> (v0: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
+//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|x|#:| |number|,| |y|#:| |number|)|#:| |number|↵|#fun| |sub|(|x|#:| |number|,| |y|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|x|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|x|#:| |number|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |isnull|(|x|#:| |anything|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|n|#:| |null|)|#:| |null|↵|#fun| |un|(|n|#:| |undefined|)|#:| |undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|x|#:| |number|)|#:| |number|↵|#fun| |wtf|(|x|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|f|#:| |Foooooo|)|#:| |unit|↵|#fun| |out|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|b|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|
+//│ Parsed: {fun hello: [] -> () -> unit; fun add: [] -> (x: number, y: number,) -> number; fun sub: [] -> (x: number, y: number,) -> number; fun foo: [] -> () -> number; fun id: [] -> (x: anything,) -> anything; fun odd: [] -> (x: number,) -> ((false,) | (true,)); fun isnull: [] -> (x: anything,) -> ((false,) | (true,)); fun bar: [] -> () -> anything; fun nu: [] -> (n: null,) -> null; fun un: [] -> (n: undefined,) -> undefined; fun fail: [] -> () -> nothing; fun create: [] -> () -> object; fun pa: [] -> (x: number,) -> number; fun wtf: [] -> (x: anything,) -> unit; class Foooooo() {let ooooooo: [] -> number}; fun inn: [] -> (f: Foooooo,) -> unit; fun out: [] -> () -> Foooooo; trait Barrrrrrrrr(): {let rrrrrrr: [] -> number}; fun inn2: [] -> (b: Barrrrrrrrr,) -> unit; fun out2: [] -> () -> Barrrrrrrrr}
diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls
index a834b60b76..3030acd69a 100644
--- a/ts2mls/js/src/test/diff/ClassMember.d.mls
+++ b/ts2mls/js/src/test/diff/ClassMember.d.mls
@@ -1,16 +1,16 @@
 :NewParser
 :ParseOnly
-class Student(v0: string, v1: number) {
+class Student(s: string, age: number) {
   let name: string
-  fun isFriend(v0: Student): (false) | (true)
-  fun addScore(v0: string, v1: number): unit
+  fun isFriend(other: Student): (false) | (true)
+  fun addScore(sub: string, score: number): unit
   fun getID(): number
 }
 class Foo<T>() {
-  fun bar(v0: T): unit
+  fun bar(x: T): unit
 }
 class EZ() {
-  fun inc(v0: number): number
+  fun inc(x: number): number
 }
 class Outer() {
   class Inner() {
@@ -18,8 +18,8 @@ class Outer() {
   }
 }
 class TTT<T>() {
-  fun ttt(v0: T): T
-  fun ttt2(v0: T): T
+  fun ttt(x: T): T
+  fun ttt2(x: T): T
 }
-//│ |#class| |Student|(|v0|#:| |string|,| |v1|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|v0|#:| |Student|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |addScore|(|v0|#:| |string|,| |v1|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|v0|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|v0|#:| |T|)|#:| |T|←|↵|}|
-//│ Parsed: {class Student(v0: string, v1: number,) {let name: [] -> string; fun isFriend: [] -> (v0: Student,) -> ((false,) | (true,)); fun addScore: [] -> (v0: string, v1: number,) -> unit; fun getID: [] -> () -> number}; class Foo[T]() {fun bar: [] -> (v0: T,) -> unit}; class EZ() {fun inc: [] -> (v0: number,) -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> (v0: T,) -> T; fun ttt2: [] -> (v0: T,) -> T}}
+//│ |#class| |Student|(|s|#:| |string|,| |age|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|other|#:| |Student|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |addScore|(|sub|#:| |string|,| |score|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|x|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|x|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|x|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {class Student(s: string, age: number,) {let name: [] -> string; fun isFriend: [] -> (other: Student,) -> ((false,) | (true,)); fun addScore: [] -> (sub: string, score: number,) -> unit; fun getID: [] -> () -> number}; class Foo[T]() {fun bar: [] -> (x: T,) -> unit}; class EZ() {fun inc: [] -> (x: number,) -> number}; class Outer() {class Inner() {let a: [] -> number}}; class TTT[T]() {fun ttt: [] -> (x: T,) -> T; fun ttt2: [] -> (x: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls
index b5c36e52a0..d7d3e434f1 100644
--- a/ts2mls/js/src/test/diff/Enum.d.mls
+++ b/ts2mls/js/src/test/diff/Enum.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun pass(v0: int): (false) | (true)
+fun pass(c: int): (false) | (true)
 fun stop(): int
-fun g(v0: int): int
-//│ |#fun| |pass|(|v0|#:| |int|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|v0|#:| |int|)|#:| |int|
-//│ Parsed: {fun pass: [] -> (v0: int,) -> ((false,) | (true,)); fun stop: [] -> () -> int; fun g: [] -> (v0: int,) -> int}
+fun g(x: int): int
+//│ |#fun| |pass|(|c|#:| |int|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|x|#:| |int|)|#:| |int|
+//│ Parsed: {fun pass: [] -> (c: int,) -> ((false,) | (true,)); fun stop: [] -> () -> int; fun g: [] -> (x: int,) -> int}
diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls
index 8e9250a30d..4b45a98f34 100644
--- a/ts2mls/js/src/test/diff/Heritage.d.mls
+++ b/ts2mls/js/src/test/diff/Heritage.d.mls
@@ -5,7 +5,7 @@ class A() {
 }
 class B(): A {}
 class C<T>() {
-  fun set(v0: T): unit
+  fun set(x: T): unit
   fun get(): T
 }
 class D(): C<number> {}
@@ -28,10 +28,10 @@ class Home<T>(): VG<string> {
   let y: T
 }
 trait O<I>() {
-  fun xx(v0: I): I
+  fun xx(x: I): I
 }
 class OR<R>(): O<R> {
-  fun xx(v0: R): R
+  fun xx(x: R): R
 }
 namespace Five {
   class ROTK() {
@@ -40,5 +40,5 @@ namespace Five {
   class Y(): Five'ROTK {}
 }
 class Y(): Five'ROTK {}
-//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|v0|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|v0|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|v0|#:| |R|)|#:| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
-//│ Parsed: {class A() {fun foo: [] -> () -> unit}; class B(): A {}; class C[T]() {fun set: [] -> (v0: T,) -> unit; fun get: [] -> () -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> (false,) | (true,)}; class WuWu(): Wu {let y: [] -> (false,) | (true,)}; trait WuWuWu(): WuWu: {let z: [] -> (false,) | (true,)}; trait Never(): WuWuWu: {fun w: [] -> () -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> (v0: I,) -> I}; class OR[R](): O‹R› {fun xx: [] -> (v0: R,) -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
+//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|x|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|x|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|x|#:| |R|)|#:| |R|←|↵|}|↵|#namespace| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five'ROTK| |{||}|
+//│ Parsed: {class A() {fun foo: [] -> () -> unit}; class B(): A {}; class C[T]() {fun set: [] -> (x: T,) -> unit; fun get: [] -> () -> T}; class D(): C‹number› {}; trait Wu(): {let x: [] -> (false,) | (true,)}; class WuWu(): Wu {let y: [] -> (false,) | (true,)}; trait WuWuWu(): WuWu: {let z: [] -> (false,) | (true,)}; trait Never(): WuWuWu: {fun w: [] -> () -> nothing}; class VG[T]() {let x: [] -> T}; class Home[T](): VG‹string› {let y: [] -> T}; trait O[I](): {fun xx: [] -> (x: I,) -> I}; class OR[R](): O‹R› {fun xx: [] -> (x: R,) -> R}; namespace Five(): {class ROTK() {let wu: [] -> string}; class Y(): Five'ROTK {}}; class Y(): Five'ROTK {}}
diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
index 031845828d..83d941c6a2 100644
--- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
+++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls
@@ -1,7 +1,7 @@
 :NewParser
 :ParseOnly
-fun h1(v0: number => number, v1: number): number
-fun h2(v0: string): unit => string
-fun h3(v0: number => number, v1: number => number): number => number
-//│ |#fun| |h1|(|v0|#:| |number| |=>| |number|,| |v1|#:| |number|)|#:| |number|↵|#fun| |h2|(|v0|#:| |string|)|#:| |unit| |=>| |string|↵|#fun| |h3|(|v0|#:| |number| |=>| |number|,| |v1|#:| |number| |=>| |number|)|#:| |number| |=>| |number|
-//│ Parsed: {fun h1: [] -> (v0: number -> number, v1: number,) -> number; fun h2: [] -> (v0: string,) -> unit -> string; fun h3: [] -> (v0: number -> number, v1: number -> number,) -> number -> number}
+fun h1(inc: (number) => number, num: number): number
+fun h2(hint: string): unit => string
+fun h3(f: (number) => number, g: (number) => number): (number) => number
+//│ |#fun| |h1|(|inc|#:| |(|number|)| |=>| |number|,| |num|#:| |number|)|#:| |number|↵|#fun| |h2|(|hint|#:| |string|)|#:| |unit| |=>| |string|↵|#fun| |h3|(|f|#:| |(|number|)| |=>| |number|,| |g|#:| |(|number|)| |=>| |number|)|#:| |(|number|)| |=>| |number|
+//│ Parsed: {fun h1: [] -> (inc: number -> number, num: number,) -> number; fun h2: [] -> (hint: string,) -> unit -> string; fun h3: [] -> (f: number -> number, g: number -> number,) -> number -> number}
diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
index 312ba2ea79..aebb04425e 100644
--- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls
+++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls
@@ -2,39 +2,39 @@
 :ParseOnly
 trait IFoo() {
   let a: string
-  fun b(v0: number): number
+  fun b(x: number): number
   fun c(): (false) | (true)
-  fun d(v0: string): unit
+  fun d(x: string): unit
 }
 trait II<T>() {
-  fun test(v0: T): number
+  fun test(x: T): number
 }
 fun create(): (v: number,)
-fun get(v0: (t: string,)): string
+fun get(x: (t: string,)): string
 trait IEvent() {
-  fun callback(v0: unit): number => unit
+  fun callback(): (number) => unit
 }
 trait SearchFunc() {
-  fun __call(v0: string, v1: string): (false) | (true)
+  fun __call(source: string, subString: string): (false) | (true)
 }
 trait StringArray() {
-  fun __index(v0: number): string
+  fun __index(index: number): string
 }
 trait Counter() {
-  fun __call(v0: number): string
+  fun __call(start: number): string
   let interval: number
   fun reset(): unit
 }
 trait Simple() {
   let a: number
-  fun b(v0: (false) | (true)): string
+  fun b(x: (false) | (true)): string
 }
 trait Simple2<T>() {
   let abc: T
 }
 trait Next(): Simple {}
 trait TTT<T>() {
-  fun ttt(v0: T): T
+  fun ttt(x: T): T
 }
-//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|v0|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |d|(|v0|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|v0|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|v0|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(|v0|#:| |unit|)|#:| |number| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|v0|#:| |string|,| |v1|#:| |string|)|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|v0|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|v0|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|v0|#:| |T|)|#:| |T|←|↵|}|
-//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (v0: number,) -> number; fun c: [] -> () -> ((false,) | (true,)); fun d: [] -> (v0: string,) -> unit}; trait II[T](): {fun test: [] -> (v0: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (v0: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> (v0: unit,) -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (v0: string, v1: string,) -> ((false,) | (true,))}; trait StringArray(): {fun __index: [] -> (v0: number,) -> string}; trait Counter(): {fun __call: [] -> (v0: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (v0: (false,) | (true,),) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (v0: T,) -> T}}
+//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|x|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |d|(|x|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|x|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|x|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(||)|#:| |(|number|)| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|source|#:| |string|,| |subString|#:| |string|)|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|index|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|start|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|←|↵|}|
+//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (x: number,) -> number; fun c: [] -> () -> ((false,) | (true,)); fun d: [] -> (x: string,) -> unit}; trait II[T](): {fun test: [] -> (x: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (x: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> () -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (source: string, subString: string,) -> ((false,) | (true,))}; trait StringArray(): {fun __index: [] -> (index: number,) -> string}; trait Counter(): {fun __call: [] -> (start: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (x: (false,) | (true,),) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (x: T,) -> T}}
diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls
index c9f7599e87..10181ff2a1 100644
--- a/ts2mls/js/src/test/diff/Intersection.d.mls
+++ b/ts2mls/js/src/test/diff/Intersection.d.mls
@@ -1,21 +1,21 @@
 :NewParser
 :ParseOnly
-fun extend<T, U>(v0: T, v1: U): (T) & (U)
-fun foo<T, U>(v0: (T) & (U)): unit
-fun over(v0: (number => string) & (object => string)): string
+fun extend<T, U>(first: T, second: U): (T) & (U)
+fun foo<T, U>(x: (T) & (U)): unit
+fun over(f: ((number) => string) & ((object) => string)): string
 trait IA() {
   let x: number
 }
 trait IB() {
   let y: number
 }
-fun iii(v0: (IA) & (IB)): (IA) & (IB)
-fun uu<U, V, T, P>(v0: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
-fun iiii<U, T, V>(v0: ((U) & (T)) & (V)): ((U) & (T)) & (V)
-fun arr<U, T>(v0: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
-fun tt<U, T, V>(v0: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
+fun iii(x: (IA) & (IB)): (IA) & (IB)
+fun uu<U, V, T, P>(x: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))
+fun iiii<U, T, V>(x: ((U) & (T)) & (V)): ((U) & (T)) & (V)
+fun arr<U, T>(a: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)
+fun tt<U, T, V>(x: ((U, T, )) & ((V, V, ))): ((U, T, )) & ((V, V, ))
 class A() {}
 class B() {}
-fun inter(v0: (A) & (B)): (A) & (B)
-//│ |#fun| |extend|‹|T|,| |U|›|(|v0|#:| |T|,| |v1|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|‹|T|,| |U|›|(|v0|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|v0|#:| |(|number| |=>| |string|)| |&| |(|object| |=>| |string|)|)|#:| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|(|v0|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|‹|U|,| |V|,| |T|,| |P|›|(|v0|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|‹|U|,| |T|,| |V|›|(|v0|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|‹|U|,| |T|›|(|v0|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|‹|U|,| |T|,| |V|›|(|v0|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|(|v0|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
-//│ Parsed: {fun extend: [] -> (v0: T, v1: U,) -> ((T,) & (U,)); fun foo: [] -> (v0: (T,) & (U,),) -> unit; fun over: [] -> (v0: (number -> string,) & (object -> string,),) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> (v0: (IA,) & (IB,),) -> ((IA,) & (IB,)); fun uu: [] -> (v0: ((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (v0: ((U,) & (T,),) & (V,),) -> (((U,) & (T,),) & (V,)); fun arr: [] -> (v0: (MutArray[U],) & (MutArray[T],),) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (v0: ((U, T,),) & ((V, V,),),) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> (v0: (A,) & (B,),) -> ((A,) & (B,))}
+fun inter(c: (A) & (B)): (A) & (B)
+//│ |#fun| |extend|‹|T|,| |U|›|(|first|#:| |T|,| |second|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|‹|T|,| |U|›|(|x|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|f|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|object|)| |=>| |string|)|)|#:| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|(|x|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|‹|U|,| |V|,| |T|,| |P|›|(|x|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|‹|U|,| |T|,| |V|›|(|x|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|‹|U|,| |T|›|(|a|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|‹|U|,| |T|,| |V|›|(|x|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|(|c|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|
+//│ Parsed: {fun extend: [] -> (first: T, second: U,) -> ((T,) & (U,)); fun foo: [] -> (x: (T,) & (U,),) -> unit; fun over: [] -> (f: (number -> string,) & (object -> string,),) -> string; trait IA(): {let x: [] -> number}; trait IB(): {let y: [] -> number}; fun iii: [] -> (x: (IA,) & (IB,),) -> ((IA,) & (IB,)); fun uu: [] -> (x: ((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),),) -> (((((U,) & (T,),) | ((U,) & (P,),),) | ((V,) & (T,),),) | ((V,) & (P,),)); fun iiii: [] -> (x: ((U,) & (T,),) & (V,),) -> (((U,) & (T,),) & (V,)); fun arr: [] -> (a: (MutArray[U],) & (MutArray[T],),) -> ((MutArray[U],) & (MutArray[T],)); fun tt: [] -> (x: ((U, T,),) & ((V, V,),),) -> (((U, T,),) & ((V, V,),)); class A() {}; class B() {}; fun inter: [] -> (c: (A,) & (B,),) -> ((A,) & (B,))}
diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls
index 7af92a7a38..f5e566f1da 100644
--- a/ts2mls/js/src/test/diff/MultiFiles.d.mls
+++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls
@@ -1,6 +1,6 @@
 :NewParser
 :ParseOnly
-fun multi1(v0: number): number
+fun multi1(x: number): number
 fun multi3(): unit
 class Foo(): Base {}
 trait AnotherBase() {
@@ -11,12 +11,12 @@ namespace N {
   fun g(): unit
   fun h(): unit
 }
-fun multi2(v0: string): string
+fun multi2(x: string): string
 fun multi4(): unit
 trait Base() {
   let a: number
 }
 class AnotherFoo(): AnotherBase {}
 fun multi5(): unit
-//│ |#fun| |multi1|(|v0|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|v0|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit|
-//│ Parsed: {fun multi1: [] -> (v0: number,) -> number; fun multi3: [] -> () -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> () -> unit; fun g: [] -> () -> unit; fun h: [] -> () -> unit}; fun multi2: [] -> (v0: string,) -> string; fun multi4: [] -> () -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> () -> unit}
+//│ |#fun| |multi1|(|x|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#namespace| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|x|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit|
+//│ Parsed: {fun multi1: [] -> (x: number,) -> number; fun multi3: [] -> () -> unit; class Foo(): Base {}; trait AnotherBase(): {let y: [] -> string}; namespace N(): {fun f: [] -> () -> unit; fun g: [] -> () -> unit; fun h: [] -> () -> unit}; fun multi2: [] -> (x: string,) -> string; fun multi4: [] -> () -> unit; trait Base(): {let a: [] -> number}; class AnotherFoo(): AnotherBase {}; fun multi5: [] -> () -> unit}
diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls
index 33cc534960..b70deff220 100644
--- a/ts2mls/js/src/test/diff/Namespace.d.mls
+++ b/ts2mls/js/src/test/diff/Namespace.d.mls
@@ -1,8 +1,8 @@
 :NewParser
 :ParseOnly
 namespace N1 {
-  fun f(v0: anything): number
-  fun ff(v0: anything): number
+  fun f(x: anything): number
+  fun ff(y: anything): number
   class C() {
     fun f(): unit
   }
@@ -10,13 +10,13 @@ namespace N1 {
     fun f(): number
   }
   namespace N2 {
-    fun fff(v0: (false) | (true)): number
-    fun gg(v0: N1'C): N1'C
+    fun fff(x: (false) | (true)): number
+    fun gg(c: N1'C): N1'C
     class BBB(): N1'C {}
   }
 }
 namespace AA {
-  fun f(v0: anything): string
+  fun f(x: anything): string
   class C() {
     fun f(): unit
   }
@@ -26,7 +26,7 @@ namespace AA {
   namespace N2 {
   }
 }
-fun f1(v0: N1'C): N1'C
-fun f2(v0: AA'C): AA'C
-//│ |#namespace| |N1| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |number|↵|#fun| |ff|(|v0|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |number|↵|#fun| |gg|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|v0|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|v0|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|v0|#:| |AA'C|)|#:| |AA'C|
-//│ Parsed: {namespace N1(): {fun f: [] -> (v0: anything,) -> number; fun ff: [] -> (v0: anything,) -> number; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {fun fff: [] -> (v0: (false,) | (true,),) -> number; fun gg: [] -> (v0: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (v0: anything,) -> string; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {}}; fun f1: [] -> (v0: N1'C,) -> N1'C; fun f2: [] -> (v0: AA'C,) -> AA'C}
+fun f1(x: N1'C): N1'C
+fun f2(x: AA'C): AA'C
+//│ |#namespace| |N1| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |number|↵|#fun| |ff|(|y|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|→|#fun| |fff|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |number|↵|#fun| |gg|(|c|#:| |N1'C|)|#:| |N1'C|↵|#class| |BBB|(||)|#:| |N1'C| |{||}|←|↵|}|←|↵|}|↵|#namespace| |AA| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#namespace| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|x|#:| |N1'C|)|#:| |N1'C|↵|#fun| |f2|(|x|#:| |AA'C|)|#:| |AA'C|
+//│ Parsed: {namespace N1(): {fun f: [] -> (x: anything,) -> number; fun ff: [] -> (y: anything,) -> number; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {fun fff: [] -> (x: (false,) | (true,),) -> number; fun gg: [] -> (c: N1'C,) -> N1'C; class BBB(): N1'C {}}}; namespace AA(): {fun f: [] -> (x: anything,) -> string; class C() {fun f: [] -> () -> unit}; trait I(): {fun f: [] -> () -> number}; namespace N2(): {}}; fun f1: [] -> (x: N1'C,) -> N1'C; fun f2: [] -> (x: AA'C,) -> AA'C}
diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls
index 822d3b5625..6622dc8fa5 100644
--- a/ts2mls/js/src/test/diff/Optional.d.mls
+++ b/ts2mls/js/src/test/diff/Optional.d.mls
@@ -1,24 +1,24 @@
 :NewParser
 :ParseOnly
-fun buildName(v0: string, v1: (string) | (undefined)): string
-fun buildName2(v0: string, v1: (string) | (undefined)): string
-fun buildName3(v0: string, v1: MutArray<string>): string
-fun buildName4(v0: string, v1: MutArray<anything>): string
+fun buildName(firstName: string, lastName: (string) | (undefined)): string
+fun buildName2(firstName: string, lastName: (string) | (undefined)): string
+fun buildName3(firstName: string, lastName: MutArray<string>): string
+fun buildName4(firstName: string, lastName: MutArray<anything>): string
 trait SquareConfig() {
   let color: (string) | (undefined)
   let width: (number) | (undefined)
 }
-fun did(v0: number, v1: (number => number) | (undefined)): number
-fun getOrElse(v0: (MutArray<object>) | (undefined)): object
+fun did(x: number, f: ((number) => number) | (undefined)): number
+fun getOrElse(arr: (MutArray<object>) | (undefined)): object
 class ABC() {}
-fun testABC(v0: (ABC) | (undefined)): unit
-fun testSquareConfig(v0: (SquareConfig) | (undefined)): unit
-fun err(v0: ((number, string, )) | (undefined)): unit
-fun toStr(v0: (((number) | (false)) | (true)) | (undefined)): string
-fun boo<T, U>(v0: ((T) & (U)) | (undefined)): unit
+fun testABC(abc: (ABC) | (undefined)): unit
+fun testSquareConfig(conf: (SquareConfig) | (undefined)): unit
+fun err(msg: ((number, string, )) | (undefined)): unit
+fun toStr(x: (((number) | (false)) | (true)) | (undefined)): string
+fun boo<T, U>(x: ((T) & (U)) | (undefined)): unit
 class B<T>() {
   let b: T
 }
-fun boom(v0: (B<nothing>) | (undefined)): anything
-//│ |#fun| |buildName|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|v0|#:| |string|,| |v1|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|v0|#:| |string|,| |v1|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|(|v0|#:| |number|,| |v1|#:| |(|number| |=>| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|v0|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|v0|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|v0|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|v0|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|v0|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|v0|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
-//│ Parsed: {fun buildName: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName2: [] -> (v0: string, v1: (string,) | (undefined,),) -> string; fun buildName3: [] -> (v0: string, v1: MutArray[string],) -> string; fun buildName4: [] -> (v0: string, v1: MutArray[anything],) -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> (v0: number, v1: (number -> number,) | (undefined,),) -> number; fun getOrElse: [] -> (v0: (MutArray[object],) | (undefined,),) -> object; class ABC() {}; fun testABC: [] -> (v0: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (v0: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> (v0: ((number, string,),) | (undefined,),) -> unit; fun toStr: [] -> (v0: (((number,) | (false,),) | (true,),) | (undefined,),) -> string; fun boo: [] -> (v0: ((T,) & (U,),) | (undefined,),) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> (v0: (B[nothing],) | (undefined,),) -> anything}
+fun boom(b: (B<nothing>) | (undefined)): anything
+//│ |#fun| |buildName|(|firstName|#:| |string|,| |lastName|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName2|(|firstName|#:| |string|,| |lastName|#:| |(|string|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |buildName3|(|firstName|#:| |string|,| |lastName|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|firstName|#:| |string|,| |lastName|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|undefined|)|←|↵|}|↵|#fun| |did|(|x|#:| |number|,| |f|#:| |(|(|number|)| |=>| |number|)| ||| |(|undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|arr|#:| |(|MutArray|‹|object|›|)| ||| |(|undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|abc|#:| |(|ABC|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|conf|#:| |(|SquareConfig|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |err|(|msg|#:| |(|(|number|,| |string|,| |)|)| ||| |(|undefined|)|)|#:| |unit|↵|#fun| |toStr|(|x|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| ||| |(|undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|x|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|b|#:| |(|B|‹|nothing|›|)| ||| |(|undefined|)|)|#:| |anything|
+//│ Parsed: {fun buildName: [] -> (firstName: string, lastName: (string,) | (undefined,),) -> string; fun buildName2: [] -> (firstName: string, lastName: (string,) | (undefined,),) -> string; fun buildName3: [] -> (firstName: string, lastName: MutArray[string],) -> string; fun buildName4: [] -> (firstName: string, lastName: MutArray[anything],) -> string; trait SquareConfig(): {let color: [] -> (string,) | (undefined,); let width: [] -> (number,) | (undefined,)}; fun did: [] -> (x: number, f: (number -> number,) | (undefined,),) -> number; fun getOrElse: [] -> (arr: (MutArray[object],) | (undefined,),) -> object; class ABC() {}; fun testABC: [] -> (abc: (ABC,) | (undefined,),) -> unit; fun testSquareConfig: [] -> (conf: (SquareConfig,) | (undefined,),) -> unit; fun err: [] -> (msg: ((number, string,),) | (undefined,),) -> unit; fun toStr: [] -> (x: (((number,) | (false,),) | (true,),) | (undefined,),) -> string; fun boo: [] -> (x: ((T,) & (U,),) | (undefined,),) -> unit; class B[T]() {let b: [] -> T}; fun boom: [] -> (b: (B[nothing],) | (undefined,),) -> anything}
diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls
index caead665dc..0a411a79eb 100644
--- a/ts2mls/js/src/test/diff/Overload.d.mls
+++ b/ts2mls/js/src/test/diff/Overload.d.mls
@@ -1,26 +1,26 @@
 :NewParser
 :ParseOnly
-fun f: (number => string) & (string => string)
+fun f: ((number) => string) & ((string) => string)
 class M() {
-  let foo: (number => string) & (string => string)
+  let foo: ((number) => string) & ((string) => string)
 }
-fun app: ((string => unit) => number => unit) & ((string => unit) => string => unit)
-fun create: (number => unit => (false) | (true)) & ((false) | (true) => unit => (false) | (true))
-fun g0: (MutArray<string> => string) & (MutArray<object> => string)
-fun db: (number => MutArray<number>) & (object => MutArray<number>)
+fun app: (((string) => unit) => (number) => unit) & (((string) => unit) => (string) => unit)
+fun create: ((number) => unit => (false) | (true)) & (((false) | (true)) => unit => (false) | (true))
+fun g0: ((MutArray<string>) => string) & ((MutArray<object>) => string)
+fun db: ((number) => MutArray<number>) & ((object) => MutArray<number>)
 class N() {}
-fun id: (M => unit) & (N => unit)
-fun tst: ((z: number,) => (y: string,)) & ((z: (false) | (true),) => (y: string,))
-fun op: (number => (number) | (undefined) => unit) & (number => ((false) | (true)) | (undefined) => unit)
-fun swap: ((number, string, ) => (number, string, )) & ((string, number, ) => (number, string, ))
-fun u: (((number) | (false)) | (true) => string) & (object => string)
-fun doSome<T, U>(v0: anything): unit /* warning: the overload of function doSome is not supported yet. */
+fun id: ((M) => unit) & ((N) => unit)
+fun tst: (((z: number,)) => (y: string,)) & (((z: (false) | (true),)) => (y: string,))
+fun op: ((number) => ((number) | (undefined)) => unit) & ((number) => (((false) | (true)) | (undefined)) => unit)
+fun swap: (((number, string, )) => (number, string, )) & (((string, number, )) => (number, string, ))
+fun u: ((((number) | (false)) | (true)) => string) & ((object) => string)
+fun doSome<T, U>(x: anything): unit /* warning: the overload of function doSome is not supported yet. */
 namespace XX {
-  fun f<T>(v0: T, v1: anything): string /* warning: the overload of function f is not supported yet. */
+  fun f<T>(x: T, n: anything): string /* warning: the overload of function f is not supported yet. */
 }
 class WWW() {
-  fun F<T>(v0: T): anything /* warning: the overload of function F is not supported yet. */
+  fun F<T>(x: T): anything /* warning: the overload of function F is not supported yet. */
 }
 fun baz(): anything /* warning: the overload of function baz is not supported yet. */
-//│ |#fun| |f|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|number| |=>| |string|)| |&| |(|string| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|string| |=>| |unit|)| |=>| |number| |=>| |unit|)| |&| |(|(|string| |=>| |unit|)| |=>| |string| |=>| |unit|)|↵|#fun| |create|#:| |(|number| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|false|)| ||| |(|true|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|MutArray|‹|string|›| |=>| |string|)| |&| |(|MutArray|‹|object|›| |=>| |string|)|↵|#fun| |db|#:| |(|number| |=>| |MutArray|‹|number|›|)| |&| |(|object| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|M| |=>| |unit|)| |&| |(|N| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|z|#:| |number|,|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|z|#:| |(|false|)| ||| |(|true|)|,|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|number| |=>| |(|number|)| ||| |(|undefined|)| |=>| |unit|)| |&| |(|number| |=>| |(|(|false|)| ||| |(|true|)|)| ||| |(|undefined|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|number|,| |string|,| |)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|string|,| |number|,| |)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)| |=>| |string|)| |&| |(|object| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|v0|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|‹|T|›|(|v0|#:| |T|,| |v1|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|‹|T|›|(|v0|#:| |T|)|#:| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|
-//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> ((false,) | (true,)),) & (((false,) | (true,)) -> unit -> ((false,) | (true,)),); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: (false,) | (true,),) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> (((false,) | (true,),) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> ((((number,) | (false,),) | (true,)) -> string,) & (object -> string,); fun doSome: [] -> (v0: anything,) -> unit; namespace XX(): {fun f: [] -> (v0: T, v1: anything,) -> string}; class WWW() {fun F: [] -> (v0: T,) -> anything}; fun baz: [] -> () -> anything}
+//│ |#fun| |f|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|(|string|)| |=>| |unit|)| |=>| |(|number|)| |=>| |unit|)| |&| |(|(|(|string|)| |=>| |unit|)| |=>| |(|string|)| |=>| |unit|)|↵|#fun| |create|#:| |(|(|number|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|(|false|)| ||| |(|true|)|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|(|MutArray|‹|string|›|)| |=>| |string|)| |&| |(|(|MutArray|‹|object|›|)| |=>| |string|)|↵|#fun| |db|#:| |(|(|number|)| |=>| |MutArray|‹|number|›|)| |&| |(|(|object|)| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|(|M|)| |=>| |unit|)| |&| |(|(|N|)| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|(|z|#:| |number|,|)|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|(|z|#:| |(|false|)| ||| |(|true|)|,|)|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|(|number|)| |=>| |(|(|number|)| ||| |(|undefined|)|)| |=>| |unit|)| |&| |(|(|number|)| |=>| |(|(|(|false|)| ||| |(|true|)|)| ||| |(|undefined|)|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|(|number|,| |string|,| |)|)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|(|string|,| |number|,| |)|)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| |=>| |string|)| |&| |(|(|object|)| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|x|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|‹|T|›|(|x|#:| |T|,| |n|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|‹|T|›|(|x|#:| |T|)|#:| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|
+//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> ((false,) | (true,)),) & (((false,) | (true,)) -> unit -> ((false,) | (true,)),); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: (false,) | (true,),) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> (((false,) | (true,),) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> ((((number,) | (false,),) | (true,)) -> string,) & (object -> string,); fun doSome: [] -> (x: anything,) -> unit; namespace XX(): {fun f: [] -> (x: T, n: anything,) -> string}; class WWW() {fun F: [] -> (x: T,) -> anything}; fun baz: [] -> () -> anything}
diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls
index 3d4709090b..42c5b9ac5d 100644
--- a/ts2mls/js/src/test/diff/Tuple.d.mls
+++ b/ts2mls/js/src/test/diff/Tuple.d.mls
@@ -1,20 +1,20 @@
 :NewParser
 :ParseOnly
-fun key(v0: (string, (false) | (true), )): string
-fun value(v0: (string, (false) | (true), )): (false) | (true)
-fun third(v0: (number, number, number, )): number
-fun vec2(v0: number, v1: number): (number, number, )
-fun twoFunctions(v0: (number => number, number => number, ), v1: number): number
-fun tupleIt(v0: string): (unit => string, )
-fun s(v0: (false) | (true)): ((string) | (number), ((number) | (false)) | (true), )
-fun s2(v0: ((false) | (true), (string) | (number), )): (string) | (number)
-fun ex<T, U>(v0: T, v1: U): (T, U, (T) & (U), )
-fun foo<T, U>(v0: ((T) & (U), )): unit
-fun conv(v0: (y: number,)): ((y: number,), (z: string,), )
+fun key(x: (string, (false) | (true), )): string
+fun value(x: (string, (false) | (true), )): (false) | (true)
+fun third(x: (number, number, number, )): number
+fun vec2(x: number, y: number): (number, number, )
+fun twoFunctions(ff: ((number) => number, (number) => number, ), x: number): number
+fun tupleIt(x: string): (unit => string, )
+fun s(flag: (false) | (true)): ((string) | (number), ((number) | (false)) | (true), )
+fun s2(t: ((false) | (true), (string) | (number), )): (string) | (number)
+fun ex<T, U>(x: T, y: U): (T, U, (T) & (U), )
+fun foo<T, U>(x: ((T) & (U), )): unit
+fun conv(x: (y: number,)): ((y: number,), (z: string,), )
 class A() {
   let x: number
 }
 class B() {}
-fun swap(v0: (A, B, )): (B, A, )
-//│ |#fun| |key|(|v0|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |string|↵|#fun| |value|(|v0|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |third|(|v0|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|v0|#:| |number|,| |v1|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|v0|#:| |(|number| |=>| |number|,| |number| |=>| |number|,| |)|,| |v1|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|v0|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|,| |)|↵|#fun| |s2|(|v0|#:| |(|(|false|)| ||| |(|true|)|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|v0|#:| |T|,| |v1|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|v0|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|v0|#:| |(|y|#:| |number|,|)|)|#:| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|v0|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
-//│ Parsed: {fun key: [] -> (v0: (string, (false,) | (true,),),) -> string; fun value: [] -> (v0: (string, (false,) | (true,),),) -> ((false,) | (true,)); fun third: [] -> (v0: (number, number, number,),) -> number; fun vec2: [] -> (v0: number, v1: number,) -> (number, number,); fun twoFunctions: [] -> (v0: (number -> number, number -> number,), v1: number,) -> number; fun tupleIt: [] -> (v0: string,) -> (unit -> string,); fun s: [] -> (v0: (false,) | (true,),) -> ((string,) | (number,), ((number,) | (false,),) | (true,),); fun s2: [] -> (v0: ((false,) | (true,), (string,) | (number,),),) -> ((string,) | (number,)); fun ex: [] -> (v0: T, v1: U,) -> (T, U, (T,) & (U,),); fun foo: [] -> (v0: ((T,) & (U,),),) -> unit; fun conv: [] -> (v0: (y: number,),) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (v0: (A, B,),) -> (B, A,)}
+fun swap(x: (A, B, )): (B, A, )
+//│ |#fun| |key|(|x|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |string|↵|#fun| |value|(|x|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |third|(|x|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|x|#:| |number|,| |y|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|ff|#:| |(|(|number|)| |=>| |number|,| |(|number|)| |=>| |number|,| |)|,| |x|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|x|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|flag|#:| |(|false|)| ||| |(|true|)|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|,| |)|↵|#fun| |s2|(|t|#:| |(|(|false|)| ||| |(|true|)|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|x|#:| |T|,| |y|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|x|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|x|#:| |(|y|#:| |number|,|)|)|#:| |(|(|y|#:| |number|,|)|,| |(|z|#:| |string|,|)|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|x|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)|
+//│ Parsed: {fun key: [] -> (x: (string, (false,) | (true,),),) -> string; fun value: [] -> (x: (string, (false,) | (true,),),) -> ((false,) | (true,)); fun third: [] -> (x: (number, number, number,),) -> number; fun vec2: [] -> (x: number, y: number,) -> (number, number,); fun twoFunctions: [] -> (ff: (number -> number, number -> number,), x: number,) -> number; fun tupleIt: [] -> (x: string,) -> (unit -> string,); fun s: [] -> (flag: (false,) | (true,),) -> ((string,) | (number,), ((number,) | (false,),) | (true,),); fun s2: [] -> (t: ((false,) | (true,), (string,) | (number,),),) -> ((string,) | (number,)); fun ex: [] -> (x: T, y: U,) -> (T, U, (T,) & (U,),); fun foo: [] -> (x: ((T,) & (U,),),) -> unit; fun conv: [] -> (x: (y: number,),) -> ((y: number,), (z: string,),); class A() {let x: [] -> number}; class B() {}; fun swap: [] -> (x: (A, B,),) -> (B, A,)}
diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls
index 7b97da7b33..0c08091550 100644
--- a/ts2mls/js/src/test/diff/TypeParameter.d.mls
+++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls
@@ -1,29 +1,29 @@
 :NewParser
 :ParseOnly
-fun inc<T>(v0: T): number
+fun inc<T>(x: T): number
 class CC<T>() {
-  fun print(v0: T): unit
+  fun print(s: T): unit
 }
-fun con<U, T>(v0: T): U
+fun con<U, T>(t: T): U
 class Printer<T>() {
-  fun print(v0: T): unit
+  fun print(t: T): unit
 }
-fun setStringPrinter(v0: Printer<string>): unit
+fun setStringPrinter(p: Printer<string>): unit
 fun getStringPrinter(): Printer<string>
-fun foo<T>(v0: Printer<T>, v1: T): T
-fun foo2<T>(v0: Printer<T>, v1: T): T
+fun foo<T>(p: Printer<T>, x: T): T
+fun foo2<T>(p: Printer<T>, x: T): T
 class F<T>() {
   let x: T
-  fun GG<U>(v0: U): T
+  fun GG<U>(y: U): T
 }
 trait I<T>() {
   let x: T
-  fun GG<U>(v0: U): T
+  fun GG<U>(y: U): T
 }
 class FFF<T>() {
-  fun fff(v0: T): unit
+  fun fff(x: T): unit
 }
-fun fff(v0: FFF<string>, v1: string): unit
+fun fff(p: FFF<string>, s: string): unit
 fun getFFF(): FFF<number>
-//│ |#fun| |inc|‹|T|›|(|v0|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|v0|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|v0|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|v0|#:| |Printer|‹|T|›|,| |v1|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|v0|#:| |Printer|‹|T|›|,| |v1|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|v0|#:| |U|)|#:| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|v0|#:| |U|)|#:| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|(|v0|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |fff|(|v0|#:| |FFF|‹|string|›|,| |v1|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
-//│ Parsed: {fun inc: [] -> (v0: T,) -> number; class CC[T]() {fun print: [] -> (v0: T,) -> unit}; fun con: [] -> (v0: T,) -> U; class Printer[T]() {fun print: [] -> (v0: T,) -> unit}; fun setStringPrinter: [] -> (v0: Printer[string],) -> unit; fun getStringPrinter: [] -> () -> Printer[string]; fun foo: [] -> (v0: Printer[T], v1: T,) -> T; fun foo2: [] -> (v0: Printer[T], v1: T,) -> T; class F[T]() {let x: [] -> T; fun GG: [] -> (v0: U,) -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> (v0: U,) -> T}; class FFF[T]() {fun fff: [] -> (v0: T,) -> unit}; fun fff: [] -> (v0: FFF[string], v1: string,) -> unit; fun getFFF: [] -> () -> FFF[number]}
+//│ |#fun| |inc|‹|T|›|(|x|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|(|s|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|t|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|(|t|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|p|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|p|#:| |Printer|‹|T|›|,| |x|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|p|#:| |Printer|‹|T|›|,| |x|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|y|#:| |U|)|#:| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|y|#:| |U|)|#:| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|(|x|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |fff|(|p|#:| |FFF|‹|string|›|,| |s|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|
+//│ Parsed: {fun inc: [] -> (x: T,) -> number; class CC[T]() {fun print: [] -> (s: T,) -> unit}; fun con: [] -> (t: T,) -> U; class Printer[T]() {fun print: [] -> (t: T,) -> unit}; fun setStringPrinter: [] -> (p: Printer[string],) -> unit; fun getStringPrinter: [] -> () -> Printer[string]; fun foo: [] -> (p: Printer[T], x: T,) -> T; fun foo2: [] -> (p: Printer[T], x: T,) -> T; class F[T]() {let x: [] -> T; fun GG: [] -> (y: U,) -> T}; trait I[T](): {let x: [] -> T; fun GG: [] -> (y: U,) -> T}; class FFF[T]() {fun fff: [] -> (x: T,) -> unit}; fun fff: [] -> (p: FFF[string], s: string,) -> unit; fun getFFF: [] -> () -> FFF[number]}
diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls
index 2d01aa7aa6..7d1fc49b6e 100644
--- a/ts2mls/js/src/test/diff/Union.d.mls
+++ b/ts2mls/js/src/test/diff/Union.d.mls
@@ -1,11 +1,11 @@
 :NewParser
 :ParseOnly
-fun getString(v0: (((string) | (number)) | (false)) | (true)): string
-fun test(v0: (false) | (true)): (string) | (number)
-fun run(v0: (number => number) | (number => string)): anything
-fun get(v0: (MutArray<number>) | (MutArray<string>)): unit
-fun get2(v0: ((string, string, )) | ((number, string, ))): string
-fun typeVar<T, U>(v0: (T) | (U)): (T) | (U)
-fun uuuu(v0: (((string) | (number)) | (false)) | (true)): (((string) | (number)) | (false)) | (true)
-//│ |#fun| |getString|(|v0|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |string|↵|#fun| |test|(|v0|#:| |(|false|)| ||| |(|true|)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|v0|#:| |(|number| |=>| |number|)| ||| |(|number| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|v0|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|v0|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|v0|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|v0|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|
-//│ Parsed: {fun getString: [] -> (v0: (((string,) | (number,),) | (false,),) | (true,),) -> string; fun test: [] -> (v0: (false,) | (true,),) -> ((string,) | (number,)); fun run: [] -> (v0: (number -> number,) | (number -> string,),) -> anything; fun get: [] -> (v0: (MutArray[number],) | (MutArray[string],),) -> unit; fun get2: [] -> (v0: ((string, string,),) | ((number, string,),),) -> string; fun typeVar: [] -> (v0: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (v0: (((string,) | (number,),) | (false,),) | (true,),) -> ((((string,) | (number,),) | (false,),) | (true,))}
+fun getString(x: (((string) | (number)) | (false)) | (true)): string
+fun test(x: (false) | (true)): (string) | (number)
+fun run(f: ((number) => number) | ((number) => string)): anything
+fun get(arr: (MutArray<number>) | (MutArray<string>)): unit
+fun get2(t: ((string, string, )) | ((number, string, ))): string
+fun typeVar<T, U>(x: (T) | (U)): (T) | (U)
+fun uuuu(x: (((string) | (number)) | (false)) | (true)): (((string) | (number)) | (false)) | (true)
+//│ |#fun| |getString|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |string|↵|#fun| |test|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|f|#:| |(|(|number|)| |=>| |number|)| ||| |(|(|number|)| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|arr|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|t|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|x|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|
+//│ Parsed: {fun getString: [] -> (x: (((string,) | (number,),) | (false,),) | (true,),) -> string; fun test: [] -> (x: (false,) | (true,),) -> ((string,) | (number,)); fun run: [] -> (f: (number -> number,) | (number -> string,),) -> anything; fun get: [] -> (arr: (MutArray[number],) | (MutArray[string],),) -> unit; fun get2: [] -> (t: ((string, string,),) | ((number, string,),),) -> string; fun typeVar: [] -> (x: (T,) | (U,),) -> ((T,) | (U,)); fun uuuu: [] -> (x: (((string,) | (number,),) | (false,),) | (true,),) -> ((((string,) | (number,),) | (false,),) | (true,))}

From 5fe42716d0844cd5a28f9227038aee7fbf583e2c Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 21 Sep 2022 12:19:26 +0800
Subject: [PATCH 30/40] Refactor

---
 shared/src/main/scala/mlscript/JSBackend.scala | 2 +-
 shared/src/main/scala/mlscript/MLParser.scala  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/shared/src/main/scala/mlscript/JSBackend.scala b/shared/src/main/scala/mlscript/JSBackend.scala
index 2172884e24..55d9dcc0d8 100644
--- a/shared/src/main/scala/mlscript/JSBackend.scala
+++ b/shared/src/main/scala/mlscript/JSBackend.scala
@@ -459,7 +459,7 @@ class JSBackend {
         traits += topLevelScope.declareTrait(name, tparams map { _.name }, body, methods)
       case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _) =>
         classes += topLevelScope.declareClass(name, tparams map { _.name }, baseType, members)
-      case TypeDef(Nms, TypeName(name), _, _, _, members, _) => throw CodeGenError("Namespaces are not supported yet.") // TODO: deal with namespaces
+      case TypeDef(Nms, _, _, _, _, _, _) => throw CodeGenError("Namespaces are not supported yet.")
     }
     (traits.toList, classes.toList)
   }
diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala
index a7f5f70841..7f2282a0e3 100644
--- a/shared/src/main/scala/mlscript/MLParser.scala
+++ b/shared/src/main/scala/mlscript/MLParser.scala
@@ -204,7 +204,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {
           ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil)
       }
       case (k @ Als, id, ts) => "=" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil))
-      case (k @ Nms, id, _) => "=" ~ ty map (bod => TypeDef(k, id, Nil, bod, Nil, Nil, Nil)) // TODO: deal with namespaces
+      case (k @ Nms, id, _) => "=" ~ ty map (bod => TypeDef(k, id, Nil, bod, Nil, Nil, Nil))
     })
   def tyParams[p: P]: P[Ls[TypeName]] =
     ("[" ~ tyName.rep(0, ",") ~ "]").?.map(_.toList.flatten)

From b8445db39e3aa9f60251d839a3479f9b76730f4a Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 21 Sep 2022 12:23:25 +0800
Subject: [PATCH 31/40] Refactor

---
 shared/src/main/scala/mlscript/TyperDatatypes.scala | 2 +-
 shared/src/main/scala/mlscript/codegen/Scope.scala  | 4 ++--
 shared/src/main/scala/mlscript/helpers.scala        | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala
index 22b7845765..35836b7be9 100644
--- a/shared/src/main/scala/mlscript/TyperDatatypes.scala
+++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala
@@ -234,7 +234,7 @@ abstract class TyperDatatypes extends TyperHelpers { self: Typer =>
         else TopType
       subst(td.kind match {
         case Als => td.bodyTy
-        case Nms => td.bodyTy // TODO: deal with namespaces
+        case Nms => td.bodyTy
         case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
         case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
       }, td.targs.lazyZip(targs).toMap) //.withProv(prov)
diff --git a/shared/src/main/scala/mlscript/codegen/Scope.scala b/shared/src/main/scala/mlscript/codegen/Scope.scala
index 227ddd7e5e..001124f178 100644
--- a/shared/src/main/scala/mlscript/codegen/Scope.scala
+++ b/shared/src/main/scala/mlscript/codegen/Scope.scala
@@ -200,8 +200,8 @@ class Scope(name: Str, enclosing: Opt[Scope]) {
       declareTrait(name, tparams map { _.name }, body, mthdDefs)
     case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _) =>
       declareClass(name, tparams map { _.name }, baseType, members)
-    case TypeDef(Nms, TypeName(name), _, body, _, _, _) =>
-      throw CodeGenError("Namespaces are not supported yet.") // TODO: deal with namespaces
+    case TypeDef(Nms, _, _, _, _, _, _) =>
+      throw CodeGenError("Namespaces are not supported yet.")
   }
 
   def declareClass(
diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala
index d5adbcb091..04b6b682d4 100644
--- a/shared/src/main/scala/mlscript/helpers.scala
+++ b/shared/src/main/scala/mlscript/helpers.scala
@@ -436,7 +436,7 @@ trait TermImpl extends StatementImpl { self: Term =>
     // TODO:
     // case Rcd(fields) => ???
     // case Sel(receiver, fieldName) => ???
-    // case Let(isRec, name, rhs, body) => 
+    // case Let(isRec, name, rhs, body) => ???
     // case Blk(stmts) => ???
     // case Bra(rcd, trm) => ???
     // case Asc(trm, ty) => ???

From d1d3ca1afe48eb60fef3a67c0491ae751cefe8ca Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 21 Sep 2022 14:05:37 +0800
Subject: [PATCH 32/40] Refactor

---
 shared/src/main/scala/mlscript/MLParser.scala  | 2 +-
 shared/src/main/scala/mlscript/NewLexer.scala  | 8 ++++----
 shared/src/main/scala/mlscript/NewParser.scala | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala
index 7f2282a0e3..50922c38c1 100644
--- a/shared/src/main/scala/mlscript/MLParser.scala
+++ b/shared/src/main/scala/mlscript/MLParser.scala
@@ -204,7 +204,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {
           ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil)
       }
       case (k @ Als, id, ts) => "=" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil))
-      case (k @ Nms, id, _) => "=" ~ ty map (bod => TypeDef(k, id, Nil, bod, Nil, Nil, Nil))
+      case (k @ Nms, id, _) => throw new Exception("Namespaces are not supported yet.")
     })
   def tyParams[p: P]: P[Ls[TypeName]] =
     ("[" ~ tyName.rep(0, ",") ~ "]").?.map(_.toList.flatten)
diff --git a/shared/src/main/scala/mlscript/NewLexer.scala b/shared/src/main/scala/mlscript/NewLexer.scala
index 11d590e6b6..e887daa815 100644
--- a/shared/src/main/scala/mlscript/NewLexer.scala
+++ b/shared/src/main/scala/mlscript/NewLexer.scala
@@ -84,14 +84,14 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
         val (txt, k) =
           takeWhile(j)(c => c =/= '\n')
         go(k, COMMENT(txt))
-      case '/' if bytes.lift(i + 1).contains('*') =>
+      case '/' if bytes.lift(i + 1).contains('*') => // multiple-line comment
         val j = i + 2
         var prev1 = '/'; var prev2 = '*'
         val (txt, k) =
           takeWhile(j)(c => {
-            val r = prev1 =/= '*' || prev2 =/= '/'
+            val res = prev1 =/= '*' || prev2 =/= '/'
             prev1 = prev2; prev2 = c
-            r
+            res
           })
         go(k, COMMENT(txt.dropRight(2)))
       case BracketKind(Left(k)) => go(i + 1, OPEN_BRACKET(k))
@@ -130,7 +130,7 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
           go(k, SELECT(name))
         }
         else if (c === '>' && n.length > 1 && n.foldLeft(true)((r, i) => r && (i === c)))
-          go(i + 1, IDENT(">", true))
+          go(i + 1, IDENT(">", true)) // split  `>>` to `>` and `>` so that code like `A<B<C>>` can be parsed correctly
         else go(j, if (isSymKeyword.contains(n)) KEYWORD(n) else IDENT(n, true))
       case _ if isDigit(c) =>
         val (str, j) = takeWhile(i)(isDigit)
diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala
index 0c1cf9d7df..b80439a8b2 100644
--- a/shared/src/main/scala/mlscript/NewParser.scala
+++ b/shared/src/main/scala/mlscript/NewParser.scala
@@ -311,7 +311,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
                 (Var("<error>").withLoc(curLoc.map(_.left)), false)
             }
             foundErr || !success pipe { implicit fe =>
-              val tparams = yeetSpaces match {
+              val tparams = if (kwStr === "let") Ls[TypeName]() else yeetSpaces match {
                 case (br @ BRACKETS(Angle, toks), loc) :: _ =>
                   consume
                   val ts = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map {

From 58fdeae3b5b99a739c0f45c42412e93d65b6b1e5 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 21 Sep 2022 14:14:56 +0800
Subject: [PATCH 33/40] Refactor

---
 shared/src/main/scala/mlscript/TypeDefs.scala       | 4 +++-
 shared/src/main/scala/mlscript/TyperDatatypes.scala | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/shared/src/main/scala/mlscript/TypeDefs.scala b/shared/src/main/scala/mlscript/TypeDefs.scala
index 2db345f048..f691032ad6 100644
--- a/shared/src/main/scala/mlscript/TypeDefs.scala
+++ b/shared/src/main/scala/mlscript/TypeDefs.scala
@@ -227,7 +227,9 @@ class TypeDefs extends NuTypeDefs { self: Typer =>
         
         val rightParents = td.kind match {
           case Als => checkCycle(td.bodyTy)(Set.single(L(td.nme)))
-          case Nms => checkCycle(td.bodyTy)(Set.single(L(td.nme)))
+          case Nms =>
+            err(msg"a namespace cannot inherit from others", prov.loco)
+            false
           case k: ObjDefKind =>
             val parentsClasses = MutSet.empty[TypeRef]
             def checkParents(ty: SimpleType): Bool = ty match {
diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala
index 35836b7be9..11b9ef5f54 100644
--- a/shared/src/main/scala/mlscript/TyperDatatypes.scala
+++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala
@@ -234,7 +234,7 @@ abstract class TyperDatatypes extends TyperHelpers { self: Typer =>
         else TopType
       subst(td.kind match {
         case Als => td.bodyTy
-        case Nms => td.bodyTy
+        case Nms => throw new Exception("Namespaces are not supported yet.")
         case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
         case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
       }, td.targs.lazyZip(targs).toMap) //.withProv(prov)

From 6bcd284b02eba852a85e7da29cc54b4071bfb309 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 21 Sep 2022 14:25:33 +0800
Subject: [PATCH 34/40] Clean converter

---
 .../js/src/main/scala/ts2mls/types/Converter.scala | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 7044c8315b..0b64b711ee 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -1,7 +1,6 @@
 package ts2mls.types
 
 import mlscript.utils._
-import scala.runtime.Statics
 
 object Converter {
   private val primitiveName = Map[String, String](
@@ -15,8 +14,8 @@ object Converter {
     "undefined" -> "undefined",
     "never" -> "nothing",
     "object" -> "object",
-    "true" -> "true", // will not appear individually
-    "false" -> "false" // will not appear individually
+    "true" -> "true",
+    "false" -> "false"
   )
 
   def generateFunDeclaration(tsType: TSType, name: String)(implicit indent: String = ""): String = tsType match {
@@ -37,14 +36,7 @@ object Converter {
       if (params.length == 0) s"${primitiveName("void")} => ${convert(res)}"
       else
         params.foldRight(convert(res))((p, f) => s"(${convert(p.tp)}) => $f")
-    case TSUnionType(lhs, rhs) => {
-      val lres = convert(lhs)
-      val rres = convert(rhs)
-
-      if (lres.isEmpty()) rres
-      else if (rres.isEmpty()) lres
-      else s"($lres) | ($rres)"
-    }
+    case TSUnionType(lhs, rhs) => s"(${convert(lhs)}) | (${convert(rhs)})"
     case TSIntersectionType(lhs, rhs) => s"(${convert(lhs)}) & (${convert(rhs)})"
     case TSTypeParameter(name, _) => name // constraints should be translated where the type parameters were created rather than be used
     case TSTupleType(lst) => s"(${lst.foldLeft("")((p, t) => s"$p${convert(t)}, ")})"

From 70dde71d01668b83782e0f25e52b6e014d4a9823 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Wed, 21 Sep 2022 14:29:18 +0800
Subject: [PATCH 35/40] Add comments

---
 ts2mls/js/src/main/scala/ts2mls/types/Converter.scala | 2 +-
 ts2mls/js/src/main/scala/ts2mls/types/TSType.scala    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 0b64b711ee..28389f7c2d 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -69,7 +69,7 @@ object Converter {
           case _: TSClassType => convert(s._2)(indent + "  ") + "\n"
           case _ => "" // TODO: deal with other static type
         }
-        case _ => "" // TODO: deal with private/protected members
+        case _ => "" // TODO: deal with private/protected static members
       })
 
     val body = { // members without independent type parameters, translate them directly
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala b/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
index da371b0cf5..113cc97da7 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
@@ -6,7 +6,7 @@ case object Private extends TSAccessModifier
 case object Protected extends TSAccessModifier
 
 sealed abstract class TSType
-case class TSParameterType(name: String, val tp: TSType) extends TSType // name: tp
+case class TSParameterType(name: String, val tp: TSType) extends TSType // record both parameter's name and parameter's type
 case class TSMemberType(val base: TSType, val modifier: TSAccessModifier = Public) extends TSType
 case class TSTypeParameter(val name: String, constraint: Option[TSType] = None) extends TSType
 case class TSPrimitiveType(typeName: String) extends TSType

From d652e7ee33a924518ccc5851782e730ca6a0ddc1 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Mon, 26 Sep 2022 10:13:44 +0800
Subject: [PATCH 36/40] Fix multiple angles in bracket function

---
 shared/src/main/scala/mlscript/NewLexer.scala | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/shared/src/main/scala/mlscript/NewLexer.scala b/shared/src/main/scala/mlscript/NewLexer.scala
index e887daa815..d2d54cf64f 100644
--- a/shared/src/main/scala/mlscript/NewLexer.scala
+++ b/shared/src/main/scala/mlscript/NewLexer.scala
@@ -129,8 +129,6 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
           val (name, k) = takeWhile(j)(isIdentChar)
           go(k, SELECT(name))
         }
-        else if (c === '>' && n.length > 1 && n.foldLeft(true)((r, i) => r && (i === c)))
-          go(i + 1, IDENT(">", true)) // split  `>>` to `>` and `>` so that code like `A<B<C>>` can be parsed correctly
         else go(j, if (isSymKeyword.contains(n)) KEYWORD(n) else IDENT(n, true))
       case _ if isDigit(c) =>
         val (str, j) = takeWhile(i)(isDigit)
@@ -192,6 +190,12 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
           case _ => false
         }) =>
           go(CLOSE_BRACKET(Angle) -> loc :: rest, false, stack, acc)
+        case (IDENT(id, true), loc) :: rest
+        if (canStartAngles && id.forall(_ == '>') && id.length > 1 && (stack match {
+          case ((Angle, _), _) :: _ => true
+          case _ => false
+        })) => // split  `>>` to `>` and `>` so that code like `A<B<C>>` can be parsed correctly
+          go((CLOSE_BRACKET(Angle) -> loc.left) :: (IDENT(id.drop(1), true) -> loc) :: rest, false, stack, acc)
         case ((tk @ IDENT(">", true), loc)) :: rest if canStartAngles =>
           raise(WarningReport(msg"This looks like an angle bracket, but it does not close any angle bracket section" -> S(loc) ::
             msg"Add spaces around it if you intended to use `<` as an operator" -> N :: Nil, source = Parsing))

From 0a62009601499f71e0f4dbadcf9433e3d4a43c21 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 29 Sep 2022 17:25:04 +0800
Subject: [PATCH 37/40] Use assert and require

---
 shared/src/main/scala/mlscript/MLParser.scala         | 2 +-
 shared/src/main/scala/mlscript/TyperDatatypes.scala   | 2 +-
 ts2mls/js/src/main/scala/ts2mls/types/Converter.scala | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala
index 9c2e052060..4ce1d41fab 100644
--- a/shared/src/main/scala/mlscript/MLParser.scala
+++ b/shared/src/main/scala/mlscript/MLParser.scala
@@ -204,7 +204,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {
           ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil)
       }
       case (k @ Als, id, ts) => "=" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil))
-      case (k @ Nms, id, _) => throw new Exception("Namespaces are not supported yet.")
+      case (k @ Nms, _, _) => assert(false, "Namespaces are not supported yet."); null
     })
   def tyParams[p: P]: P[Ls[TypeName]] =
     ("[" ~ tyName.rep(0, ",") ~ "]").?.map(_.toList.flatten)
diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala
index 59e98c51f1..7ff874eb6e 100644
--- a/shared/src/main/scala/mlscript/TyperDatatypes.scala
+++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala
@@ -234,7 +234,7 @@ abstract class TyperDatatypes extends TyperHelpers { self: Typer =>
         else TopType
       subst(td.kind match {
         case Als => td.bodyTy
-        case Nms => throw new Exception("Namespaces are not supported yet.")
+        case Nms => assert(false, "Namespaces are not supported yet."); td.bodyTy
         case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
         case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
       }, td.targs.lazyZip(targs).toMap) //.withProv(prov)
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 28389f7c2d..87573ccbb2 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -26,7 +26,7 @@ object Converter {
     }
     case overload @ TSIgnoredOverload(base, _) => s"${generateFunDeclaration(base, name)} ${overload.warning}"
     case inter: TSIntersectionType => s"${indent}fun ${name}: ${Converter.convert(inter)}"
-    case _ => throw new Exception("non-function type is not allowed.")
+    case _ => require(false, "non-function type is not allowed."); ""
   }
 
   def convert(tsType: TSType)(implicit indent: String = ""): String = tsType match {

From 3e23dae52a0091be1de4b2f95635cd53fa8cd99d Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 29 Sep 2022 17:53:04 +0800
Subject: [PATCH 38/40] Revert

---
 shared/src/main/scala/mlscript/MLParser.scala         | 2 +-
 shared/src/main/scala/mlscript/TyperDatatypes.scala   | 2 +-
 ts2mls/js/src/main/scala/ts2mls/types/Converter.scala | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala
index 4ce1d41fab..eb9dba894b 100644
--- a/shared/src/main/scala/mlscript/MLParser.scala
+++ b/shared/src/main/scala/mlscript/MLParser.scala
@@ -204,7 +204,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {
           ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil)
       }
       case (k @ Als, id, ts) => "=" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil))
-      case (k @ Nms, _, _) => assert(false, "Namespaces are not supported yet."); null
+      case (k @ Nms, _, _) => throw new Exception("Namespaces are not supported yet.")
     })
   def tyParams[p: P]: P[Ls[TypeName]] =
     ("[" ~ tyName.rep(0, ",") ~ "]").?.map(_.toList.flatten)
diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala
index 7ff874eb6e..59e98c51f1 100644
--- a/shared/src/main/scala/mlscript/TyperDatatypes.scala
+++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala
@@ -234,7 +234,7 @@ abstract class TyperDatatypes extends TyperHelpers { self: Typer =>
         else TopType
       subst(td.kind match {
         case Als => td.bodyTy
-        case Nms => assert(false, "Namespaces are not supported yet."); td.bodyTy
+        case Nms => throw new Exception("Namespaces are not supported yet.")
         case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
         case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
       }, td.targs.lazyZip(targs).toMap) //.withProv(prov)
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 87573ccbb2..28389f7c2d 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -26,7 +26,7 @@ object Converter {
     }
     case overload @ TSIgnoredOverload(base, _) => s"${generateFunDeclaration(base, name)} ${overload.warning}"
     case inter: TSIntersectionType => s"${indent}fun ${name}: ${Converter.convert(inter)}"
-    case _ => require(false, "non-function type is not allowed."); ""
+    case _ => throw new Exception("non-function type is not allowed.")
   }
 
   def convert(tsType: TSType)(implicit indent: String = ""): String = tsType match {

From 0f6ee200bd30cfd14134614b279e2432742ecab0 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 29 Sep 2022 17:54:50 +0800
Subject: [PATCH 39/40] Use AssertionError instead

---
 shared/src/main/scala/mlscript/MLParser.scala         | 2 +-
 shared/src/main/scala/mlscript/TyperDatatypes.scala   | 2 +-
 ts2mls/js/src/main/scala/ts2mls/types/Converter.scala | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala
index eb9dba894b..3dd8a5f509 100644
--- a/shared/src/main/scala/mlscript/MLParser.scala
+++ b/shared/src/main/scala/mlscript/MLParser.scala
@@ -204,7 +204,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {
           ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil)
       }
       case (k @ Als, id, ts) => "=" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil))
-      case (k @ Nms, _, _) => throw new Exception("Namespaces are not supported yet.")
+      case (k @ Nms, _, _) => throw new AssertionError("Namespaces are not supported yet.")
     })
   def tyParams[p: P]: P[Ls[TypeName]] =
     ("[" ~ tyName.rep(0, ",") ~ "]").?.map(_.toList.flatten)
diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala
index 59e98c51f1..4f93642a2d 100644
--- a/shared/src/main/scala/mlscript/TyperDatatypes.scala
+++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala
@@ -234,7 +234,7 @@ abstract class TyperDatatypes extends TyperHelpers { self: Typer =>
         else TopType
       subst(td.kind match {
         case Als => td.bodyTy
-        case Nms => throw new Exception("Namespaces are not supported yet.")
+        case Nms => throw new AssertionError("Namespaces are not supported yet.")
         case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
         case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
       }, td.targs.lazyZip(targs).toMap) //.withProv(prov)
diff --git a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
index 28389f7c2d..1cb716c6a0 100644
--- a/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
+++ b/ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
@@ -26,7 +26,7 @@ object Converter {
     }
     case overload @ TSIgnoredOverload(base, _) => s"${generateFunDeclaration(base, name)} ${overload.warning}"
     case inter: TSIntersectionType => s"${indent}fun ${name}: ${Converter.convert(inter)}"
-    case _ => throw new Exception("non-function type is not allowed.")
+    case _ => throw new AssertionError("non-function type is not allowed.")
   }
 
   def convert(tsType: TSType)(implicit indent: String = ""): String = tsType match {

From 765c9ae7c22eafb490c45fa42ab9c2c63ec31716 Mon Sep 17 00:00:00 2001
From: NeilKleistGao <neilkleist@gmail.com>
Date: Thu, 29 Sep 2022 18:20:40 +0800
Subject: [PATCH 40/40] Use NotImplementedError instead

---
 shared/src/main/scala/mlscript/MLParser.scala       | 2 +-
 shared/src/main/scala/mlscript/TyperDatatypes.scala | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala
index 3dd8a5f509..981438b3e4 100644
--- a/shared/src/main/scala/mlscript/MLParser.scala
+++ b/shared/src/main/scala/mlscript/MLParser.scala
@@ -204,7 +204,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {
           ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil)
       }
       case (k @ Als, id, ts) => "=" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil))
-      case (k @ Nms, _, _) => throw new AssertionError("Namespaces are not supported yet.")
+      case (k @ Nms, _, _) => throw new NotImplementedError("Namespaces are not supported yet.")
     })
   def tyParams[p: P]: P[Ls[TypeName]] =
     ("[" ~ tyName.rep(0, ",") ~ "]").?.map(_.toList.flatten)
diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala
index 4f93642a2d..099e4f76f0 100644
--- a/shared/src/main/scala/mlscript/TyperDatatypes.scala
+++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala
@@ -234,7 +234,7 @@ abstract class TyperDatatypes extends TyperHelpers { self: Typer =>
         else TopType
       subst(td.kind match {
         case Als => td.bodyTy
-        case Nms => throw new AssertionError("Namespaces are not supported yet.")
+        case Nms => throw new NotImplementedError("Namespaces are not supported yet.")
         case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
         case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags
       }, td.targs.lazyZip(targs).toMap) //.withProv(prov)