diff --git a/samples/keyof.ts b/samples/keyof.ts new file mode 100644 index 00000000..b61de4c9 --- /dev/null +++ b/samples/keyof.ts @@ -0,0 +1,28 @@ +// copy example from https://github.com/Microsoft/TypeScript/pull/11929 +interface Thing { + name: string; + width: number; + height: number; + inStock: boolean; +} + +type K1 = keyof Thing; // "name" | "width" | "height" | "inStock" +type K2 = keyof Thing[]; // "length" | "push" | "pop" | "concat" | ... +type K3 = keyof { [x: string]: Thing }; // string + +type P1 = Thing["name"]; // string +type P2 = Thing["width" | "height"]; // number +type P3 = Thing["name" | "inStock"]; // string | boolean +type P4 = string["charAt"]; // (pos: number) => string +type P5 = string[]["push"]; // (...items: string[]) => number + +// following line will work after merged https://github.com/sjrd/scala-js-ts-importer/pull/47 +// type P6 = string[][0]; // string + +// extract example from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/lodash/index.d.ts +interface LoDashStatic { + at( + object: T | null | undefined, + ...props: Array + ): Array; +} diff --git a/samples/keyof.ts.scala b/samples/keyof.ts.scala new file mode 100644 index 00000000..f5242c9b --- /dev/null +++ b/samples/keyof.ts.scala @@ -0,0 +1,34 @@ + +import scala.scalajs.js +import js.annotation._ +import js.| + +package keyof { + +@js.native +trait Thing extends js.Object { + var name: String = js.native + var width: Double = js.native + var height: Double = js.native + var inStock: Boolean = js.native +} + +@js.native +trait LoDashStatic extends js.Object { + def at[T](`object`: T | Null | Unit, props: String*): js.Array[js.Any] = js.native +} + +@js.native +@JSGlobalScope +object Keyof extends js.Object { + type K1 = String + type K2 = String + type K3 = String + type P1 = js.Any + type P2 = js.Any + type P3 = js.Any + type P4 = js.Any + type P5 = js.Any +} + +} diff --git a/src/main/scala/org/scalajs/tools/tsimporter/Importer.scala b/src/main/scala/org/scalajs/tools/tsimporter/Importer.scala index b63fa339..e0023eac 100644 --- a/src/main/scala/org/scalajs/tools/tsimporter/Importer.scala +++ b/src/main/scala/org/scalajs/tools/tsimporter/Importer.scala @@ -330,6 +330,9 @@ class Importer(val output: java.io.PrintWriter) { case RepeatedType(underlying) => TypeRef(Name.REPEATED, List(typeToScala(underlying))) + case IndexedQueryType(_) => + TypeRef.String + case PolymorphicThisType => TypeRef.This diff --git a/src/main/scala/org/scalajs/tools/tsimporter/Trees.scala b/src/main/scala/org/scalajs/tools/tsimporter/Trees.scala index d4ebb976..8f50e550 100644 --- a/src/main/scala/org/scalajs/tools/tsimporter/Trees.scala +++ b/src/main/scala/org/scalajs/tools/tsimporter/Trees.scala @@ -159,6 +159,9 @@ object Trees { case class RepeatedType(underlying: TypeTree) extends TypeTree + case class IndexedQueryType(underlying: TypeTree) extends TypeTree + case class IndexedAccessType(objectType: TypeTree, name: TypeTree) extends TypeTree + object PolymorphicThisType extends TypeTree // Type members diff --git a/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala b/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala index 506d5c7f..63486596 100644 --- a/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala +++ b/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala @@ -40,7 +40,7 @@ class TSDefParser extends StdTokenParsers with ImplicitConversions { "public", "static", "yield", // Additional keywords of TypeScript - "declare", "module", "type", "namespace" + "declare", "module", "type", "namespace", "keyof" ) lexical.delimiters ++= List( @@ -203,10 +203,11 @@ class TSDefParser extends StdTokenParsers with ImplicitConversions { } lazy val singleTypeDesc: Parser[TypeTree] = - baseTypeDesc ~ rep("[" ~ "]") ^^ { + baseTypeDesc ~ rep("[" ~> opt(typeDesc) <~ "]") ^^ { case base ~ arrayDims => (base /: arrayDims) { - (elem, _) => ArrayType(elem) + case (elem, None) => ArrayType(elem) + case (elem, Some(index)) => IndexedAccessType(elem, index) } } @@ -218,6 +219,7 @@ class TSDefParser extends StdTokenParsers with ImplicitConversions { | typeQuery | tupleType | thisType + | indexTypeQuery | "(" ~> typeDesc <~ ")" ) @@ -248,6 +250,9 @@ class TSDefParser extends StdTokenParsers with ImplicitConversions { lazy val thisType: Parser[TypeTree] = "this" ^^^ PolymorphicThisType + lazy val indexTypeQuery: Parser[TypeTree] = + "keyof" ~> typeDesc ^^ IndexedQueryType + lazy val typeQuery: Parser[TypeTree] = "typeof" ~> rep1sep(ident, ".") ^^ { parts => TypeQuery(QualifiedIdent(parts.init.map(Ident), Ident(parts.last)))