[gtksourceview: 2/6] typescript.lang: Add/rewrite using context / language parsing



commit 50e55021ce27c1f674418ef81bc1b5422286bf18
Author: Jeffery To <jeffery to gmail com>
Date:   Thu Oct 10 23:03:11 2019 +0800

    typescript.lang: Add/rewrite using context / language parsing

 data/language-specs/typescript-js-expressions.lang |  221 +++
 .../typescript-js-functions-classes.lang           |  367 +++++
 data/language-specs/typescript-js-literals.lang    |  160 +++
 data/language-specs/typescript-js-modules.lang     |  228 +++
 data/language-specs/typescript-js-statements.lang  |  545 ++++++++
 data/language-specs/typescript-js-values.lang      |   64 +
 .../typescript-type-expressions.lang               |  533 +++++++
 data/language-specs/typescript-type-generics.lang  |  252 ++++
 data/language-specs/typescript-type-literals.lang  |  419 ++++++
 data/language-specs/typescript.lang                |  742 +++++++++-
 po/POTFILES.skip                                   |    9 +
 tests/syntax-highlighting/file.ts                  | 1448 ++++++++++++++++++--
 12 files changed, 4835 insertions(+), 153 deletions(-)
---
diff --git a/data/language-specs/typescript-js-expressions.lang 
b/data/language-specs/typescript-js-expressions.lang
new file mode 100644
index 00000000..55942deb
--- /dev/null
+++ b/data/language-specs/typescript-js-expressions.lang
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-js-expr" name="TypeScript JavaScript Expression Additions" version="2.0" 
_section="Script" hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Grouping / arrow function parameters -->
+
+    <!-- function parameter list allows for accessibility modifiers,
+         but these are not allowed in arrow function parameters
+
+         in a case like:
+         (x: number = 1) => x
+         the type annotation (: number) ends the expression (x),
+         so we add the default value assignment (= 1) back
+    -->
+
+    <!-- replaces js-expr:_grouping-item-content -->
+    <context id="grouping-item-content">
+      <include>
+        <context ref="js-expr:_grouping-item-content" original="true"/>
+        <!-- the ternary operator will match for the optional
+             modifier (?), which should end early as there is no true
+             value -->
+        <context ref="typescript:ordered-type-annotation"/>
+        <context ref="js:ordered-default-value-assignment"/>
+      </include>
+    </context> <!-- /grouping-item-content -->
+
+    <context id="_grouping" style-ref="js:grouping" once-only="true">
+      <start>\(</start>
+      <end>\)</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:grouping-operator"/>
+        <context sub-pattern="0" where="end" style-ref="js:grouping-operator"/>
+        <context ref="js:comments"/>
+        <context ref="js-expr:_grouping-content"/>
+      </include>
+    </context> <!-- /_grouping -->
+
+    <context id="_ordered-grouping" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_grouping"/>
+      </include>
+    </context> <!-- /_ordered-grouping -->
+
+    <!-- replaces js-expr:_choice-grouping -->
+    <context id="choice-grouping-and-type-annotation" end-parent="true">
+      <start>(?=\()</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_grouping-and-type-annotation-content">
+          <include>
+            <context ref="_ordered-grouping"/>
+            <context ref="typescript:ordered-type-annotation"/>
+          </include>
+        </context> <!-- /_grouping-and-type-annotation-content -->
+
+      </include>
+    </context> <!-- /choice-grouping-and-type-annotation -->
+
+
+    <!-- # Primary expression -->
+
+    <!-- replaces js-expr:_primary-expression-identifier-content -->
+    <!--
+    <context id="primary-expression-identifier-content">
+      <include>
+        <context ref="typescript-object-keywords"/>
+        <context ref="js-expr:_primary-expression-identifier-content" original="true"/>
+      </include>
+    </context> <!- - /primary-expression-identifier-content -->
+
+
+    <!-- # Non-null assertion (post-fix !)
+
+         a!.method();
+    -->
+
+    <context id="_non-null-assertion-operators" style-ref="typescript:non-null-assertion-operator">
+      <match>!</match>
+    </context> <!-- /_non-null-assertion-operators -->
+
+
+    <!-- # Function call type arguments
+
+         fn<string, number>()
+    -->
+
+    <context id="_function-call-type-arguments-lists">
+      <start extended="true">
+        (?(DEFINE)
+          (?&lt;arguments&gt;  # recursive subpattern to find matching brackets
+            &lt;
+            (?:
+              (?&gt; [^&lt;&gt;]+ ) |
+              (?&amp;arguments)
+            )*
+            &gt;
+          )
+        )
+        (?=
+          (?&amp;arguments)
+          \%{js:optional-whitespace-or-comments}
+          (?: \( | ` )  # function call or tagged template
+        )
+      </start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_function-call-type-arguments-list-content">
+          <include>
+            <context ref="typescript-type-gen:ordered-type-arguments-list"/>
+          </include>
+        </context> <!-- /_function-call-type-arguments-list-content -->
+
+      </include>
+    </context> <!-- /_function-call-type-arguments-lists -->
+
+
+    <!-- # Post-primary expression -->
+
+    <!-- replaces js-expr:_post-primary-expression -->
+    <context id="post-primary-expression">
+      <include>
+        <context ref="_non-null-assertion-operators"/>
+        <context ref="_function-call-type-arguments-lists"/>
+        <context ref="js-expr:_post-primary-expression" original="true"/>
+      </include>
+    </context> <!-- /post-primary-expression -->
+
+
+    <!-- # Pre-LHS expression -->
+
+    <!-- replaces js-expr:_pre-lhs-expression -->
+    <context id="pre-lhs-expression">
+      <include>
+        <context ref="typescript-type-gen:type-parameters-list-or-type-assertion"/>
+        <context ref="js-expr:_pre-lhs-expression" original="true"/>
+      </include>
+    </context> <!-- /pre-lhs-expression -->
+
+
+    <!-- # as operator (type assertion / cast)
+
+         a = obj as string;
+    -->
+
+    <context id="_as-operators">
+      <start>\%[as\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_as-operator-content">
+          <include>
+            <context ref="typescript-type-gen:const-type-assertion-keyword-end-parent"/>
+            <context ref="typescript-type-expr:type-expression"/>
+          </include>
+        </context> <!-- /_as-operator-content -->
+
+      </include>
+    </context> <!-- /_as-operators -->
+
+
+    <!-- # Post-LHS expression -->
+
+    <!-- ## Without comma -->
+
+    <!-- replaces js-expr:_post-lhs-expression-without-comma -->
+    <context id="post-lhs-expression-without-comma">
+      <include>
+        <context ref="js-expr:_post-lhs-expression-without-comma" original="true"/>
+        <context ref="_as-operators"/>
+      </include>
+    </context> <!-- /post-lhs-expression-without-comma -->
+
+    <!-- ## With comma -->
+
+    <!-- replaces js-expr:_post-lhs-expression-with-comma -->
+    <context id="post-lhs-expression-with-comma">
+      <include>
+        <context ref="js-expr:_post-lhs-expression-with-comma" original="true"/>
+        <context ref="_as-operators"/>
+      </include>
+    </context> <!-- /post-lhs-expression-with-comma -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-js-functions-classes.lang 
b/data/language-specs/typescript-js-functions-classes.lang
new file mode 100644
index 00000000..75957749
--- /dev/null
+++ b/data/language-specs/typescript-js-functions-classes.lang
@@ -0,0 +1,367 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-js-fn" name="TypeScript JavaScript Function and Class Additions" version="2.0" 
_section="Script" hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Accessibility modifier -->
+
+    <context id="_accessibility-modifier" style-ref="js:keyword" once-only="true">
+      <keyword>private</keyword>
+      <keyword>protected</keyword>
+      <keyword>public</keyword>
+    </context> <!-- /_accessibility-modifier -->
+
+    <context id="_ordered-accessibility-modifier" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_accessibility-modifier"/>
+      </include>
+    </context> <!-- /_ordered-accessibility-modifier -->
+
+
+    <!-- # Function expression -->
+
+    <!-- <CallSignature> / <ParameterList> -->
+    <!-- replaces js-fn:_function-parameters-content -->
+    <context id="function-parameters-content">
+      <include>
+        <context ref="_ordered-accessibility-modifier"/>
+        <context ref="js:ordered-rest-syntax"/>
+        <context ref="js:ordered-assignment-target"/>
+        <context ref="typescript:ordered-optional-modifier"/>
+        <context ref="typescript:ordered-type-annotation"/>
+        <context ref="js:ordered-default-value-assignment"/>
+      </include>
+    </context> <!-- /function-parameters-content -->
+
+    <!-- replaces js-fn:_function-first-parameter -->
+    <context id="function-first-parameter" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:embedded-lang-hooks"/>
+        <context ref="js:comments"/>
+
+        <context id="_function-first-parameter-content">
+          <include>
+            <context ref="_ordered-accessibility-modifier"/>
+            <context ref="js:ordered-rest-syntax"/>
+            <context ref="typescript:ordered-this-parameter-or-assignment-target"/>
+            <context ref="typescript:ordered-optional-modifier"/>
+            <context ref="typescript:ordered-type-annotation"/>
+            <context ref="js:ordered-default-value-assignment"/>
+          </include>
+        </context> <!-- /_function-first-parameter-content -->
+
+      </include>
+    </context> <!-- /function-first-parameter -->
+
+    <!-- <FunctionExpression> (Modified) (part of) /
+         <CallSignature> /
+         <FunctionDeclaration> (Modified) (part of) -->
+    <!-- replaces js-fn:_function-expression-content -->
+    <context id="function-expression-content">
+      <include>
+        <context ref="js-fn:_ordered-function-expression-async-keyword"/>
+        <context ref="js-fn:_ordered-function-expression-function-keyword"/>
+        <context ref="js:ordered-generator-modifier"/>
+        <context ref="js:ordered-identifier"/>
+        <context ref="typescript-type-gen:ordered-type-parameters-list"/>
+        <context ref="js-fn:_ordered-function-parameters-list"/>
+        <context ref="typescript:ordered-type-annotation"/>
+        <context ref="js-fn:_last-function-body"/>
+      </include>
+    </context> <!-- /function-expression-content -->
+
+
+    <!-- # Method definition -->
+
+    <!-- ensure type annotation for functions:
+           method(): 'type' { ... }
+         doesn't conflict with object literal property value:
+           property: 'value'
+    -->
+
+    <context id="_function-parameter-list-and-type-annotation" once-only="true">
+      <start>(?=\()</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_function-parameter-list-and-type-annotation-content">
+          <include>
+            <context ref="js-fn:_ordered-function-parameters-list" style-ref="js:function-expression"/>
+            <context ref="typescript:ordered-type-annotation"/>
+          </include>
+        </context> <!-- /_function-parameter-list-and-type-annotation-content -->
+
+      </include>
+    </context> <!-- /_function-parameter-list-and-type-annotation -->
+
+    <context id="_ordered-function-parameter-list-and-type-annotation" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_function-parameter-list-and-type-annotation"/>
+      </include>
+    </context> <!-- /_ordered-function-parameter-list-and-type-annotation -->
+
+    <!-- replaces js-fn:_method-definition-content -->
+    <context id="method-definition-content">
+      <include>
+        <context ref="js-fn:_ordered-method-definition-modifier"/>
+        <context ref="js:ordered-generator-modifier"/>
+        <context ref="js-lit:ordered-property-name"/>
+        <!-- technically, only class members can be marked as optional,
+             not object members -->
+        <context ref="typescript:ordered-optional-modifier"/>
+        <!-- technically, only class properties can be marked as
+             definitely assigned, not object members -->
+        <!-- also, optional modifier and definitely assignment
+             assertion cannot both be specified -->
+        <context ref="typescript:ordered-definite-assignment-assertion"/>
+        <context ref="typescript-type-gen:ordered-type-parameters-list"/>
+        <context ref="_ordered-function-parameter-list-and-type-annotation"/>
+        <context ref="js-fn:_last-function-body" style-ref="js:function-expression"/>
+      </include>
+    </context> <!-- /method-definition-content -->
+
+
+    <!-- # Class expression -->
+
+    <!-- ## Class expression keyword -->
+
+    <context id="_class-expression-abstract-keyword" style-ref="js:keyword">
+      <keyword>abstract</keyword>
+    </context> <!-- /_class-expression-abstract-keyword -->
+
+    <context id="_ordered-class-expression-abstract-keyword" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_class-expression-abstract-keyword"/>
+      </include>
+    </context> <!-- /_ordered-class-expression-abstract-keyword -->
+
+    <context id="_class-expression-class-keyword" style-ref="js:keyword">
+      <keyword>class</keyword>
+    </context> <!-- /_class-expression-class-keyword -->
+
+    <context id="_ordered-class-expression-class-keyword" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_class-expression-class-keyword"/>
+      </include>
+    </context> <!-- /_ordered-class-expression-class-keyword -->
+
+    <!-- ## Class optional name -->
+
+    <!-- replaces js-fn:_class-optional-name-content -->
+    <context id="class-optional-name-content">
+      <include>
+
+        <context id="_choice-class-optional-name-ignore-implements" end-parent="true">
+          <start>(?=\%[implements\%])</start>
+          <end>\%{def:always-match}</end>
+        </context> <!-- /_choice-class-optional-name-ignore-implements -->
+
+        <context ref="js-fn:_class-optional-name-content" original="true"/>
+      </include>
+    </context> <!-- /class-optional-name-content -->
+
+    <!-- ## Class extends clause -->
+
+    <!-- replaces js-fn:_class-extends-clause-content -->
+    <context id="class-extends-clause-content">
+      <include>
+        <context ref="js-fn:_class-extends-clause-content" original="true"/>
+        <context ref="typescript-type-gen:ordered-type-arguments-list"/>
+      </include>
+    </context> <!-- /class-extends-clause-content -->
+
+    <!-- ## Class implements clause -->
+
+    <context id="_class-implements-clause" once-only="true">
+      <start>\%[implements\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_class-implements-clause-content">
+          <include>
+            <context ref="typescript:type-reference-list"/>
+          </include>
+        </context> <!-- /_class-implements-clause-content -->
+
+      </include>
+    </context> <!-- /_class-implements-clause -->
+
+    <context id="_ordered-class-implements-clause" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_class-implements-clause"/>
+      </include>
+    </context> <!-- /_ordered-class-implements-clause -->
+
+    <!-- ## Class body -->
+
+    <context id="_class-body-member-modifier" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_class-body-member-modifier-content">
+          <include>
+
+            <context id="_class-body-member-modifier-keywords" style-ref="js:keyword">
+              <keyword>abstract</keyword>
+              <keyword>readonly</keyword>
+            </context> <!-- /_class-body-member-modifier-keywords -->
+
+          </include>
+        </context> <!-- /_class-body-member-modifier-content -->
+
+      </include>
+    </context> <!-- /_class-body-member-modifier -->
+
+    <context id="_ordered-class-body-member-modifier" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_class-body-member-modifier"/>
+      </include>
+    </context> <!-- /_ordered-class-body-member-modifier -->
+
+    <context id="_choice-class-body-index-member" end-parent="true">
+      <start>(?=\[)</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_class-body-index-member-content">
+          <include>
+            <context ref="typescript-type-lit:ordered-index-property"/>
+            <context ref="typescript:ordered-type-annotation"/>
+          </include>
+        </context> <!-- /_class-body-index-member-content -->
+
+      </include>
+    </context> <!-- /_choice-class-body-index-member -->
+
+    <context id="_choice-class-body-property-or-method-member" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_class-body-property-or-method-member-content">
+          <include>
+            <context ref="js-fn:ordered-method-definition"/>
+            <!-- method-definition has a type-annotation, but it is tied
+                 to function-parameter-list -->
+            <context ref="typescript:ordered-type-annotation"/>
+            <context ref="js:ordered-default-value-assignment"/>
+          </include>
+        </context> <!-- /_class-body-property-or-method-member-content -->
+
+      </include>
+    </context> <!-- /_choice-class-body-property-or-method-member -->
+
+    <!-- replaces js-fn:_class-body-member-content -->
+    <context id="class-body-member-content">
+      <include>
+        <!-- only "readonly" applies to index members
+             but these all need to be here because of ordering -->
+        <context ref="_ordered-accessibility-modifier"/>
+        <!-- "static" must precede "readonly" -->
+        <context ref="js-fn:_ordered-class-body-member-modifier"/>
+        <context ref="_ordered-class-body-member-modifier"/>
+        <context ref="_choice-class-body-index-member"/>
+        <context ref="_choice-class-body-property-or-method-member"/>
+      </include>
+    </context> <!-- /class-body-member-content -->
+
+    <!-- ## Class expression -->
+
+    <!-- replaces js-fn:_class-expression-content -->
+    <context id="class-expression-content">
+      <include>
+        <context ref="_ordered-class-expression-abstract-keyword"/>
+        <context ref="_ordered-class-expression-class-keyword"/>
+        <context ref="js-fn:_ordered-class-optional-name"/>
+        <context ref="typescript-type-gen:ordered-type-parameters-list"/>
+        <context ref="js-fn:_ordered-class-extends-clause"/>
+        <context ref="_ordered-class-implements-clause"/>
+        <context ref="js-fn:_last-class-body"/>
+      </include>
+    </context> <!-- /class-expression-content -->
+
+    <!-- <ClassExpression> / <ClassDeclaration> -->
+    <!-- replaces js-fn:choice-class-expression -->
+    <context id="choice-class-expression" style-ref="js:class-expression" end-parent="true">
+      <start>(?=\%{typescript:class-expression-keyword})</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+        <context ref="js-fn:_class-expression-content"/>
+      </include>
+    </context> <!-- /choice-class-expression -->
+
+    <!-- replaces js-fn:_class-expression-required-name-content -->
+    <context id="class-expression-required-name-content">
+      <include>
+        <context ref="_ordered-class-expression-abstract-keyword"/>
+        <context ref="_ordered-class-expression-class-keyword"/>
+        <context ref="js:ordered-identifier"/>
+        <context ref="typescript-type-gen:ordered-type-parameters-list"/>
+        <context ref="js-fn:_ordered-class-extends-clause"/>
+        <context ref="_ordered-class-implements-clause"/>
+        <context ref="js-fn:_last-class-body"/>
+      </include>
+    </context> <!-- /class-expression-required-name-content -->
+
+    <!-- <ClassExpression> / <ClassDeclaration> -->
+    <!-- replaces js-fn:choice-class-expression-required-name -->
+    <context id="choice-class-expression-required-name" style-ref="js:class-expression" end-parent="true">
+      <start>(?=\%{typescript:class-expression-keyword})</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+        <context ref="js-fn:_class-expression-required-name-content"/>
+      </include>
+    </context> <!-- /choice-class-expression-required-name -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-js-literals.lang b/data/language-specs/typescript-js-literals.lang
new file mode 100644
index 00000000..66f25cb0
--- /dev/null
+++ b/data/language-specs/typescript-js-literals.lang
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-js-lit" name="TypeScript JavaScript Literal Additions" version="2.0" 
_section="Script" hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Number
+
+         Numeric separators (stage 2 proposal):
+         1_000_000
+         0b1100_0011_1101_0001
+         0o123_456_700
+         0xFF_0C_00_FF
+    -->
+
+    <!-- replaces js-lit:choice-number -->
+    <context id="choice-number">
+      <include>
+
+        <define-regex id="_decimal-digits" extended="true">
+          (?&gt;
+            [0-9]
+            (?:
+              [0-9]+ |
+              (?: _ [0-9] )+
+            )*
+          )
+        </define-regex> <!-- /_decimal-digits -->
+
+        <define-regex id="_decimal" extended="true">
+          (?&gt;
+            (?: [1-9] _? \%{_decimal-digits} | [0-9] ) (?: \. \%{_decimal-digits}? )? |
+            \. \%{_decimal-digits}
+          )
+          (?&gt; [eE] [+-]? \%{_decimal-digits} )?
+        </define-regex> <!-- /_decimal -->
+
+        <context id="_choice-decimal" style-ref="js:decimal" end-parent="true">
+          <start extended="true">
+            (?&lt;! \%{js:identifier-char} | \. )
+            (?=
+              \%{_decimal}
+              (?! \%{js:identifier-part} | \. )
+            )
+          </start>
+          <end>\%{_decimal}</end>
+        </context> <!-- /_choice-decimal -->
+
+        <define-regex id="_decimal-integer" extended="true">
+          (?&gt;
+            (?: [1-9] _? \%{_decimal-digits} | [0-9] )
+          )
+        </define-regex> <!-- /_decimal-integer -->
+
+        <context id="_choice-decimal-big-integer" style-ref="js:decimal" end-parent="true">
+          <start extended="true">
+            (?&lt;! \%{js:identifier-char} | \. )
+            (?=
+              \%{_decimal-integer} n
+              (?! \%{js:identifier-part} | \. )
+            )
+          </start>
+          <end>\%{_decimal-integer}n</end>
+        </context> <!-- /_choice-decimal-big-integer -->
+
+        <define-regex id="_binary-integer" extended="true">
+          (?&gt;
+            0 [bB] [01]
+            (?:
+              [01]+ |
+              (?: _ [01] )+
+            )*
+          )
+        </define-regex> <!-- /_binary-integer -->
+
+        <context id="_choice-binary-integer" style-ref="js:binary-integer" end-parent="true">
+          <start extended="true">
+            (?&lt;! \%{js:identifier-char} | \. )
+            (?=
+              \%{_binary-integer} n?
+              (?! \%{js:identifier-part} | \. )
+            )
+          </start>
+          <end>\%{_binary-integer}n?</end>
+        </context> <!-- /_choice-binary-integer -->
+
+        <define-regex id="_octal-integer" extended="true">
+          (?&gt;
+            0 [oO] [0-7]
+            (?:
+              [0-7]+ |
+              (?: _ [0-7] )+
+            )*
+          )
+        </define-regex> <!-- /_octal-integer -->
+
+        <context id="_choice-octal-integer" style-ref="js:octal-integer" end-parent="true">
+          <start extended="true">
+            (?&lt;! \%{js:identifier-char} | \. )
+            (?=
+              \%{_octal-integer} n?
+              (?! \%{js:identifier-part} | \. )
+            )
+          </start>
+          <end>\%{_octal-integer}n?</end>
+        </context> <!-- /_choice-octal-integer -->
+
+        <define-regex id="_hex-integer" extended="true">
+          (?&gt;
+            0 [xX] [0-9a-fA-F]
+            (?:
+              [0-9a-fA-F]+ |
+              (?: _ [0-9a-fA-F] )+
+            )*
+          )
+        </define-regex> <!-- /_hex-integer -->
+
+        <context id="_choice-hex-integer" style-ref="js:hex-integer" end-parent="true">
+          <start extended="true">
+            (?&lt;! \%{js:identifier-char} | \. )
+            (?=
+              \%{_hex-integer} n?
+              (?! \%{js:identifier-part} | \. )
+            )
+          </start>
+          <end>\%{_hex-integer}n?</end>
+        </context> <!-- /_choice-hex-integer -->
+
+        <context ref="js-lit:_choice-legacy-octal-integer"/>
+      </include>
+    </context> <!-- /choice-number -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-js-modules.lang b/data/language-specs/typescript-js-modules.lang
new file mode 100644
index 00000000..96805908
--- /dev/null
+++ b/data/language-specs/typescript-js-modules.lang
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-js-mod" name="TypeScript JavaScript Module Additions" version="2.0" 
_section="Script" hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Export declaration -->
+
+    <!-- ## Export as namespace (UMD module definition)
+
+         export as namespace myModule;
+    -->
+
+    <context id="_export-as-namespace-keyword" style-ref="js:keyword" once-only="true">
+      <keyword>namespace</keyword>
+    </context> <!-- /_export-as-namespace-keyword -->
+
+    <context id="_ordered-export-as-namespace-keyword" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_export-as-namespace-keyword"/>
+      </include>
+    </context> <!-- /_ordered-export-as-namespace-keyword -->
+
+    <context id="_choice-export-as-namespace" end-parent="true">
+      <start>\%[as\%]</start>
+      <end>\%{js:statement-end}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_export-as-namespace-content">
+          <include>
+            <context ref="_ordered-export-as-namespace-keyword"/>
+            <context ref="js:ordered-identifier"/>
+          </include>
+        </context> <!-- /_export-as-namespace-content -->
+
+      </include>
+    </context> <!-- /_choice-export-as-namespace -->
+
+    <!-- ## Export assignment
+
+         export = obj;
+    -->
+
+    <!-- <ExportAssignment> -->
+    <context id="_choice-export-assignment" end-parent="true">
+      <start>=</start>
+      <end>\%{js:statement-end}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_export-assignment-content">
+          <include>
+            <context ref="js:ordered-identifier"/>
+          </include>
+        </context> <!-- /_export-assignment-content -->
+
+      </include>
+    </context> <!-- /_choice-export-assignment -->
+
+    <!-- ## Export declaration -->
+
+    <!-- replaces js-mod:_export-declaration-content -->
+    <context id="export-declaration-content">
+      <include>
+        <context ref="_choice-export-as-namespace"/>
+        <context ref="_choice-export-assignment"/>
+        <context ref="typescript-js-st:choice-ambient-declaration"/>
+        <context ref="typescript-js-st:choice-const-declaration"/>
+        <context ref="typescript-js-st:choice-enum-declaration"/>
+        <context ref="_choice-import-declaration"/> <!-- for import alias declaration -->
+        <context ref="typescript-js-st:choice-interface-declaration"/>
+        <context ref="typescript-js-st:choice-namespace-declaration"/>
+        <context ref="typescript-js-st:choice-type-alias-declaration"/>
+        <context ref="js-mod:_export-declaration-content" original="true"/>
+      </include>
+    </context> <!-- /export-declaration-content -->
+
+
+    <!-- # Import declaration -->
+
+    <!-- ## Import alias / import require
+
+         import shortname = Long.Namespace.Name;
+         import mod = require("module");
+
+         even though these are not variations of import default,
+         we add these to import default because it matches an
+         identifier after the import keyword
+    -->
+
+    <context id="_choice-import-require" end-parent="true">
+      <start>\%[require\%]</start>
+      <end>\%{js:statement-end}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_import-require-content">
+          <include>
+
+            <context id="_import-require-parameter-list" once-only="true">
+              <start>\(</start>
+              <end>\)</end>
+              <include>
+                <context ref="js:comments"/>
+
+                <context id="_import-require-parameter-list-content">
+                  <include>
+                    <context ref="typescript:js-ordered-string"/>
+                  </include>
+                </context> <!-- /_import-require-parameter-list-content -->
+
+              </include>
+            </context> <!-- /_import-require-parameter-list -->
+
+          </include>
+        </context> <!-- /_import-require-content -->
+
+      </include>
+    </context> <!-- /_choice-import-require -->
+
+    <context id="_choice-import-alias" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:statement-end}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_import-alias-content">
+          <include>
+            <context ref="typescript:ordered-namespace-name"/>
+          </include>
+        </context> <!-- /_import-alias-content -->
+
+      </include>
+    </context> <!-- /_choice-import-alias -->
+
+    <context id="_choice-import-alias-or-require" end-parent="true">
+      <start>=</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_import-alias-or-require-content">
+          <include>
+            <context ref="_choice-import-require"/>
+            <context ref="_choice-import-alias"/>
+          </include>
+        </context> <!-- /_import-alias-or-require-content -->
+
+      </include>
+    </context> <!-- /_choice-import-alias-or-require -->
+
+    <!-- ## Import default -->
+
+    <!-- replaces js-mod:_import-default-content -->
+    <context id="import-default-content">
+      <include>
+        <context ref="js:ordered-identifier"/>
+        <context ref="_choice-import-alias-or-require"/>
+        <context ref="js-mod:_choice-import-default-additional"/>
+        <context ref="js-mod:_choice-import-default-only"/>
+      </include>
+    </context> <!-- /import-default-content -->
+
+    <!-- ## Import declaration -->
+
+    <define-regex id="_import-declaration-keyword" extended="true">
+      (?:
+        \%[ import \%]
+        (?! \%{js:import-function-keyword-suffix} )
+        (?! \%{typescript:import-meta-object-keyword-suffix} )
+      )
+    </define-regex>
+
+    <!-- <ImportDeclaration> -->
+    <context id="_choice-import-declaration" style-ref="js:export-import-declaration" end-parent="true">
+      <start>\%{_import-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="js-mod:_import-declaration-content"/>
+      </include>
+    </context> <!-- /_choice-import-declaration -->
+
+    <!-- replaces js-mod:import-declarations -->
+    <context id="import-declarations" style-ref="js:export-import-declaration">
+      <start>\%{_import-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="js-mod:_import-declaration-content"/>
+      </include>
+    </context> <!-- /import-declarations -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-js-statements.lang 
b/data/language-specs/typescript-js-statements.lang
new file mode 100644
index 00000000..259a43ae
--- /dev/null
+++ b/data/language-specs/typescript-js-statements.lang
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-js-st" name="TypeScript JavaScript Statement Additions" version="2.0" 
_section="Script" hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Class declaration -->
+
+    <!-- <ClassExpression> / <ClassDeclaration> -->
+    <!-- replaces js-st:_class-declarations -->
+    <context id="class-declarations">
+      <start>(?=\%{typescript:class-expression-keyword})</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+        <context ref="js-st:_class-declaration-content"/>
+      </include>
+    </context> <!-- /class-declarations -->
+
+
+    <!-- # Variable declaration -->
+
+    <!-- replaces js-st:_variable-declaration-item-content -->
+    <context id="variable-declaration-item-content">
+      <include>
+        <context ref="js:ordered-assignment-target"/>
+        <context ref="typescript:ordered-definite-assignment-assertion"/>
+        <context ref="typescript:ordered-type-annotation"/>
+        <context ref="js:ordered-default-value-assignment"/>
+      </include>
+    </context> <!-- /variable-declaration-item-content -->
+
+
+    <!-- # Ambient declaration
+
+         declare var a;
+         declare function fn;
+         declare function fn { ... }
+         declare class Foo { ... }
+         declare enum Foo { ... }
+         declare namespace Foo { ... }
+         declare module "foo" { ... }
+         declare module "foo";
+         declare global { ... }
+    -->
+
+    <define-regex id="_ambient-declaration-keyword" extended="true">
+      (?: \%[ declare \%] )
+    </define-regex> <!-- /_ambient-declaration-keyword -->
+
+    <context id="_choice-global-augmentation" style-ref="typescript:global-augmentation" end-parent="true">
+      <start>\%[global\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_global-augmentation-content">
+          <include>
+            <context ref="_last-namespace-body"/>
+          </include>
+        </context> <!-- /_global-augmentation-content -->
+
+      </include>
+    </context> <!-- /_choice-global-augmentation -->
+
+    <context id="_ambient-declaration-content">
+      <include>
+        <context ref="choice-const-declaration"/>
+        <context ref="choice-enum-declaration"/>
+        <context ref="_choice-global-augmentation"/>
+        <context ref="choice-module-declaration"/>
+        <context ref="choice-namespace-declaration"/>
+        <context ref="js-fn:choice-class-expression-required-name"/>
+        <context ref="js-fn:choice-function-expression"/>
+        <context ref="js-st:choice-variable-declaration"/>
+      </include>
+    </context> <!-- /_ambient-declaration-content -->
+
+    <!-- <AmbientDeclaration> -->
+    <context id="_ambient-declarations" style-ref="typescript:ambient-declaration">
+      <start>\%{_ambient-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_ambient-declaration-content"/>
+      </include>
+    </context> <!-- /_ambient-declarations -->
+
+    <!-- <AmbientDeclaration> -->
+    <context id="choice-ambient-declaration" style-ref="typescript:ambient-declaration" end-parent="true">
+      <start>\%{_ambient-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_ambient-declaration-content"/>
+      </include>
+    </context> <!-- /choice-ambient-declaration -->
+
+
+    <!-- # Const declaration
+
+         const a = 1;
+         const enum Foo { ... }
+
+         we need a custom const declaration to handle "const enum"
+    -->
+
+    <define-regex id="_const-declaration-keyword" extended="true">
+      (?: \%[ const \%] )
+    </define-regex> <!-- /_const-declaration-keyword -->
+
+    <context id="_const-declaration-content">
+      <include>
+        <context ref="choice-enum-declaration"/>
+
+        <context id="_choice-const-declaration-variable-declaration" end-parent="true">
+          <start>\%{js:before-next-token}</start>
+          <end>\%{js:statement-end}</end>
+          <include>
+            <context ref="js:comments"/>
+            <context ref="js-st:_variable-declaration-content"/>
+          </include>
+        </context> <!-- /_choice-const-declaration-variable-declaration -->
+
+      </include>
+    </context> <!-- /_const-declaration-content -->
+
+    <context id="_const-declarations" style-ref="js:variable-declaration">
+      <start>\%{_const-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_const-declaration-content"/>
+      </include>
+    </context> <!-- /_const-declarations -->
+
+    <context id="choice-const-declaration" style-ref="js:variable-declaration" end-parent="true">
+      <start>\%{_const-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_const-declaration-content"/>
+      </include>
+    </context> <!-- /choice-const-declaration -->
+
+
+    <!-- # Enum declaration
+
+         enum Foo { A = 1, B, C }
+    -->
+
+    <define-regex id="_enum-declaration-keyword" extended="true">
+      (?: \%[ enum \%] )
+    </define-regex> <!-- /_enum-declaration-keyword -->
+
+    <context id="_enum-member-content">
+      <include>
+        <context ref="typescript-type-lit:ordered-property-name"/>
+        <context ref="js:ordered-default-value-assignment"/>
+      </include>
+    </context> <!-- /_enum-member-content -->
+
+    <context id="_enum-body" once-only="true">
+      <start>{</start>
+      <end>}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_enum-body-content">
+          <include>
+
+            <context id="_enum-first-member" once-only="true">
+              <start>\%{js:before-next-token}</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_enum-member-content"/>
+              </include>
+            </context> <!-- /_enum-first-member -->
+
+            <context id="_enum-members">
+              <start>,</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_enum-member-content"/>
+              </include>
+            </context> <!-- /_enum-members -->
+
+          </include>
+        </context> <!-- /_enum-body-content -->
+
+      </include>
+    </context> <!-- /_enum-body -->
+
+    <context id="_last-enum-body" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_enum-body"/>
+      </include>
+    </context> <!-- /_last-enum-body -->
+
+    <context id="_enum-declaration-content">
+      <include>
+        <context ref="js:ordered-identifier"/>
+        <context ref="_last-enum-body"/>
+      </include>
+    </context> <!-- /_enum-declaration-content -->
+
+    <!-- <EnumDeclaration> -->
+    <context id="_enum-declarations" style-ref="typescript:enum-declaration">
+      <start>\%{_enum-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_enum-declaration-content"/>
+      </include>
+    </context> <!-- /_enum-declarations -->
+
+    <!-- <EnumDeclaration> -->
+    <context id="choice-enum-declaration" style-ref="typescript:enum-declaration" end-parent="true">
+      <start>\%{_enum-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_enum-declaration-content"/>
+      </include>
+    </context> <!-- /choice-enum-declaration -->
+
+
+    <!-- # Interface declaration
+
+         interface MyObj { ... }
+         interface MyObj<T, U> extends AThing,
+           AnotherThing<string, number> { ... }
+    -->
+
+    <define-regex id="_interface-declaration-keyword" extended="true">
+      (?: \%[ interface \%] )
+    </define-regex> <!-- /_interface-declaration-keyword -->
+
+    <context id="_interface-extends-clause" once-only="true">
+      <start>\%[extends\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_interface-extends-clause-content">
+          <include>
+            <context ref="typescript:type-reference-list"/>
+          </include>
+        </context> <!-- /_interface-extends-clause-content -->
+
+      </include>
+    </context> <!-- /_interface-extends-clause -->
+
+    <context id="_ordered-interface-extends-clause" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_interface-extends-clause"/>
+      </include>
+    </context> <!-- /_ordered-interface-extends-clause -->
+
+    <context id="_interface-declaration-content">
+      <include>
+        <context ref="js:ordered-identifier"/>
+        <context ref="typescript-type-gen:ordered-type-parameters-list"/>
+        <context ref="_ordered-interface-extends-clause"/>
+        <context ref="typescript-type-lit:last-object-type-literal"/>
+      </include>
+    </context> <!-- /_interface-declaration-content -->
+
+    <!-- <InterfaceDeclaration> -->
+    <context id="_interface-declarations" style-ref="typescript:interface-declaration">
+      <start>\%{_interface-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_interface-declaration-content"/>
+      </include>
+    </context> <!-- /_interface-declarations -->
+
+    <!-- <InterfaceDeclaration> -->
+    <context id="choice-interface-declaration" style-ref="typescript:interface-declaration" 
end-parent="true">
+      <start>\%{_interface-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_interface-declaration-content"/>
+      </include>
+    </context> <!-- /choice-interface-declaration -->
+
+
+    <!-- # Module declaration
+
+         module Foo.Bar { ... } // same as namespace
+                                // ("internal module")
+         module "foo.bar" { ... } // "external module" for d.ts files
+    -->
+
+    <define-regex id="_module-declaration-keyword" extended="true">
+      (?: \%[ module \%] )
+    </define-regex> <!-- /_module-declaration-keyword -->
+
+    <context id="_module-identifier-or-string" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_module-identifier-or-string-content">
+          <include>
+            <context ref="js-lit:choice-string"/>
+            <context ref="typescript:choice-namespace-name"/>
+          </include>
+        </context> <!-- /_module-identifier-or-string-content -->
+
+      </include>
+    </context> <!-- /_module-identifier-or-string -->
+
+    <context id="_ordered-module-identifier-or-string" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_module-identifier-or-string"/>
+      </include>
+    </context> <!-- /_ordered-module-identifier-or-string -->
+
+    <context id="_module-declaration-content">
+      <include>
+        <context ref="_ordered-module-identifier-or-string"/>
+        <context ref="_last-namespace-body"/>
+      </include>
+    </context> <!-- /_module-declaration-content -->
+
+    <!-- <NamespaceDeclaration> -->
+    <context id="_module-declarations" style-ref="typescript:module-declaration">
+      <start>\%{_module-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_module-declaration-content"/>
+      </include>
+    </context> <!-- /_module-declarations -->
+
+    <!-- <NamespaceDeclaration> -->
+    <context id="choice-module-declaration" style-ref="typescript:module-declaration" end-parent="true">
+      <start>\%{_module-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_module-declaration-content"/>
+      </include>
+    </context> <!-- /choice-module-declaration -->
+
+
+    <!-- # Namespace declaration
+
+         namespace Foo.Bar { ... }
+    -->
+
+    <define-regex id="_namespace-declaration-keyword" extended="true">
+      (?: \%[ namespace \%] )
+    </define-regex> <!-- /_namespace-declaration-keyword -->
+
+    <context id="_namespace-body" once-only="true">
+      <start>{</start>
+      <end>}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_namespace-body-content">
+          <include>
+            <context ref="js-mod:export-declarations"/>
+            <context ref="js-mod:import-declarations"/> <!-- for import alias declarations -->
+            <context ref="js-st:statements"/>
+          </include>
+        </context> <!-- /_namespace-body-content -->
+
+      </include>
+    </context> <!-- /_namespace-body -->
+
+    <context id="_last-namespace-body" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_namespace-body"/>
+      </include>
+    </context> <!-- /_last-namespace-body -->
+
+    <context id="_namespace-declaration-content">
+      <include>
+        <context ref="typescript:ordered-namespace-name"/>
+        <context ref="_last-namespace-body"/>
+      </include>
+    </context> <!-- /_namespace-declaration-content -->
+
+    <!-- <NamespaceDeclaration> -->
+    <context id="_namespace-declarations" style-ref="typescript:namespace-declaration">
+      <start>\%{_namespace-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_namespace-declaration-content"/>
+      </include>
+    </context> <!-- /_namespace-declarations -->
+
+    <!-- <NamespaceDeclaration> -->
+    <context id="choice-namespace-declaration" style-ref="typescript:namespace-declaration" 
end-parent="true">
+      <start>\%{_namespace-declaration-keyword}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_namespace-declaration-content"/>
+      </include>
+    </context> <!-- /choice-namespace-declaration -->
+
+
+    <!-- # Type alias declaration
+
+         type Name = string;
+         type NameResolver = () => string;
+         type NameOrResolver = Name | NameResolver;
+         type Container<T> = { value: T };
+    -->
+
+    <define-regex id="_type-alias-declaration-keyword" extended="true">
+      (?: \%[ type \%] )
+    </define-regex> <!-- /_type-alias-declaration-keyword -->
+
+    <context id="_type-alias-value" once-only="true">
+      <start>=</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-alias-value-content">
+          <include>
+            <context ref="typescript-type-expr:type-expression"/>
+          </include>
+        </context> <!-- /_type-alias-value-content -->
+
+      </include>
+    </context> <!-- /_type-alias-value -->
+
+    <context id="_ordered-type-alias-value" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_type-alias-value"/>
+      </include>
+    </context> <!-- /_ordered-type-alias-value -->
+
+    <context id="_type-alias-declaration-content">
+      <include>
+        <context ref="js:ordered-identifier"/>
+        <context ref="typescript-type-gen:ordered-type-parameters-list"/>
+        <context ref="_ordered-type-alias-value"/>
+      </include>
+    </context> <!-- /_type-alias-declaration-content -->
+
+    <!-- <TypeAliasDeclaration> -->
+    <context id="_type-alias-declarations" style-ref="typescript:type-alias-declaration">
+      <start>\%{_type-alias-declaration-keyword}</start>
+      <end>\%{js:statement-end}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_type-alias-declaration-content"/>
+      </include>
+    </context> <!-- /_type-alias-declarations -->
+
+    <!-- <TypeAliasDeclaration> -->
+    <context id="choice-type-alias-declaration" style-ref="typescript:type-alias-declaration" 
end-parent="true">
+      <start>\%{_type-alias-declaration-keyword}</start>
+      <end>\%{js:statement-end}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+        <context ref="_type-alias-declaration-content"/>
+      </include>
+    </context> <!-- /choice-type-alias-declaration -->
+
+
+    <!-- # Statements -->
+
+    <!-- replaces js-st:statements -->
+    <context id="statements">
+      <include>
+        <context ref="_ambient-declarations"/>
+        <context ref="_const-declarations"/>
+        <context ref="_enum-declarations"/>
+        <context ref="_interface-declarations"/>
+        <context ref="_module-declarations"/>
+        <context ref="_namespace-declarations"/>
+        <context ref="_type-alias-declarations"/>
+        <context ref="js-mod:import-declarations"/> <!-- for import alias declarations -->
+        <context ref="js-st:statements" original="true"/>
+      </include>
+    </context> <!-- /statements -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-js-values.lang b/data/language-specs/typescript-js-values.lang
new file mode 100644
index 00000000..1ed420ee
--- /dev/null
+++ b/data/language-specs/typescript-js-values.lang
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-js-val" name="TypeScript JavaScript Built-in Value Additions" version="2.0" 
_section="Script" hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Global values -->
+
+    <!-- replaces js-val:global-values -->
+    <context id="global-values">
+      <include>
+
+        <!-- import.meta: stage 3 proposal -->
+        <context id="_import-meta-object-keyword">
+          <start extended="true">
+            \%[ import \%] (?= \%{typescript:import-meta-object-keyword-suffix} )
+          </start>
+          <end>\%[meta\%]</end>
+          <include>
+            <context sub-pattern="0" where="start" style-ref="js:keyword"/>
+            <context sub-pattern="0" where="end" style-ref="js:keyword"/>
+            <context ref="js:comments"/>
+
+            <context id="_import-meta-object-keyword-content">
+              <include>
+                <context ref="js:ordered-keyword-dot" style-ref="js:keyword"/>
+              </include>
+            </context> <!-- /_import-meta-object-keyword-content -->
+
+          </include>
+        </context> <!-- /_import-meta-object-keyword -->
+
+        <context ref="js-val:global-values" original="true"/>
+      </include>
+    </context> <!-- /global-values -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-type-expressions.lang 
b/data/language-specs/typescript-type-expressions.lang
new file mode 100644
index 00000000..4570c176
--- /dev/null
+++ b/data/language-specs/typescript-type-expressions.lang
@@ -0,0 +1,533 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-type-expr" name="TypeScript Type Expressions" version="2.0" _section="Script" 
hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Infer declaration (in conditional types)
+
+         T extends (infer U)[] ? U : any
+         T extends (...args: any[]) => infer U ? U : any
+         T extends Promise<infer U> ? U : any
+
+         introduces a type variable instead of referencing a type
+    -->
+
+    <context id="_choice-infer-declaration" end-parent="true">
+      <start>\%[infer\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="infer-declaration-content">
+          <include>
+            <context ref="js:ordered-identifier"/>
+          </include>
+        </context> <!-- /_infer-declaration-content -->
+
+      </include>
+    </context> <!-- /_choice-infer-declaration -->
+
+
+    <!-- # Pre-primary type
+
+         new () => object
+         keyof T
+         readonly string[]
+         unique symbol
+    -->
+
+    <context id="_pre-primary-type">
+      <include>
+        <context ref="typescript:constructor-modifier"/>
+        <context ref="typescript-type-gen:type-parameters-list"/>
+
+        <context id="_indexed-type-queries" style-ref="typescript:type-keyword">
+          <keyword>keyof</keyword>
+        </context> <!-- /_indexed-type-queries -->
+
+        <context id="_readonly-type-modifier" style-ref="typescript:type-keyword">
+          <keyword>readonly</keyword>
+        </context> <!-- /_readonly-type-modifier -->
+
+        <!-- for unique symbol subtype, can contain newlines between
+             "unique" and "symbol" -->
+        <context id="_unique-symbol-subtype" style-ref="typescript:basic-type" once-only="true">
+          <keyword>unique</keyword>
+        </context> <!-- /_unique-symbol-subtype -->
+
+      </include>
+    </context> <!-- /_pre-primary-type -->
+
+    <context id="_ordered-pre-primary-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_pre-primary-type"/>
+      </include>
+    </context> <!-- /_ordered-pre-primary-type -->
+
+
+    <!-- # Parenthesized type / function/constructor type
+
+         (string)
+         ({ a: number, b: string })
+         (x, y: number) => void
+         ({ a: x, b: y }, [a, b]) => boolean
+         (x: string, y?: number, ...rest: number[]) => void
+    -->
+
+    <!-- ## Type "grouping" -->
+
+    <!-- this will only catch simple cases :-( -->
+    <context id="_choice-type-grouping-this-parameter-or-assignment-target" end-parent="true">
+      <start extended="true">
+        (?:
+          (?&lt;= \.\.\. ) (?= \%{js:identifier} ) |  # adding js:optional-whitespace-or-comments in between 
doesn't work
+          (?= \%{js:identifier} \%{js:optional-whitespace-or-comments} [?:,] )
+        )
+      </start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-grouping-this-parameter-or-assignment-target-content">
+          <include>
+            <context ref="typescript:ordered-this-parameter-or-assignment-target"/>
+          </include>
+        </context> <!-- /_type-grouping-this-parameter-or-assignment-target-content -->
+
+      </include>
+    </context> <!-- /__choice-type-grouping-this-parameter-or-assignment-target -->
+
+    <context id="_type-grouping-type-expression-or-this-parameter-or-assignment-target" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <!-- no comments here -->
+
+        <context id="_type-grouping-type-expression-or-this-parameter-or-assignment-target-content">
+          <include>
+            <context ref="_choice-type-grouping-this-parameter-or-assignment-target"/>
+            <context ref="choice-type-expression"/>
+          </include>
+        </context> <!-- /_type-grouping-type-expression-or-this-parameter-or-assignment-target-content -->
+
+      </include>
+    </context> <!-- /_type-grouping-type-expression-or-this-parameter-or-assignment-target -->
+
+    <!-- function parameter list allows for accessibility modifiers and
+         default value assignment, but these are not allowed in a
+         function type definition -->
+
+    <context id="_type-grouping" once-only="true">
+      <start>\(</start>
+      <end>\)</end>
+      <include>
+        <context sub-pattern="0" where="start" 
style-ref="typescript:parenthesized-type-or-function-type-operator"/>
+        <context sub-pattern="0" where="end" 
style-ref="typescript:parenthesized-type-or-function-type-operator"/>
+        <context ref="js:comments"/>
+
+        <context id="_type-grouping-content">
+          <include>
+
+            <context id="_type-grouping-first-item" once-only="true">
+              <start>\%{js:before-next-token}</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+
+                <context id="_type-grouping-first-item-content">
+                  <include>
+                    <context ref="js:ordered-rest-syntax"/>
+                    <context ref="_type-grouping-type-expression-or-this-parameter-or-assignment-target"/>
+                    <context ref="typescript:ordered-optional-modifier"/>
+                    <context ref="typescript:ordered-type-annotation"/>
+                  </include>
+                </context> <!-- /_type-grouping-first-item-content -->
+
+              </include>
+            </context> <!-- /_type-grouping-first-item -->
+
+            <context id="_type-grouping-items">
+              <start>,</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+
+                <context id="_type-grouping-item-content">
+                  <include>
+                    <context ref="js:ordered-rest-syntax"/>
+                    <context ref="js:ordered-assignment-target"/>
+                    <context ref="typescript:ordered-optional-modifier"/>
+                    <context ref="typescript:ordered-type-annotation"/>
+                  </include>
+                </context> <!-- /_type-grouping-item-content -->
+
+              </include>
+            </context> <!-- /_type-grouping-items -->
+
+          </include>
+        </context> <!-- /_type-grouping-content -->
+
+      </include>
+    </context> <!-- /_type-grouping -->
+
+    <context id="_ordered-type-grouping" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_type-grouping"/>
+      </include>
+    </context> <!-- /_ordered-type-grouping -->
+
+    <!-- ## Function / constructor type -->
+
+    <!-- <FunctionType> / <ConstructorType> -->
+    <!-- function parameter list matched by grouping context -->
+    <context id="_function-type" once-only="true">
+      <start>=&gt;</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" 
style-ref="typescript:parenthesized-type-or-function-type-operator"/>
+        <context ref="js:comments"/>
+
+        <context id="_function-type-content">
+          <include>
+            <context ref="type-expression"/>
+          </include>
+        </context> <!-- /_function-type-content -->
+
+      </include>
+    </context> <!-- /_function-type -->
+
+    <context id="_ordered-function-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_function-type"/>
+      </include>
+    </context> <!-- /_ordered-function-type -->
+
+    <!-- ## Parenthesized type / function type -->
+
+    <!-- <ParenthesizedType> / <ParameterList> -->
+    <context id="_choice-parenthesized-type-or-function-type" 
style-ref="typescript:parenthesized-type-or-function-type" end-parent="true">
+      <start>(?=\()</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_parenthesized-type-or-function-type-content">
+          <include>
+            <context ref="_ordered-type-grouping"/>
+            <context ref="_ordered-function-type"/>
+          </include>
+        </context> <!-- /_parenthesized-type-or-function-type-content -->
+
+      </include>
+    </context> <!-- /_choice-parenthesized-type-or-function-type -->
+
+
+    <!-- # Primary type -->
+
+    <!-- <PrimaryType> -->
+    <context id="_primary-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_primary-type-content">
+          <include>
+            <context ref="_choice-parenthesized-type-or-function-type"/>
+            <context ref="typescript-type-lit:choice-tuple-type-literal"/>
+            <context ref="typescript-type-lit:choice-object-type-literal"/>
+            <context ref="typescript-type-lit:choice-numeric-type"/>
+            <context ref="js-lit:choice-string" style-ref="typescript:string-type"/>
+
+            <!-- <TypeQuery> -->
+            <context id="_choice-type-query" style-ref="typescript:type-query" end-parent="true">
+              <start>\%[typeof\%]</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+                <context ref="js:comments"/>
+
+                <context id="_type-query-content">
+                  <include>
+                    <context ref="typescript:ordered-namespace-name"/>
+                  </include>
+                </context> <!-- /_type-query-content -->
+
+              </include>
+            </context> <!-- /_choice-type-query -->
+
+            <context ref="typescript-type-lit:choice-basic-type"/>
+            <context ref="typescript-type-lit:choice-boolean-type"/>
+            <context ref="typescript-type-lit:choice-this-type"/>
+            <context ref="typescript:choice-type-reference"/>
+          </include>
+        </context> <!-- /_primary-type-content -->
+
+      </include>
+    </context> <!-- /_primary-type -->
+
+    <context id="_ordered-primary-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_primary-type"/>
+      </include>
+    </context> <!-- /_ordered-primary-type -->
+
+
+    <!-- # Conditional type
+
+         T extends U ? X : Y
+    -->
+
+    <context id="_choice-conditional-type-operator-missing-super-type" end-parent="true">
+      <start>(?=[?:])</start>
+      <end>\%{def:always-match}</end>
+    </context> <!-- /_choice-conditional-type-operator-missing-super-type -->
+
+    <context id="_choice-conditional-type-operator-missing-true-type" end-parent="true">
+      <start>(?=:)</start>
+      <end>\%{def:always-match}</end>
+    </context> <!-- /_choice-conditional-type-operator-missing-true-type -->
+
+    <context id="_conditional-type-operator-false-clause" once-only="true">
+      <start>:</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:conditional-type-operator"/>
+        <context ref="js:comments"/>
+
+        <context id="_conditional-type-operator-false-clause-content">
+          <include>
+            <context ref="type-expression"/>
+          </include>
+        </context> <!-- /_conditional-type-operator-false-clause-content -->
+
+      </include>
+    </context> <!-- /_conditional-type-operator-false-clause -->
+
+    <context id="_choice-conditional-type-operator-true-type" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_conditional-type-operator-true-type-content">
+          <include>
+            <context ref="type-expression"/>
+            <context ref="_conditional-type-operator-false-clause"/>
+          </include>
+        </context> <!-- /_conditional-type-operator-true-type-content -->
+
+      </include>
+    </context> <!-- /_choice-conditional-type-operator-true-type -->
+
+    <context id="_conditional-type-operator-true-clause" once-only="true">
+      <start>\?</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:conditional-type-operator"/>
+        <context ref="js:comments"/>
+
+        <context id="_conditional-type-operator-true-clause-content">
+          <include>
+            <context ref="_choice-conditional-type-operator-missing-true-type"/>
+            <context ref="_choice-conditional-type-operator-true-type"/>
+          </include>
+        </context> <!-- /_conditional-type-operator-true-clause-content -->
+
+      </include>
+    </context> <!-- /_conditional-type-operator-true-clause -->
+
+    <context id="_choice-conditional-type-operator-super-type" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_conditional-type-operator-super-type-content">
+          <include>
+            <context ref="type-expression"/>
+            <context ref="_conditional-type-operator-true-clause"/>
+          </include>
+        </context> <!-- /_conditional-type-operator-super-type-content -->
+
+      </include>
+    </context> <!-- /_choice-conditional-type-operator-super-type -->
+
+    <context id="_conditional-type-operators">
+      <start>\%[extends\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_conditional-type-operator-content">
+          <include>
+            <context ref="_choice-conditional-type-operator-missing-super-type"/>
+            <context ref="_choice-conditional-type-operator-super-type"/>
+          </include>
+        </context> <!-- /_conditional-type-operator-content -->
+
+      </include>
+    </context> <!-- /_conditional-type-operators -->
+
+
+    <!-- # Post-primary type
+
+         string[]
+         MyClass["property"]
+         string[][0]
+         string | void
+         T & U
+         pet is Fish
+         T extends U ? X : Y
+    -->
+
+    <context id="_post-primary-type">
+      <include>
+
+        <!-- <ArrayType> -->
+        <context id="_bracket-type-operators">
+          <start>\[</start>
+          <end>]</end>
+          <include>
+            <context sub-pattern="0" where="start" style-ref="typescript:bracket-type-operator"/>
+            <context sub-pattern="0" where="end" style-ref="typescript:bracket-type-operator"/>
+            <context ref="js:comments"/>
+
+            <context id="_bracket-type-operator-content">
+              <include>
+                <context ref="type-expression"/>
+              </include>
+            </context> <!-- /_bracket-type-operator-content -->
+
+          </include>
+        </context> <!-- /_bracket-type-operators -->
+
+        <!-- <UnionType> / <IntersectionType> -->
+        <context id="_union-intersection-type-operators">
+          <start>[|&amp;]</start>
+          <end>\%{js:before-next-token}</end>
+          <include>
+            <context sub-pattern="0" where="start" style-ref="typescript:union-intersection-type-operator"/>
+            <context ref="js:comments"/>
+
+            <context id="_union-intersection-type-operator-content">
+              <include>
+                <context ref="type-expression"/>
+              </include>
+            </context> <!-- /_union-intersection-type-operator-content -->
+
+          </include>
+        </context> <!-- /_union-intersection-type-operators -->
+
+        <context id="_type-predicate-operators">
+          <start>\%[is\%]</start>
+          <end>\%{js:before-next-token}</end>
+          <include>
+            <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+            <context ref="js:comments"/>
+
+            <context id="_type-predicate-operator-content">
+              <include>
+                <context ref="type-expression"/>
+              </include>
+            </context> <!-- /_type-predicate-operator-content -->
+
+          </include>
+        </context> <!-- /_type-predicate-operators -->
+
+        <context ref="_conditional-type-operators"/>
+      </include>
+    </context> <!-- /_post-primary-type -->
+
+    <context id="_ordered-post-primary-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_post-primary-type"/>
+      </include>
+    </context> <!-- /_ordered-post-primary-type -->
+
+
+    <!-- # Type expression -->
+
+    <context id="_choice-actual-type" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_actual-type-content">
+          <include>
+            <context ref="_ordered-pre-primary-type"/>
+            <context ref="_ordered-primary-type"/>
+            <context ref="_ordered-post-primary-type"/>
+          </include>
+        </context> <!-- /_actual-type-content -->
+
+      </include>
+    </context> <!-- /_choice-actual-type -->
+
+    <context id="_type-expression-content">
+      <include>
+        <context ref="_choice-infer-declaration"/>
+        <context ref="_choice-actual-type"/>
+      </include>
+    </context> <!-- /_type-expression-content -->
+
+    <context id="type-expression" style-ref="typescript:type-expression" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+        <context ref="_type-expression-content"/>
+      </include>
+    </context> <!-- /type-expression -->
+
+    <context id="choice-type-expression" style-ref="typescript:type-expression" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+        <context ref="_type-expression-content"/>
+      </include>
+    </context> <!-- /choice-type-expression -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-type-generics.lang 
b/data/language-specs/typescript-type-generics.lang
new file mode 100644
index 00000000..8a4e3c26
--- /dev/null
+++ b/data/language-specs/typescript-type-generics.lang
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-type-gen" name="TypeScript Type Generics" version="2.0" _section="Script" 
hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Type parameters
+
+         <T, U extends V, V extends Function>
+         <T = string>
+    -->
+
+    <!-- <Constraint> -->
+    <context id="_type-parameter-constraint" once-only="true">
+      <start>\%[extends\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_type-parameter-constraint-content">
+          <include>
+            <context ref="typescript-type-expr:type-expression"/>
+          </include>
+        </context> <!-- /_type-parameter-constraint-content -->
+
+      </include>
+    </context> <!-- /_type-parameter-constraint -->
+
+    <context id="_ordered-type-parameter-constraint" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_type-parameter-constraint"/>
+      </include>
+    </context> <!-- /_ordered-type-parameter-constraint -->
+
+    <context id="_type-parameter-default-value" once-only="true">
+      <start>=</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-parameter-default-value-content">
+          <include>
+            <context ref="typescript-type-expr:type-expression"/>
+          </include>
+        </context> <!-- /_type-parameter-default-value-content -->
+
+      </include>
+    </context> <!-- /_type-parameter-default-value -->
+
+    <context id="_ordered-type-parameter-default-value" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_type-parameter-default-value"/>
+      </include>
+    </context> <!-- /_ordered-type-parameter-default-value -->
+
+    <context id="_type-parameter-content">
+      <include>
+        <context ref="js:ordered-identifier"/>
+        <context ref="_ordered-type-parameter-constraint"/>
+        <context ref="_ordered-type-parameter-default-value"/>
+      </include>
+    </context> <!-- /_type-parameter-content -->
+
+    <context id="_type-parameters">
+      <start>,</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+        <context ref="_type-parameter-content"/>
+      </include>
+    </context> <!-- /_type-parameters -->
+
+    <!-- ## Type parameter list -->
+
+    <context id="_type-first-parameter" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+        <context ref="_type-parameter-content"/>
+      </include>
+    </context> <!-- /_type-first-parameter -->
+
+    <!-- <TypeParameters> -->
+    <context id="type-parameters-list" style-ref="typescript:type-parameters-list" once-only="true">
+      <start>&lt;</start>
+      <end>&gt;</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-parameters-list-content">
+          <include>
+            <context ref="_type-first-parameter"/>
+            <context ref="_type-parameters"/>
+          </include>
+        </context> <!-- /_type-parameters-list-content -->
+
+      </include>
+    </context> <!-- /type-parameters-list -->
+
+    <context id="ordered-type-parameters-list" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="type-parameters-list"/>
+      </include>
+    </context> <!-- /ordered-type-parameters-list -->
+
+    <!-- ## Type parameters list (for arrow function) / type assertion (cast)
+
+         Type parameters:
+         <T>(x: T) => x
+         <T, U>(x: T, y: U) => { return x + y; }
+         <T extends any>(x: T) => x
+
+         Type assertion:
+         <T>(x)
+         <T>((x) => x)
+    -->
+
+    <context id="const-type-assertion-keyword-end-parent" style-ref="typescript:type-keyword" 
end-parent="true">
+      <start>(?=\%[const\%])</start>
+      <end>const</end>
+    </context> <!-- /const-type-assertion-keyword-end-parent -->
+
+    <context id="_type-parameters-list-or-type-assertion-first-parameter" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-parameters-list-or-type-assertion-first-parameter-content">
+          <include>
+            <context ref="const-type-assertion-keyword-end-parent"/>
+            <context ref="typescript-type-expr:type-expression"/> <!-- should also match namespace-name-->
+            <context ref="_ordered-type-parameter-constraint"/>
+            <context ref="_ordered-type-parameter-default-value"/>
+          </include>
+        </context> <!-- /_type-parameters-list-or-type-assertion-first-parameter-content -->
+
+      </include>
+    </context> <!-- /_type-parameters-list-or-type-assertion-first-parameter -->
+
+    <!-- <TypeParameters> /
+         <ArrowFormalParameters> (Modified) /
+         <UnaryExpression> (Modified) (part of) -->
+    <context id="type-parameters-list-or-type-assertion" 
style-ref="typescript:type-parameters-list-or-type-assertion" once-only="true">
+      <start>&lt;</start>
+      <end>&gt;</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-parameters-list-or-type-assertion-content">
+          <include>
+            <context ref="_type-parameters-list-or-type-assertion-first-parameter"/>
+            <context ref="_type-parameters"/>
+          </include>
+        </context> <!-- /_type-parameters-list-or-type-assertion-content -->
+
+      </include>
+    </context> <!-- /type-parameters-list-or-type-assertion-->
+
+
+    <!-- # Type arguments
+
+         <string>
+         <A, B>
+    -->
+
+    <context id="_type-argument-content">
+      <include>
+        <context ref="typescript-type-expr:type-expression"/>
+      </include>
+    </context> <!-- /_type-argument-content -->
+
+    <!-- <TypeArguments> -->
+    <context id="_type-arguments-list" style-ref="typescript:type-arguments-list" once-only="true">
+      <start>&lt;</start>
+      <end>&gt;</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-arguments-list-content">
+          <include>
+
+            <context id="_type-first-argument" once-only="true">
+              <start>\%{js:before-next-token}</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_type-argument-content"/>
+              </include>
+            </context> <!-- /_type-first-argument -->
+
+            <context id="_type-arguments">
+              <start>,</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_type-argument-content"/>
+              </include>
+            </context> <!-- /_type-arguments -->
+
+          </include>
+        </context> <!-- /_type-arguments-list-content -->
+
+      </include>
+    </context> <!-- /_type-arguments-list -->
+
+    <context id="ordered-type-arguments-list" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_type-arguments-list"/>
+      </include>
+    </context> <!-- /ordered-type-arguments-list -->
+
+
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript-type-literals.lang 
b/data/language-specs/typescript-type-literals.lang
new file mode 100644
index 00000000..e387fbab
--- /dev/null
+++ b/data/language-specs/typescript-type-literals.lang
@@ -0,0 +1,419 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ This file is part of GtkSourceView
+
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
+
+ GtkSourceView is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ GtkSourceView is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<language id="typescript-type-lit" name="TypeScript Type Literals" version="2.0" _section="Script" 
hidden="true">
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
+  <definitions>
+
+    <!--
+         See typescript.lang for general notes, naming conventions, etc.
+    -->
+
+
+    <!-- # Basic type
+
+         any
+         boolean
+    -->
+
+    <define-regex id="_basic-types" extended="true">
+      (?:
+        \%[
+        (?:
+          any |
+          bigint |
+          boolean |
+          never |
+          null |
+          number |
+          object |
+          string |
+          symbol |
+          undefined |
+          unknown |
+          void
+        )
+        \%]
+      )
+    </define-regex> <!-- /_basic-types -->
+
+    <!-- <PredefinedType> -->
+    <context id="choice-basic-type" style-ref="typescript:basic-type" end-parent="true">
+      <start>(?=\%{_basic-types})</start>
+      <end>\%{_basic-types}</end>
+    </context> <!-- /choice-basic-type -->
+
+
+    <!-- # Boolean literal type
+
+         true
+         false
+    -->
+
+    <define-regex id="_boolean-types" extended="true">
+      (?: \%[ (?: false | true ) \%] )
+    </define-regex> <!-- /_boolean-literal-types -->
+
+    <!-- <PredefinedType> -->
+    <context id="choice-boolean-type" style-ref="typescript:boolean-type" end-parent="true">
+      <start>(?=\%{_boolean-types})</start>
+      <end>\%{_boolean-types}</end>
+    </context> <!-- /choice-boolean-type -->
+
+
+    <!-- # Numeric literal type
+
+         123
+         0b0101
+         0o777
+         0xfff
+    -->
+
+    <!-- does not include legacy octal integers -->
+    <context id="choice-numeric-type">
+      <include>
+        <context ref="typescript-js-lit:_choice-decimal" style-ref="typescript:decimal-type"/>
+        <context ref="typescript-js-lit:_choice-decimal-big-integer" style-ref="typescript:decimal-type"/>
+        <context ref="typescript-js-lit:_choice-binary-integer" style-ref="typescript:binary-integer-type"/>
+        <context ref="typescript-js-lit:_choice-octal-integer" style-ref="typescript:octal-integer-type"/>
+        <context ref="typescript-js-lit:_choice-hex-integer" style-ref="typescript:hex-integer-type"/>
+      </include>
+    </context> <!-- /choice-numeric-type -->
+
+
+    <!-- # This type
+
+         this
+    -->
+
+    <!-- <ThisType> -->
+    <context id="choice-this-type" style-ref="typescript:basic-type" end-parent="true">
+      <start>(?=\%[this\%])</start>
+      <end>this</end>
+    </context> <!-- /choice-this-type -->
+
+
+    <!-- # Tuple type literal
+
+         [string, any, boolean]
+    -->
+
+    <context id="_tuple-type-literal-type-content">
+      <include>
+        <context ref="js:ordered-rest-syntax"/>
+        <context ref="typescript-type-expr:type-expression"/>
+        <context ref="typescript:ordered-optional-modifier"/>
+      </include>
+    </context> <!-- /_tuple-type-literal-type-content -->
+
+    <!-- <TupleType> -->
+    <context id="choice-tuple-type-literal" style-ref="typescript:tuple-type-literal" end-parent="true">
+      <start>\[</start>
+      <end>]</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_tuple-type-literal-content">
+          <include>
+
+            <context id="_tuple-type-literal-first-type" once-only="true">
+              <start>\%{js:before-next-token}</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_tuple-type-literal-type-content"/>
+              </include>
+            </context> <!-- /_tuple-type-literal-first-type -->
+
+            <context id="_tuple-type-literal-types">
+              <start>,</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_tuple-type-literal-type-content"/>
+              </include>
+            </context> <!-- /_tuple-type-literal-types -->
+
+          </include>
+        </context> <!-- /_tuple-type-literal-content -->
+
+      </include>
+    </context> <!-- /choice-tuple-type-literal -->
+
+
+    <!-- # Object type
+
+         {
+           x: string,
+           y: any
+         }
+    -->
+
+    <!-- ## Mapped type modifier prefix
+
+         type MutableRequired<T> =
+           { -readonly [P in keyof T]-?: T[P] };
+    -->
+
+    <context id="_mapped-type-modifier-prefix" style-ref="typescript:mapped-type-modifier-prefix" 
once-only="true">
+      <match>[+-]</match>
+    </context> <!-- /_mapped-type-modifier-prefix -->
+
+    <context id="_ordered-mapped-type-modifier-prefix" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_mapped-type-modifier-prefix"/>
+      </include>
+    </context> <!-- /_ordered-mapped-type-modifier-prefix -->
+
+    <!-- ## Modifier
+
+         readonly
+    -->
+
+    <context id="_object-type-literal-modifier" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_object-type-literal-modifier-content">
+          <include>
+
+            <context id="_choice-object-type-literal-modifier-keyword" style-ref="typescript:type-keyword" 
end-parent="true">
+              <keyword>readonly</keyword>
+            </context> <!-- /_choice-object-type-literal-modifier-keyword -->
+
+          </include>
+        </context> <!-- /_object-type-literal-modifier-content -->
+
+      </include>
+    </context> <!-- /_object-type-literal-modifier -->
+
+    <context id="_ordered-object-type-literal-modifier" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_object-type-literal-modifier"/>
+      </include>
+    </context> <!-- /_ordered-object-type-literal-modifier -->
+
+    <!-- ## Index member
+
+         [index: number]: string,
+         readonly [P in keyof T]?: T[P];
+    -->
+
+    <context id="_type-annotation-or-mapped-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-annotation-or-mapped-type-content">
+          <include>
+            <context ref="typescript:choice-type-annotation"/>
+
+            <context id="_choice-mapped-type" end-parent="true">
+              <start>\%[in\%]</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context sub-pattern="0" where="start" style-ref="typescript:type-keyword"/>
+                <context ref="js:comments"/>
+
+                <context id="_mapped-type-content">
+                  <include>
+                    <context ref="typescript-type-expr:type-expression"/>
+                  </include>
+                </context> <!-- /_mapped-type-content -->
+
+              </include>
+            </context> <!-- /_choice-mapped-type -->
+
+          </include>
+        </context> <!-- /_type-annotation-or-mapped-type-content -->
+
+      </include>
+    </context> <!-- /_type-annotation-or-mapped-type -->
+
+    <context id="_ordered-type-annotation-or-mapped-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_type-annotation-or-mapped-type"/>
+      </include>
+    </context> <!-- /_ordered-type-annotation-or-mapped-type -->
+
+    <!-- <IndexSignature> -->
+    <context id="_index-property" once-only="true">
+      <start>\[</start>
+      <end>]</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_index-property-content">
+          <include>
+            <context ref="js:ordered-identifier"/>
+            <context ref="_ordered-type-annotation-or-mapped-type"/>
+          </include>
+        </context> <!-- /_index-property-content -->
+
+      </include>
+    </context> <!-- /_index-property -->
+
+    <context id="ordered-index-property" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_index-property"/>
+      </include>
+    </context> <!-- /ordered-index-property -->
+
+    <context id="_choice-object-type-literal-index-member" end-parent="true">
+      <start>(?=\[)</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_object-type-literal-index-member-content">
+          <include>
+            <context ref="ordered-index-property"/>
+            <context ref="_ordered-mapped-type-modifier-prefix"/>
+            <context ref="typescript:ordered-optional-modifier"/>
+            <context ref="typescript:ordered-type-annotation"/>
+          </include>
+        </context> <!-- /_object-type-literal-index-member-content -->
+
+      </include>
+    </context> <!-- /_choice-object-type-literal-index-member -->
+
+    <!-- ## Property / method member
+
+         property: string;
+         method?<T>(x),
+         new <T extends Function>(x, ...rest): void,
+    -->
+
+    <!-- <PropertyName> -->
+    <context id="_property-name" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_property-name-content">
+          <include>
+            <context ref="js-lit:choice-number"/>
+            <context ref="js-lit:choice-string"/>
+            <context ref="js:choice-identifier"/>
+          </include>
+        </context> <!-- /_property-name-content -->
+
+      </include>
+    </context> <!-- /_property-name -->
+
+    <context id="ordered-property-name" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_property-name"/>
+      </include>
+    </context> <!-- /ordered-property-name -->
+
+
+    <context id="_choice-object-type-literal-property-or-method-member" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_object-type-literal-property-or-method-member-content">
+          <include>
+            <context ref="typescript:ordered-constructor-modifier"/>
+            <context ref="ordered-property-name"/>
+            <context ref="typescript:ordered-optional-modifier"/>
+            <context ref="typescript-type-gen:ordered-type-parameters-list"/>
+            <context ref="js-fn:_ordered-function-parameters-list"/>
+            <context ref="typescript:ordered-type-annotation"/>
+          </include>
+        </context> <!-- /_object-type-literal-property-or-method-member-content -->
+
+      </include>
+    </context> <!-- /_choice-object-type-literal-property-or-method-member -->
+
+    <!-- ## Object type literal -->
+
+    <context id="_object-type-literal-member-content">
+      <include>
+        <context ref="_ordered-mapped-type-modifier-prefix"/>
+        <context ref="_ordered-object-type-literal-modifier"/>
+        <context ref="_choice-object-type-literal-index-member"/>
+        <context ref="_choice-object-type-literal-property-or-method-member"/>
+      </include>
+    </context> <!-- /_object-type-literal-member-content -->
+
+    <!-- <ObjectType> -->
+    <context id="choice-object-type-literal" style-ref="typescript:object-type-literal" end-parent="true">
+      <start>{</start>
+      <end>}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_object-type-literal-content">
+          <include>
+
+            <context id="_object-type-literal-first-member" once-only="true">
+              <start>\%{js:before-next-token}</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_object-type-literal-member-content"/>
+              </include>
+            </context> <!-- /_object-type-literal-first-member -->
+
+            <context id="_object-type-literal-members">
+              <start>[,;]</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_object-type-literal-member-content"/>
+              </include>
+            </context> <!-- /_object-type-literal-members -->
+
+          </include>
+        </context> <!-- /_object-type-literal-content -->
+
+      </include>
+    </context> <!-- /choice-object-type-literal -->
+
+    <context id="last-object-type-literal" style-ref="typescript:object-type-literal" end-parent="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="choice-object-type-literal"/>
+      </include>
+    </context> <!-- /last-object-type-literal -->
+
+  </definitions>
+</language>
diff --git a/data/language-specs/typescript.lang b/data/language-specs/typescript.lang
index 650ffd3e..bfa4b60f 100644
--- a/data/language-specs/typescript.lang
+++ b/data/language-specs/typescript.lang
@@ -3,12 +3,8 @@
 
  This file is part of GtkSourceView
 
- Author: Scott Martin <scott coffeeblack org>
- Copyright (C) 2004 Scott Martin <scott coffeeblack org>
- Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef memberwebs com>
- Copyright (C) 2005-2007 Marco Barisione <barisione gmail com>
- Copyright (C) 2005-2007 Emanuele Aina
- Copyright (C) 2018 Jeffery To <jeffery to gmail com>
+ Author: Jeffery To <jeffery to gmail com>
+ Copyright (C) 2019 Jeffery To <jeffery to gmail com>
 
  GtkSourceView is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
@@ -24,7 +20,7 @@
  along with this library; if not, see <http://www.gnu.org/licenses/>.
 
 -->
-<language id="ts" name="TypeScript" version="2.0" _section="Script">
+<language id="typescript" name="TypeScript" version="2.0" _section="Script">
   <metadata>
     <property 
name="mimetypes">application/typescript;application/x-typescript;text/x-typescript;text/typescript</property>
     <property name="globs">*.ts</property>
@@ -34,72 +30,680 @@
   </metadata>
 
   <styles>
-    <style id="keyword" name="Keyword" map-to="def:keyword"/>
-    <style id="basic-type" name="Basic Data Type" map-to="def:type"/>
-    <style id="utility-type" name="Utility Type" map-to="def:function"/>
+    <!-- General -->
+    <style id="type-keyword"        name="Type keyword"             map-to="js:keyword"/>
+
+    <!-- Type literals -->
+    <style id="basic-type"          name="Basic type"               map-to="def:type"/>
+    <style id="boolean-type"        name="Boolean type"             map-to="js:boolean"/>
+    <style id="decimal-type"        name="Decimal number type"      map-to="js:decimal"/>
+
+    <style id="binary-integer-type" name="Binary integer type"      map-to="js:binary-integer"/>
+    <style id="octal-integer-type"  name="Octal integer type"       map-to="js:octal-integer"/>
+    <style id="hex-integer-type"    name="Hexadecimal integer type" map-to="js:hex-integer"/>
+    <style id="string-type"         name="String type"              map-to="js:string"/>
+
+    <!-- Built-in types -->
+    <style id="built-in-library-type" name="Built-in library type"    map-to="js:built-in-constructor"/>
+
+    <!-- The following are for debugging use -->
+
+    <!-- General -->
+    <style id="optional-modifier"                             name="Optional Modifier"/>
+    <style id="definite-assignment-assertion"                 name="Definite Assignment Assertion"/>
+    <style id="type-annotation"                               name="Type Annotation"/>
+
+    <!-- Type literals -->
+    <style id="mapped-type-modifier-prefix"                   name="Mapped Type Modifier Prefix"/>
+    <style id="tuple-type-literal"                            name="Tuple Type Literal"/>
+    <style id="object-type-literal"                           name="Object Type Literal"/>
+
+    <!-- Type generics -->
+    <style id="type-parameters-list"                          name="Type Parameters List"/>
+    <style id="type-parameters-list-or-type-assertion"        name="Type Parameters List or Type Assertion"/>
+    <style id="type-arguments-list"                           name="Type Arguments List"/>
+
+    <!-- Type expressions -->
+    <style id="parenthesized-type-or-function-type"           name="Parenthesized Type or Function Type"/>
+    <style id="parenthesized-type-or-function-type-operator"  name="Parenthesized Type or Function Type 
Operator"/>
+    <style id="type-query"                                    name="Type Query"/>
+    <style id="bracket-type-operator"                         name="Bracket Type Operator"/>
+    <style id="conditional-type-operator"                     name="Conditional Type Operator"/>
+    <style id="union-intersection-type-operator"              name="Union / Intersection Type Operator"/>
+    <style id="type-expression"                               name="Type Expression"/>
+
+    <!-- JavaScript expressions -->
+    <style id="non-null-assertion-operator"                   name="Non-null Assertion Operator"/>
+
+    <!-- JavaScript statements -->
+    <style id="global-augmentation"                           name="Global Augmentation"/>
+    <style id="ambient-declaration"                           name="Ambient Declaration"/>
+    <style id="enum-declaration"                              name="Enum Declaration"/>
+    <style id="interface-declaration"                         name="Interface Declaration"/>
+    <style id="module-declaration"                            name="Module Declaration"/>
+    <style id="namespace-declaration"                         name="Namespace Declaration"/>
+    <style id="type-alias-declaration"                        name="Type Alias Declaration"/>
   </styles>
 
+  <keyword-char-class>[a-zA-Z0-9_$]</keyword-char-class>
+
   <definitions>
-    <!-- TS specific stuff (i.e. stuff which is not JS) -->
-    <context id="ts-proper">
-      <include>
-        <!-- From: https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#221-reserved-words -->
-        <context id="keywords" style-ref="keyword">
-          <keyword>abstract</keyword>
-          <keyword>declare</keyword>
-          <keyword>enum</keyword>
-          <keyword>implements</keyword>
-          <keyword>infer</keyword>
-          <keyword>interface</keyword>
-          <keyword>is</keyword>
-          <keyword>keyof</keyword>
-          <keyword>module</keyword>
-          <keyword>namespace</keyword>
-          <keyword>package</keyword>
-          <keyword>private</keyword>
-          <keyword>protected</keyword>
-          <keyword>public</keyword>
-          <keyword>readonly</keyword>
-          <keyword>type</keyword>
-        </context>
-
-        <context id="basic-types" style-ref="basic-type">
-          <!-- Other types such as `null`, `undefined`, and `void` are already
-               highlighted by JS rules which we don't want to override -->
-          <keyword>any</keyword>
-          <keyword>boolean</keyword>
-          <keyword>never</keyword>
-          <keyword>number</keyword>
-          <keyword>object</keyword>
-          <keyword>string</keyword>
-          <keyword>symbol</keyword>
-          <keyword>unknown</keyword>
-        </context>
-
-        <!-- From: https://www.typescriptlang.org/docs/handbook/utility-types.html -->
-        <context id="utility-types" style-ref="utility-type">
-          <keyword>Exclude</keyword>
-          <keyword>Extract</keyword>
-          <keyword>InstanceType</keyword>
-          <keyword>NonNullable</keyword>
-          <keyword>Omit</keyword>
-          <keyword>Partial</keyword>
-          <keyword>Pick</keyword>
-          <keyword>Readonly</keyword>
-          <keyword>Record</keyword>
-          <keyword>Required</keyword>
-          <keyword>ReturnType</keyword>
-          <keyword>ThisType</keyword>
-        </context>
-      </include>
-    </context>
-
-    <!-- Actual language definition (TS specific stuff + everything from JS) -->
-    <context id="ts" class="no-spell-check">
-      <include>
-        <context ref="ts-proper"/>
+
+    <!--
+         Based on version 1.8 of the TypeScript Language Specification
+         and the official TypeScript documentation
+         https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md
+         https://www.typescriptlang.org/
+
+         Supported level: TypeScript 3.6
+
+         Not supported yet:
+         * Decorators: Still an experimental feature of TypeScript and
+           a Stage 2 proposal for ECMAScript
+
+         Naming conventions described in javascript.lang
+    -->
+
+
+    <!-- # General -->
+
+    <!-- "unknown id" errors can occur when using a regex defined in one
+          component file in another component file
+          so we move the definitions of these regexes here
+    -->
+
+    <define-regex id="import-meta-object-keyword-suffix" extended="true">
+      (?:
+        \%{js:optional-whitespace-or-comments}
+        \.
+        \%{js:optional-whitespace-or-comments}
+        meta \%]
+      )
+    </define-regex> <!-- /import-meta-object-keyword-suffix -->
+
+    <!-- no line terminator allowed between "abstract" and "class"
+         technically, there can be abstract class declarations but not
+         abstract class expressions -->
+    <define-regex id="class-expression-keyword" extended="true">
+      (?:
+        (?:
+          \%[ abstract \%]
+          \%{js:optional-whitespace-or-comments}
+        )?
+        \%[ class \%]
+      )
+    </define-regex> <!-- / -->
+
+    <context id="js-ordered-string" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js-lit:choice-string"/>
+      </include>
+    </context> <!-- /js-ordered-string -->
+
+    <!-- ## @ts-ignore comment pragma
+
+         // @ts-ignore
+    -->
+
+    <!-- can be double- or triple-slash
+         pragma must be at start of comment
+         technically, must be at the start of the line
+         
https://github.com/microsoft/TypeScript/blob/e82d0af554d96738b2e8c7f9027e53ac8bc31007/src/compiler/program.ts#L2
+    -->
+    <context id="_ts-ignore-comment-pragmas" style-ref="js:directive" end-at-line-end="true" class="comment">
+      <start extended="true">
+        ///? \s* @ts-ignore \%]
+      </start>
+      <include>
+        <context ref="def:in-comment"/>
+      </include>
+    </context> <!-- /_ts-ignore-comment-pragmas -->
+
+    <context id="_ts-ignore-comment-pragmas-no-extend-parent" style-ref="js:directive" 
end-at-line-end="true" class="comment" extend-parent="false">
+      <start extended="true">
+        ///? \s* @ts-ignore \%]
+      </start>
+      <include>
+        <context ref="def:in-comment"/>
+      </include>
+    </context> <!-- /_ts-ignore-comment-pragmas-no-extend-parent -->
+
+    <!-- ## Triple-slash directive
+
+         /// <reference path="..."
+
+         can only be preceded by comments or other triple-slash
+         directives (i.e. at the top of a file)
+    -->
+
+    <context id="_triple-slash-directives" style-ref="js:directive" end-at-line-end="true" class="comment">
+      <start extended="true">
+        /// \s* &lt;
+        (
+          amd-module |
+          amd-dependency |
+          reference
+        )
+        \s
+      </start>
+    </context> <!-- /_triple-slash-directives -->
+
+    <!-- ## Namespace name
+
+         Validation.StringValidator
+    -->
+
+    <context id="_namespace-name-part-content">
+      <include>
+        <context ref="js:identifier"/>
+      </include>
+    </context> <!-- /_namespace-name-part-content -->
+
+    <!-- <NamespaceName> -->
+    <context id="choice-namespace-name" end-parent="true">
+      <start>(?=\%{js:identifier-start})</start>
+      <end>\%{def:always-match}</end>
+      <include>
+        <!-- no comments here -->
+
+        <context id="_namespace-name-content">
+          <include>
+            <context ref="_namespace-name-part-content"/>
+
+            <context id="_namespace-name-parts">
+              <start>\.(?=\%{js:identifier-start})</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <!-- no comments here -->
+                <context sub-pattern="0" where="start" style-ref="js:identifier"/>
+                <context ref="_namespace-name-part-content"/>
+              </include>
+            </context> <!-- /_namespace-name-parts -->
+
+            <context id="_namespace-name-trailing-dot-error-end-parent" style-ref="js:error" 
end-parent="true">
+              <start>(?=\.)</start>
+              <end>\.</end>
+            </context> <!-- /_namespace-name-trailing-dot-error-end-parent -->
+
+          </include>
+        </context> <!-- /_namespace-name-content -->
+
+      </include>
+    </context> <!-- /choice-namespace-name -->
+
+    <context id="ordered-namespace-name" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="choice-namespace-name"/>
+      </include>
+    </context> <!-- /ordered-namespace-name -->
+
+    <!-- ## Constructor modifier -->
+
+    <context id="constructor-modifier" style-ref="type-keyword" once-only="true">
+      <keyword>new</keyword>
+    </context> <!-- /constructor-modifier -->
+
+    <context id="ordered-constructor-modifier" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="constructor-modifier"/>
+      </include>
+    </context> <!-- /ordered-constructor-modifier -->
+
+    <!-- ## Optional modifier
+
+         let a: (x?: number) => void;
+         let a: { property?; method?(): void };
+         let a = { method?() { ... } };
+         class MyClass { property?; method?() { ... } }
+         function fn (x?) { ... }
+    -->
+
+    <context id="_optional-modifier" style-ref="optional-modifier" once-only="true">
+      <match>\?</match>
+    </context> <!-- /_optional-modifier -->
+
+    <context id="ordered-optional-modifier" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_optional-modifier"/>
+      </include>
+    </context> <!-- /ordered-optional-modifier -->
+
+    <!-- ## Definite assignment assertion
+
+         var a!: number;
+         class MyClass { property!: string; }
+    -->
+
+    <context id="_definite-assignment-assertion" style-ref="definite-assignment-assertion" once-only="true">
+      <match>!</match>
+    </context> <!-- /_definite-assignment-assertion -->
+
+    <context id="ordered-definite-assignment-assertion" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_definite-assignment-assertion"/>
+      </include>
+    </context> <!-- /ordered-definite-assignment-assertion -->
+
+    <!-- ## this parameter or assignment target -->
+
+    <context id="_this-parameter-or-assignment-target" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_this-parameter-or-assignment-target-content">
+          <include>
+
+            <context id="_choice-this-parameter" style-ref="js:keyword" end-parent="true">
+              <keyword>this</keyword>
+            </context> <!-- /_choice-this-parameter -->
+
+            <context id="_js-choice-assignment-target" end-parent="true">
+              <start>\%{js:before-next-token}</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:embedded-lang-hooks"/>
+                <context ref="js:comments"/>
+                <context ref="js:_assignment-target-content"/>
+              </include>
+            </context> <!-- /_js-choice-assignment-target -->
+
+          </include>
+        </context> <!-- /_this-parameter-or-assignment-target-content -->
+
+      </include>
+    </context> <!-- /_this-parameter-or-assignment-target -->
+
+    <context id="ordered-this-parameter-or-assignment-target" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_this-parameter-or-assignment-target"/>
+      </include>
+    </context> <!-- /ordered-this-parameter-or-assignment-target -->
+
+
+    <!-- # Types -->
+
+    <!-- ## Type name -->
+
+    <context id="_built-in-library-types" style-ref="built-in-library-type">
+      <keyword>Exclude</keyword>
+      <keyword>Extract</keyword>
+      <keyword>InstanceType</keyword>
+      <keyword>NonNullable</keyword>
+      <keyword>Omit</keyword>
+      <keyword>Partial</keyword>
+      <keyword>Pick</keyword>
+      <keyword>ReadonlyArray</keyword>
+      <keyword>Readonly</keyword>
+      <keyword>Record</keyword>
+      <keyword>Required</keyword>
+      <keyword>ReturnType</keyword>
+      <keyword>ThisType</keyword>
+    </context> <!-- /_built-in-library-types -->
+
+    <context id="_choice-type-name-identifier-only" end-parent="true">
+      <start extended="true">
+        (?= (?&gt; \%{js:identifier} ) (?! \. ) )
+      </start>
+      <end>\%{def:always-match}</end>
+      <include>
+        <!-- no comments here -->
+
+        <context id="_type-name-identifier-only-content">
+          <include>
+            <context ref="_built-in-library-types"/>
+            <context ref="js-val:_constructors"/>
+            <context ref="js:identifier"/>
+          </include>
+        </context> <!-- /_type-name-identifier-only-content -->
+
+      </include>
+    </context> <!-- /_choice-type-name-identifier-only -->
+
+    <context id="_type-name" end-parent="true">
+      <start>(?=\%{js:identifier-start})</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <!-- no comments here -->
+
+        <context id="_type-name-content">
+          <include>
+            <context ref="_choice-type-name-identifier-only"/>
+            <context ref="choice-namespace-name"/>
+          </include>
+        </context> <!-- /_type-name-content -->
+
+      </include>
+    </context> <!-- /_type-name -->
+
+    <context id="ordered-type-name" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_type-name"/>
+      </include>
+    </context> <!-- /ordered-type-name -->
+
+
+    <!-- ## Type reference -->
+
+    <!-- ### Import type (prefix to type reference)
+
+         import("module").ModuleType
+    -->
+
+    <context id="_import-type-argument" once-only="true">
+      <start>\(</start>
+      <end>\)</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_import-type-argument-content">
+          <include>
+            <context ref="js-ordered-string"/>
+          </include>
+        </context> <!-- /_import-type-argument-content -->
+
+      </include>
+    </context> <!-- /_import-type-argument -->
+
+    <context id="_ordered-import-type-argument" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_import-type-argument"/>
+      </include>
+    </context> <!-- /_ordered-import-type-argument -->
+
+    <context id="_import-type-trailing-dot" once-only="true">
+      <match>\.</match>
+    </context> <!-- /_import-type-trailing-dot -->
+
+    <context id="_ordered-import-type-trailing-dot" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_import-type-trailing-dot"/>
+      </include>
+    </context> <!-- /_ordered-import-type-trailing-dot -->
+
+    <context id="_import-type" once-only="true">
+      <start>\%[import\%]</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context sub-pattern="0" where="start" style-ref="type-keyword"/>
+        <context ref="js:comments"/>
+
+        <context id="_import-type-content">
+          <include>
+            <context ref="_ordered-import-type-argument"/>
+            <context ref="_ordered-import-type-trailing-dot"/>
+          </include>
+        </context> <!-- /_import-type-content -->
+
+      </include>
+    </context> <!-- /_import-type -->
+
+    <context id="_ordered-import-type" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="_import-type"/>
+      </include>
+    </context> <!-- /_ordered-import-type -->
+
+    <!-- ### Type reference -->
+
+    <!-- <TypeReference> -->
+    <context id="choice-type-reference" end-parent="true">
+      <start>(?=\%{js:identifier-start})</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-reference-content">
+          <include>
+            <context ref="_ordered-import-type"/>
+            <context ref="ordered-type-name"/>
+            <context ref="typescript-type-gen:ordered-type-arguments-list"/>
+          </include>
+        </context> <!-- /_type-reference-content -->
+
+      </include>
+    </context> <!-- /choice-type-reference -->
+
+
+    <!-- ## Type reference list (interface extends, class
+         implements) -->
+
+    <context id="_type-reference-list-reference-content">
+      <include>
+        <context ref="choice-type-reference"/>
+      </include>
+    </context> <!-- /_type-reference-list-reference-content -->
+
+    <!-- <ClassOrInterfaceType> -->
+    <context id="type-reference-list" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-reference-list-content">
+          <include>
+
+            <context id="_type-reference-list-first-reference" once-only="true">
+              <start>\%{js:before-next-token}</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_type-reference-list-reference-content"/>
+              </include>
+            </context> <!-- /_type-reference-list-first-reference -->
+
+            <context id="_type-reference-list-references">
+              <start>,</start>
+              <end>\%{js:before-next-token}</end>
+              <include>
+                <context ref="js:comments"/>
+                <context ref="_type-reference-list-reference-content"/>
+              </include>
+            </context> <!-- /_type-reference-list-references -->
+
+          </include>
+        </context> <!-- /_type-reference-list-content -->
+
+      </include>
+    </context> <!-- /type-reference-list -->
+
+
+    <!-- ## Type annotation
+
+         : string
+    -->
+
+    <!-- <TypeAnnotation> -->
+    <context id="choice-type-annotation" style-ref="type-annotation" end-parent="true">
+      <start>:</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="js:comments"/>
+
+        <context id="_type-annotation-content">
+          <include>
+            <context ref="typescript-type-expr:type-expression"/>
+          </include>
+        </context> <!-- /_type-annotation-content -->
+
+      </include>
+    </context> <!-- /choice-type-annotation -->
+
+    <context id="ordered-type-annotation" once-only="true">
+      <start>\%{js:before-next-token}</start>
+      <end>\%{js:before-next-token}</end>
+      <include>
+        <context ref="choice-type-annotation"/>
+      </include>
+    </context> <!-- /ordered-type-annotation -->
+
+
+    <!-- Approximate code order for component files:
+         * typescript-type-literals.lang
+         * typescript-type-generics.lang
+         * typescript-type-expressions.lang
+         * typescript-js-literals.lang
+         * typescript-js-values.lang
+         * typescript-js-functions-classes.lang
+         * typescript-js-expressions.lang
+         * typescript-js-statements.lang
+         * typescript-js-modules.lang
+    -->
+
+
+    <!-- using a context from a component file in a <replace> before
+         referencing a context from the file causes "unknown context"
+         errors -->
+    <context id="unknown-context-error-workaround">
+      <include>
+        <context ref="typescript-js-lit:choice-number"/>
+        <context ref="typescript-js-val:global-values"/>
+        <context ref="typescript-js-fn:function-parameters-content"/>
+        <context ref="typescript-js-expr:grouping-item-content"/>
+        <context ref="typescript-js-st:class-declarations"/>
+        <context ref="typescript-js-mod:export-declaration-content"/>
+      </include>
+    </context> <!-- /unknown-context-error-workaround -->
+
+
+    <!-- # TypeScript additions -->
+
+    <!-- ## General -->
+
+    <context id="_comments">
+      <include>
+        <context ref="_ts-ignore-comment-pragmas"/>
+        <context ref="js:comments" original="true"/>
+      </include>
+    </context> <!-- /_comments -->
+
+    <context id="_comments-no-extend-parent">
+      <include>
+        <context ref="_ts-ignore-comment-pragmas-no-extend-parent"/>
+        <context ref="js:comments-no-extend-parent" original="true"/>
+      </include>
+    </context> <!-- /_comments-no-extend-parent -->
+
+    <replace id="js:comments" ref="_comments"/>
+    <replace id="js:comments-no-extend-parent" ref="_comments-no-extend-parent"/>
+
+
+    <!-- ## Literals -->
+
+    <replace id="js-lit:choice-number" ref="typescript-js-lit:choice-number"/>
+
+
+    <!-- ## Values -->
+
+    <replace id="js-val:global-values" ref="typescript-js-val:global-values"/>
+
+
+    <!-- ## Functions and classes -->
+
+    <!-- ### Function expression -->
+
+    <replace id="js-fn:_function-parameters-content" ref="typescript-js-fn:function-parameters-content"/>
+    <replace id="js-fn:_function-first-parameter" ref="typescript-js-fn:function-first-parameter"/>
+    <replace id="js-fn:_function-expression-content" ref="typescript-js-fn:function-expression-content"/>
+
+    <!-- ### Method definition -->
+
+    <replace id="js-fn:_method-definition-content" ref="typescript-js-fn:method-definition-content"/>
+
+    <!-- ### Class expression -->
+
+    <replace id="js-fn:_class-optional-name-content" ref="typescript-js-fn:class-optional-name-content"/>
+
+    <replace id="js-fn:_class-extends-clause-content" ref="typescript-js-fn:class-extends-clause-content"/>
+
+    <replace id="js-fn:_class-body-member-content" ref="typescript-js-fn:class-body-member-content"/>
+
+    <replace id="js-fn:_class-expression-content" ref="typescript-js-fn:class-expression-content"/>
+    <replace id="js-fn:choice-class-expression" ref="typescript-js-fn:choice-class-expression"/>
+    <replace id="js-fn:_class-expression-required-name-content" 
ref="typescript-js-fn:class-expression-required-name-content"/>
+    <replace id="js-fn:choice-class-expression-required-name" 
ref="typescript-js-fn:choice-class-expression-required-name"/>
+
+
+    <!-- ## Expressions -->
+
+    <!-- ### Grouping / arrow function parameters -->
+
+    <replace id="js-expr:_grouping-item-content" ref="typescript-js-expr:grouping-item-content"/>
+    <replace id="js-expr:_choice-grouping" ref="typescript-js-expr:choice-grouping-and-type-annotation"/>
+
+    <!-- ### Post-primary expression -->
+
+    <replace id="js-expr:_post-primary-expression" ref="typescript-js-expr:post-primary-expression"/>
+
+    <!-- ### Pre-LHS expression -->
+
+    <replace id="js-expr:_pre-lhs-expression" ref="typescript-js-expr:pre-lhs-expression"/>
+
+    <!-- ### Post-LHS expression -->
+
+    <replace id="js-expr:_post-lhs-expression-without-comma" 
ref="typescript-js-expr:post-lhs-expression-without-comma"/>
+
+    <replace id="js-expr:_post-lhs-expression-with-comma" 
ref="typescript-js-expr:post-lhs-expression-with-comma"/>
+
+
+    <!-- ## Statements -->
+
+    <!-- ### Class declaration -->
+
+    <replace id="js-st:_class-declarations" ref="typescript-js-st:class-declarations"/>
+
+    <!-- ### Variable declaration -->
+
+    <replace id="js-st:_variable-declaration-item-content" 
ref="typescript-js-st:variable-declaration-item-content"/>
+
+    <!-- ### Statements -->
+
+    <replace id="js-st:statements" ref="typescript-js-st:statements"/>
+
+
+    <!-- ## Modules -->
+
+    <!-- ### Export declaration -->
+
+    <replace id="js-mod:_export-declaration-content" ref="typescript-js-mod:export-declaration-content"/>
+
+    <!-- ### Import declaration -->
+
+    <replace id="js-mod:_import-default-content" ref="typescript-js-mod:import-default-content"/>
+
+    <replace id="js-mod:import-declarations" ref="typescript-js-mod:import-declarations"/>
+
+
+    <!-- # Main context -->
+
+    <context id="typescript" class="no-spell-check">
+      <include>
+        <context ref="_triple-slash-directives"/>
         <context ref="js:js"/>
       </include>
-    </context>
+    </context> <!-- /typescript -->
+
   </definitions>
 </language>
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 578f211e..f633f842 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -143,7 +143,16 @@ data/language-specs/tera.lang
 data/language-specs/texinfo.lang
 data/language-specs/thrift.lang
 data/language-specs/toml.lang
+data/language-specs/typescript-js-expressions.lang
+data/language-specs/typescript-js-functions-classes.lang
+data/language-specs/typescript-js-literals.lang
+data/language-specs/typescript-js-modules.lang
+data/language-specs/typescript-js-statements.lang
+data/language-specs/typescript-js-values.lang
 data/language-specs/typescript.lang
+data/language-specs/typescript-type-expressions.lang
+data/language-specs/typescript-type-generics.lang
+data/language-specs/typescript-type-literals.lang
 data/language-specs/vala.lang
 data/language-specs/vbnet.lang
 data/language-specs/verilog.lang
diff --git a/tests/syntax-highlighting/file.ts b/tests/syntax-highlighting/file.ts
index 7a2044c1..513bae2a 100644
--- a/tests/syntax-highlighting/file.ts
+++ b/tests/syntax-highlighting/file.ts
@@ -1,85 +1,1365 @@
-// Declarations
-declare var v: any;
-
-// Namespaces
-namespace N {}
-
-// Modules
-declare module '*.txt' {
-  export const txt: string;
-}
-
-// Types
-let num: number = 1;
-let str: string = 'str';
-let bool: boolean = true;
-let obj: object = {};
-let sym: symbol = Symbol();
-let something: any;
-let dunno: unknown;
-let none: null = null;
-let undef: undefined = undefined;
-// Void type
-function nothing(): void {
-  return;
-}
-// Never type
-function err(): never {
-  throw new Error();
-}
-
-// Custom types
-type T = Array<string | number>;
-type Keys = keyof {a: number; b: number};
-type Inferred<T> = T extends {a: infer U; b: infer U} ? U : never;
-
-// Utility types
-let part: Partial<{a: number; b: number}>;
-let ro: Readonly<string[]>;
-let rec: Record<string, any>;
-let pick: Pick<{a: number; b: number}, 'a'>;
-let omit: Omit<{a: number; b: number}, 'b'>;
-let exc: Exclude<'a' | 'b' | 'c', 'a'>;
-let ext: Extract<'a' | 'b' | 'c', 'a' | 'f'>;
-let nonNull: NonNullable<string | null>;
-let retT: ReturnType<() => string>;
-let inst: InstanceType<typeof Number>;
-let req: Required<{a?: number; b?: string}>;
-let thisT: ThisType<any>;
-
-// Interfaces
-interface I {
-  prop: T;
-}
-interface II extends I {
-  readonly r: string;
-}
-
-// Classes
-abstract class C implements II {
-  prop: T;
-  readonly r: string;
-
-  public pub: number;
-  protected prot: number;
-  private priv: number;
-
-  constructor(private priv2: string) {}
-
-  public abstract abst(): void;
-}
-
-// Enums
-enum Dir {
-  Up = 1,
-  Down,
-}
-const enum E {
-  Yes = 1,
-  No = Yes - 1,
-}
-
-// Type guards
-function isNumber(n: any): n is number {
-  return typeof n === 'number';
+/*
+ * Type
+ */
+
+// Predefined type
+let a: any;
+let a: bigint;
+let a: boolean;
+let a: null;
+let a: number;
+let a: object;
+let a: string;
+let a: symbol;
+let a: undefined;
+let a: unknown;
+let a: void;
+function fn(): never { throw new Error(); }
+
+// Parenthesized type
+let a: ( string );
+
+// Type reference
+let a: T;
+let a: Super.Sub;
+// Bullt-in constructors
+let a: Array<string>;
+let a: Function;
+let a: RegExp;
+// Built-in utility types
+let a: ReadonlyArray<number>;
+let a: Partial<Person>;
+let a: Readonly<Person>;
+// Import type
+let a: import("module").ModuleType;
+
+// Object type
+let a: {
+    // Property signature
+    property;
+    property?,
+    property: string;
+    readonly property?: string,
+
+    // Call signature
+    ();
+    <T>(x),
+    (this: void, x: number, y?: string): void;
+    <T extends Function>(x, ...rest): void,
+
+    // Construct signature
+    new ();
+    new <T>(x),
+    new (x: number, y?: string): void;
+    new <T extends Function>(x, ...rest): void,
+
+    // Index signature
+    [index: number]: string;
+    readonly [prop: string]: any,
+
+    // Method signature
+    method();
+    method?<T>(x),
+    method?(this: void, x: number, y?: string): void;
+    method<T extends Function>(x, ...rest): void,
+
+    // Mapped type
+    readonly [P in keyof T]?: T[P],
+    -readonly [P in keyof T]+?: T[P];
+};
+
+// Array type
+let a: string[];
+
+// Indexed access type (lookup type)
+let a: MyType["property"];
+
+// Tuple type
+let a: [string];
+let a: [string, number, boolean?]; // optional element
+let a: [string, ...number[]]; // rest elements
+
+// Type query
+let a: typeof Super.Sub;
+
+// This type
+let a: this;
+
+// String literal type
+let a: 'string';
+let a: "string";
+
+// Numeric literal type
+let a: 123;
+let a: 0b0101;
+let a: 0o777;
+let a: 0xfff;
+// Numeric separators with BigInt
+let a: 1_23n;
+let a: 0b01_01n;
+let a: 0o7_77n;
+let a: 0xf_f_fn;
+
+// Boolean literal type
+let a: true;
+let a: false;
+
+// "unique symbol" subtype
+let a: unique symbol;
+let a: unique /* comment */ symbol;
+let a: unique /* comment
+*/ symbol;
+let a: unique // comment
+symbol;
+
+// Union / intersection type
+let a: string | number;
+let a: string & number;
+
+// Type predicate (user-defined type guard)
+function isString(x: any): x is string {}
+
+// Indexed type query (keyof)
+let a: keyof T;
+
+// Conditional type
+let a: T extends number ? number[] : T[];
+
+// Type inference (in conditional types)
+let a: T extends (infer U)[] ? U : any;
+let a: T extends (...args: any[]) => infer U ? U : any;
+let a: T extends Promise<infer U> ? U : any;
+
+// Function type
+let a: () => void;
+let a: <T>(x) => T;
+let a: (this: void, x: number, y?: string) => string; // this parameter
+let a: <T extends Function>(x, ...rest) => T;
+
+let a: ([x, y]: [string, number], [z, w]: [string, number]) => void;
+let a: ({ x: a, y: b }: { x: number, y: string }, { z: c, w: d }: { z: number, w: string }) => void;
+
+// Constructor type
+let a: new () => void;
+let a: new <T>(x) => T;
+let a: new (x: number, y?: string) => string;
+let a: new <T extends Function>(x, ...rest) => T;
+
+let a: new ([x, y]: [string, number], [z, w]: [string, number]) => void;
+let a: new ({ x: a, y: b }: { x: number, y: string }, { z: c, w: d }: { z: number, w: string }) => void;
+
+// Readonly array / tuple types
+let a: readonly string[];
+let a: readonly /* comment */ [string, string];
+
+// Parenthesized type vs parameters list of function type
+// Parenthesized
+let a: (string);
+let a: ((string: string) => void);
+// Parameters list
+let a: (string: string) => void;
+let a: (string?
+: string) => void;
+let a: (string /* comment */ ,
+string) => void;
+let a: (this: void) => void;
+let a: (this /* comment */ : void) => void;
+let a: (...string
+: string[]) => void;
+// Not correctly highlighted
+let a: (string
+: string) => void;
+let a: (this /* comment
+*/ : void) => void;
+let a: (... string
+: string[]) => void;
+let a: (... /* comment */ string
+: string[]) => void;
+
+
+/*
+ * Type parameters
+ */
+
+function fn<T>() {}
+function fn<T, U>() {}
+function fn<T = string, U extends V = any, V extends Function>() {}
+function fn<T, K extends keyof T>() {}
+
+
+/*
+ * Type parameters (for arrow function) / type assertion (cast)
+ */
+
+// Type parameters
+a = <T>(x) => x;
+a = <T, U>(x) => x;
+a = <T = string, U extends V = any, V extends Function>(x) => x;
+a = <T, K extends keyof T>(x) => x;
+
+// Type assertion
+a = <string>obj;
+a = <const>obj;
+
+
+/*
+ * Type arguments
+ */
+
+fn<string>();
+fn<string, number>();
+
+
+/*
+ * Type annotation
+ */
+
+let a: string;
+
+
+/*
+ * TypeScript-specific operators
+ */
+
+/* as operator (type assertion / cast) */
+
+( obj as string );
+( obj as const );
+
+
+// Non-null assertion operator (post-fix !)
+( a!.method() );
+
+
+/*
+ * TypeScript-specific statements and declarations
+ */
+
+/* @ts-ignore comment pragmas */
+
+// Valid pragmas
+//@ts-ignore
+/// @ts-ignore add reason here
+{
+    //  @ts-ignore
+}
+
+// Invalid pragmas
+// @ ts-ignore
+/// @TS-IGNORE
+/* @ts-ignore */
+
+
+/* Triple-slash directives */
+
+// Valid directives
+///<reference path="foo" />
+/// <reference lib="es2017.string" />
+/// <amd-module name="bar" />
+///  <amd-dependency />
+
+// Invalid directives
+/// comment
+/// <comment
+/// < reference
+/// <reference-path
+
+
+/* Ambient declaration */
+
+declare let a;
+declare const a: number, b: string;
+declare function fn();
+declare function fn<T>(x): T;
+declare function fn(this: void, x: number, y?: string): string;
+declare function fn<T extends Function>(x, ...rest): T;
+declare class MyClass extends Super implements Super.Sub {}
+declare abstract class MyClass<T extends MyClass> extends Super<string> {}
+declare abstract /* comment */ class MyClass<T extends MyClass> extends Super<string> {}
+declare enum Color { Red, Green, Blue }
+declare const enum Num { One = 1, Two, Three }
+declare global {}
+declare module Super.Sub {}
+declare module "module" {}
+declare module "module";
+declare namespace Super.Sub {}
+
+
+/* Enum declaration */
+
+enum Color {
+    Red,
+    Green,
+    Blue
+}
+const enum Num {
+    One = 1,
+    Two = '2',
+    Three
+}
+
+
+/* Interface declaration */
+
+interface MyObj {
+    property,
+    <T extends Function>(): void,
+    readonly [index: number]: string,
+    method?(this: void, x: number, y?: string): void
+}
+interface Square<T> extends Shape, PenStroke<number> {
+    sideLength: number;
+}
+
+
+/* Module declaration */
+
+module Super.Sub { // namespace ("internal module")
+    let a = 1;
+}
+module "module" { // "external module"
+    let a = 1;
+}
+
+
+/* Namespace declaration */
+
+namespace Super.Sub {
+    let a = 1;
+}
+
+
+/* Type alias declaration */
+
+type Name = string;
+type NameResolver = () => string;
+type NameOrResolver = Name | NameResolver;
+type Container<T> = { value: T };
+
+
+/*
+ * Modifications to existing statements and declarations
+ */
+
+/* Literals */
+
+// Numeric separators (stage 2 proposal)
+let decimal = 1_000_000;
+let binary_integer = 0b1100_0011_1101_0001;
+let octal_integer = 0o123_456_700;
+let hex_integer = 0xFF_0C_00_FF;
+// Numeric separators with BigInt
+let decimal_bigint = 1_000_000n;
+let binary_bigint = 0B1100_0011_1101_0001n;
+let octal_bigint = 0O123_456_700n;
+let hex_bigint = 0XFF_0C_00_FFn;
+
+
+/* Object literal */
+
+a = {
+    // Property value vs type annotation 
+    property: void 1,
+    method(): void {},
+
+    // Type parameters, type annotations for methods
+    method(this: void, x: number, y?: string, z: number = 0, ...rest: any[]): void {},
+    method<T extends Function>(x: T): T {},
+    get property(): string {},
+    set property(value: string) {}
+};
+
+
+/* Function expression / declaration */
+
+// Type parameters, type annotations
+a = function (this: void, x: number, y?: string, z: number = 1, ...rest: any[]): void {};
+a = function <T extends Function>(x: T): T {};
+function fn(this: void, x: number, y?: string, z: number = 1, ...rest: any[]): void {}
+function fn<T extends Function>(x: T): T {}
+
+
+/* Grouping / arrow function parameters */
+
+// Type parameters, type annotations
+a = (x: number, y?: string, z: number = 0, ...rest: any[]): void => x + y;
+a = <T extends Function>(x: T): T => x;
+
+
+/* Class expression / declaration */
+
+// Abstract class
+abstract class MyClass {}
+abstract /* comment */ class MyClass {}
+abstract /* comment
+*/ class MyClass {} // correctly highlighted, because abstract cannot be followed by a line terminator
+
+// Type parameters
+a = class <T> {};
+a = class <T extends MyClass> extends Super {};
+class MyClass<T> {}
+class MyClass<T extends MyClass> extends Super {}
+
+// Extends clause with type arguments
+a = class extends Super<string> {};
+class MyClass extends Super<string> {}
+
+// Implements clause
+a = class implements Super.Sub {};
+a = class extends Super implements Super.Sub {};
+class MyClass implements Super.Sub {}
+class MyClass extends Super implements Super.Sub {}
+
+a = class {
+    // Class property
+    property;
+    public property?: number;
+    private property!: number;
+    protected static readonly property: number = 1;
+    abstract property;
+
+    // Accessibility modifiers, type annotation, parameter properties for constructor
+    private constructor(public x: number, private y?: string);
+    protected constructor(protected x: number = 1) {}
+
+    // Accessibility modifiers, type parameters, type annotation for class method
+    public method?(this: void, x: number, y?: string, z: number = 1, ...rest: any[]): void;
+    private static method<T extends Function>(x: T): T {}
+    public abstract method();
+    protected get property(): string {}
+    static set property(value: string) {}
+    abstract get property(): string {}
+
+    // Index members
+    [index: number]: string;
+    readonly [prop: string]: any;
+};
+
+
+/* Expression */
+
+// Dynamic import expression (ES2020)
+a = import('module');
+import("module").then(module => {});
+
+// import.meta (stage 3 proposal)
+a = import.meta.__dirname;
+a = import . /* comment */ meta.__dirname;
+a = import . /* comment
+*/ meta.__dirname; // incorrectly highlighted
+a = import // comment
+.meta.__dirname; // incorrectly highlighted
+
+// Type arguments for function calls
+fn<string>();
+fn<string, number>();
+fn < string > /* comment */ ();
+// Not correctly highlighted (interpreted as less than / equal than)
+fn<string
+>();
+fn<string>
+();
+fn<string> /* comment
+*/ ();
+fn<string> // comment
+();
+
+// Type arguments for tagged templates
+myTag<string>`Template literal`;
+myTag<string, number>`Template literal`;
+myTag < string > /* comment */ `Template literal`;
+// Not correctly highlighted (interpreted as less than / equal than)
+myTag<string
+>`Template literal`;
+myTag<string>
+`Template literal`;
+myTag<string> /* comment
+*/ `Template literal`;
+myTag<string> // comment
+`Template literal`;
+
+// Type assertion
+a = <string>obj;
+a = <const>obj;
+
+
+/* Export / import declaration */
+
+// Export ambient declaration
+export declare let a;
+export declare const a: number, b: string;
+export declare function fn();
+export declare function fn<T>(x): T;
+export declare function fn(this: void, x: number, y?: string): string;
+export declare function fn<T extends Function>(x, ...rest): T;
+export declare class MyClass extends Super implements Super.Sub {}
+export declare abstract class MyClass<T extends MyClass> extends Super<string> {}
+export declare abstract /* comment */ class MyClass<T extends MyClass> extends Super<string> {}
+export declare enum Color { Red, Green, Blue }
+export declare const enum Num { One = 1, Two, Three }
+export declare module Super.Sub {}
+export declare module "module" {}
+export declare namespace Super.Sub {}
+
+// Export enum declaration
+export enum Color { Red, Green, Blue }
+export const enum Num { One = 1, Two, Three }
+
+// Export interface declaration
+export interface MyObj {}
+export interface Square<T> extends Shape, PenStroke<number> {}
+
+// Export module declaration
+export module Super.Sub {}
+
+// Export namespace declaration
+export namespace Super.Sub {}
+
+// Export type alias declaration
+export type Name = string;
+export type NameResolver = () => string;
+export type NameOrResolver = Name | NameResolver;
+export type Container<T> = { value: T };
+
+// Export assignment
+export = obj;
+
+// Export as namespace (UMD module definition)
+export as namespace myModule;
+
+// Import alias
+import shortname = Long.Namespace.Name;
+
+// Import require
+import mod = require("module");
+
+
+/* Variable declaration */
+
+// Type annotation
+const a: number;
+let a: number = 1, b: string;
+var { a, b }: { a: number, b: string } = { a: 1, b: 'b' };
+
+// Definite assignment assertion
+let a!: number;
+
+
+// from file.js
+
+/*
+ * Expressions (in expression statements)
+ */
+
+/*
+ * Literals
+ */
+
+/* Keyword values */
+
+var NULL = null;
+var TRUE = true;
+var FALSE = false;
+
+
+/* Number */
+
+var decimal1 = 0;
+var decimal2 = 123.45;
+var decimal3 = .66667;
+var decimal4 = 10e20;
+var decimal5 = 0.2e+1;
+var decimal6 = .5E-20;
+var hex1 = 0xDEADBEEF;
+var hex2 = 0Xcafebabe;
+
+// ES2015 binary and octal numbers
+let binary1 = 0b1010;
+let binary2 = 0B00001111;
+let octal1 = 0o0123;
+let octal2 = 0O4567;
+
+// Legacy octal numbers
+var legacy_octal1 = 01;
+var legacy_octal2 = 007;
+
+// BigInt (ES2020)
+var decimal1 = 0n;
+var decimal2 = 123n;
+var hex1 = 0xDEADBEEFn;
+var hex2 = 0Xcafebaben;
+var binary1 = 0b1010n;
+var binary2 = 0B00001111n;
+var octal1 = 0o0123n;
+var octal2 = 0O4567n;
+
+
+/* String */
+
+// Escape sequences
+'\b\f\n\r\t\v\0\'\"\\'; // Single character escape
+"\1\01\001";            // Octal escape (Annex B)
+'\xA9';                 // Hexadecimal escape
+"\u00a9";               // Unicode escape
+'\u{1D306}';            // Unicode code point escape
+
+
+/* Array literal */
+
+[];
+[1];
+[1.0, 'two', 0x03];
+
+// Trailing comma
+[
+    [1,2,3],
+    [4,5,6],
+];
+
+// Spread syntax
+[1, ...a, 2];
+
+
+/* Object literal */
+
+a = {};
+a = { prop: 'value' };
+a = { prop: 'value', extends: 1 };
+
+// Trailing comma
+a = {
+    prop: 'value',
+    extends: 1,
+};
+
+// Shorthand property names
+a = { b, c, d };
+
+// Getter / setter
+a = {
+    _hidden: null,
+    get property() { return _hidden; },
+    set property(value) { this._hidden = value; }
+};
+
+// Shorthand function notation
+a = {
+    method() {},
+    *generator() {},
+
+    // Async function (ES2017)
+    async method() {},
+    async /* comment */ method() {},
+    async() {},// method called "async"
+    async: false, // property called "async"
+    async prop: 'val', // incorrectly highlighted (syntax error)
+
+    // Async generator (ES2018)
+    async *generator() {}
+};
+
+// Computed property names
+a = {
+    ['prop']: 1,
+    ['method']() {}
+};
+
+// Spread properties (ES2018)
+a = { ...b };
+
+
+/* Regular expression literal */
+
+/abc/;
+x = /abc/gi;
+function_with_regex_arg(/abc/);
+[ /abc/m, /def/u ];
+a = { regex: /abc/s }; // s (dotAll): ES2018
+(1 === 0) ? /abc/ : /def/;
+/abc/; /* Comment */
+/abc/; // Comment
+var matches = /abc/.exec('Alphabet ... that should contain abc, right?');
+
+// No regex here
+a = [thing / thing, thing / thing];
+x = a /b/ c / d;
+
+// Character groups with backslashes
+/[ab\\]/; // a, b or backslash
+/[ab\]]/; // a, b or ]
+/\\[ab]/; // a or b preceded by backslash
+/\[ab]/;  // Literally "[ab]"
+
+// Control escape
+/\cJ/;
+
+// Unicode property escape (ES2018)
+/\p{General_Category=Letter}/u;
+/\p{Letter}/u;
+
+// Named capture groups (ES2018)
+/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
+/(?<foobar>foo|bar)/u;
+/^(?<half>.*).\k<half>$/u; // backreference
+
+/* Template literal */
+
+console.log(`The sum of 2 and 2 is ${2 + 2}`);
+
+let y = 8;
+let my_string = `This is a multiline
+string that also contains
+a template ${y + (4.1 - 2.2)}`;
+
+
+/*
+ * Built-in values
+ */
+
+// global object values
+Infinity;
+NaN;
+undefined;
+
+// global object functions
+decodeURIComponent();
+decodeURI();
+encodeURIComponent();
+encodeURI();
+eval();
+isFinite();
+isNaN();
+parseFloat();
+parseInt();
+
+// constructors (subset)
+Array();
+BigInt(); // ES2020
+Boolean();
+Date();
+Error();
+Function();
+Map();
+Object();
+Promise();
+RegExp();
+Set();
+String();
+Symbol();
+
+// objects
+JSON.parse();
+Math.random();
+
+// object keywords
+arguments;
+globalThis; // ES2020
+new.target;
+new . /* comment */ target;
+super;
+this;
+new . /* comment
+*/ target; // not correctly highlighted
+new // comment
+.target; // not correctly highlighted
+
+// function keywords
+import(); // ES2020
+import /* comment */ (); // ES2020
+import /* comment
+*/ (); // not correctly highlighted (though it may appear correct)
+import // comment
+(); // not correctly highlighted (though it may appear correct)
+
+// properties (subset)
+array.length;
+Math.PI;
+Number.NaN;
+object.constructor;
+Class.prototype;
+Symbol.asyncIterator; // ES2018
+Symbol('desc').description; // ES2019
+
+// methods (subset)
+array.keys();
+date.toString();
+object.valueOf();
+re.test();
+array.includes(); // ES2016
+Object.values(); // ES2017
+Object.entries(); // ES2017
+string.padStart(); // ES2017
+string.padEnd(); // ES2017
+Object.getOwnPropertyDescriptors(); // ES2017
+promise.finally(); // ES2018
+Object.fromEntries(); // ES2019
+string.trimStart(); // ES2019
+string.trimEnd(); // ES2019
+array.flat(); // ES2019
+array.flatMap(); // ES2019
+string.matchAll(); // ES2020
+Promise.allSettled(); // ES2020
+BigInt.asUintN(); // ES2020
+
+
+/*
+ * Function expression, arrow function
+ */
+
+a = function () { return 1 };
+a = function fn() {
+    return;
+};
+a = function fn(x) {};
+a = function fn(x, y) {};
+
+// Arrow function
+x => -x;
+() => {};
+(x, y) => x + y;
+(x, y) => { return x + y; };
+(x, y) => /* comment */ { return x + y; } /* comment */ ;
+(x) => ({ a: x }); // return object
+
+// Default parameters
+a = function fn(x, y = 1) {};
+(x, y = 1) => x + y;
+
+// Parameter without default after default parameters
+a = function fn(x = 1, y) {};
+(x = 1, y) => x + y;
+
+// Array destructuring
+a = function fn([x]) {};
+a = function fn([x, y]) {};
+([x]) => x;
+([x, y]) => x + y;
+
+// Object destructuring
+a = function fn({ x }) {};
+a = function fn({ x, b: y }) {};
+({ x }) => x;
+({ x, b: y }) => x + y;
+
+// Destructuring and default value
+a = function f([x, y] = [1, 2], {c: z} = {c: 3}) {};
+([x, y] = [1, 2], {c: z} = {c: x + y}) => x + y + z;
+
+// Generator function
+a = function*fn() {};
+a = function * fn() {};
+
+// Rest parameters
+a = function fn(...rest) {};
+a = function fn(x, y, ...rest) {};
+(...rest) => rest;
+(x, y, ...rest) => rest;
+
+// Async function (ES2017)
+a = async function fn() {};
+a = async /* comment */ function fn() {};
+a = async /* comment
+*/ function fn() {}; // correctly highlighted, because async cannot be followed by a line terminator
+async x => x;
+async () => {};
+async /* comment */ () => {};
+async /* comment
+*/ () => {}; // correctly highlighted, because async cannot be followed by a line terminator
+async(); // incorrectly highlighted
+
+// Async generator (ES2018)
+a = async function * fn() {};
+
+// Trailing comma (ES2017)
+a = function fn(x, y,) {};
+(x, y,) => x + y;
+
+// Trailing comma after rest parameters (syntax error)
+a = function fn(x, y, ...rest,) {};
+(x, y, ...rest,) => rest;
+
+
+/*
+ * Class expression
+ */
+
+a = class Foo {
+    constructor() {
+    }
+    method(x, y) {
+        return x + y;
+    }
+    *generator() {}
+};
+a = class extends Bar {
+    constructor() {
+        this._value = null;
+    }
+    get property() {
+        return this._value;
+    }
+    set property(x) {
+        this._value = x;
+    }
+    static get bar() {
+        return 'bar';
+    }
+};
+
+
+/*
+ * Operators
+ * use groupings to test, as there can only be one expression (in the
+ * first grouping item)
+ */
+
+// Grouping
+( 1 + 2 );
+
+// Increment / decrement
+( ++a );
+( --a );
+( a++ );
+( a-- );
+
+// Keyword unary
+( await promise() ); // ES2017
+( delete obj.prop );
+( new Array() );
+( void 1 );
+( typeof 'str' );
+( yield 1 );
+( yield* fn() );
+
+// Arithmetic
+( 1 + 2 );
+( 1 - 2 );
+( 1 * 2 );
+( 1 / 2 );
+( 1 % 2 );
+( 1 ** 2 ); // ES2016
+( +1 );
+( -1 );
+
+// Keyword relational
+( prop in obj );
+( obj instanceof constructor );
+
+// Comparison
+( 1 == 2 );
+( 1 != 2 );
+( 1 === 2 );
+( 1 !== 2 );
+( 1 < 2 );
+( 1 > 2 );
+( 1 <= 2 );
+( 1 >= 2 );
+
+// Bitwise
+( 1 & 2 );
+( 1 | 2 );
+( 1 ^ 2 );
+( ~1 );
+( 1 << 2 );
+( 1 >> 2 );
+( 1 >>> 2 );
+
+// Logical
+( 1 && 2 );
+( 1 || 2 );
+( !1 );
+
+// Assignment
+( a = 1 );
+( a += 1 );
+( a -= 1 );
+( a *= 1 );
+( a /= 1 );
+( a %= 1 );
+( a **= 1 ); // ES2016
+( a <<= 1 );
+( a >>= 1 );
+( a >>>= 1 );
+( a &= 1 );
+( a |= 1 );
+( a ^= 1 );
+( [a, b] = [1, 2] ); // array destructuring
+( {a, b} = { a: 1, b: 2} ); // object destructuring
+
+// Comma
+1, 2 ;
+
+// Conditional / ternary
+( true ? 1 : 2 );
+( true ? : 2 ); // missing true value (syntax error)
+
+
+/*
+ * Property accessors
+ */
+
+// Dot notation
+arr.length;
+obj
+    . prototype
+    . constructor;
+
+// Bracket notation
+arr['length'];
+obj
+    ['prototype']
+    ['constructor'];
+
+// Mixed
+obj
+    ['prototype']
+    . constructor;
+obj
+    . prototype
+    ['constructor'];
+
+
+/*
+ * Function call
+ */
+
+fn();
+obj.fn(1);
+obj['fn'](1, 2);
+
+// Spread syntax
+fn(x, y, ...args);
+
+// Trailing comma (ES2017)
+fn(x, y,);
+
+
+/* Tagged template */
+
+myTag`That ${ person } is ${ age }`;
+
+
+/*
+ * Statements and declarations
+ */
+
+/* Use strict directive */
+
+"use strict";
+function () {
+    'use strict';
+}
+
+// invalid directives
+" use strict";
+'use strict ';
+"use  strict";
+'use   strict';
+"hello 'use strict' world";
+fn("use strict");
+{ 'use strict'; }
+
+
+/* Block statement */
+
+{
+    hello();
+    world();
+}
+{ hello(); world() }
+
+
+/* Break statement */
+
+break;
+break label;
+break       // end statement
+    label;  // separate statement
+{ break }
+
+
+/*
+ * Class declaration
+ */
+
+class Foo {
+    constructor() {
+    }
+    method(x, y) {
+        return x + y;
+    }
+    *generator() {}
+}
+class Foo extends Bar {
+    constructor() {
+        this._value = null;
+    }
+    get property() {
+        return this._value;
+    }
+    set property(x) {
+        this._value = x;
+    }
+    static get bar() {
+        return 'bar';
+    }
+}
+
+
+/* Continue statement */
+
+continue;
+continue label;
+continue    // end statement
+    label;  // separate statement
+{ continue }
+
+
+/* Debugger statement */
+
+debugger;
+debugger
+    ;
+
+
+/* Export / import statement */
+
+export { a };
+export { a, b, };
+export { x as a };
+export { x as a, y as b, };
+export var a;
+export let a, b;
+export const a = 1;
+export var a = 1, b = 2;
+export function fn() {}
+export function* fn() {}
+export class Class {}
+
+export default 1;
+export default function () {}
+export default function *fn() {}
+export default class {}
+export { a as default, b };
+
+export * from 'module';
+export { a, b } from 'module';
+export { x as a, y as b, } from 'module';
+export { default } from 'module';
+
+import a from "module";
+import * as ns from "module";
+import { a } from "module";
+import { a, b } from "module";
+import { x as a } from "module";
+import { x as a, y as b } from "module";
+import { default as a } from "module";
+import a, { b } from "module";
+import a, * as nm from "module";
+import "module";
+
+
+/* For statement */
+
+for (i = 0; i < 10; i++) something();
+for (var i = 10; i >= 0; i--) {
+    something();
+}
+for (i = 0, j = 0; i < 10; i++, j++) something();
+for (let i = 10, j = 0; i >= 0; i--, j += 1) {
+    something();
+}
+for (prop in obj) {} // matches "in" binary operator instead
+for (const prop in obj) {}
+for (val of generator()) {}
+for (var val of array) {}
+for await (let x of asyncIterable) {} // ES2018
+for /* comment */ await /* comment */ (let x of asyncIterable) {} // ES2018
+
+
+/* Function declaration statement */
+
+function fn() {
+    return;
+}
+async function fn() {} // ES2017
+async /* comment */ function fn() {} // ES2017
+async /* comment
+*/ function fn() {} // correctly highlighted, because async cannot be followed by a line terminator
+
+
+/* If..else statement */
+
+if (a < 0) lessThan(); else if (a > 0) greaterThan(); else equal();
+if (a < 0)
+    lessThan();
+else if (a > 0)
+    greaterThan();
+else
+    equal();
+if (a < 0) {
+    lessThan();
+} else if (a > 0) {
+    greaterThan();
+} else {
+    equal();
+}
+
+
+/* Label statement */
+
+outer: for (var i = 0; i < 10; i++) {
+inner /* comment */ : for (var j = 0; j < 2; j++) {}
+}
+loop /* comment
+*/ : for (var i in obj) {} // incorrectly highlighted (though it may appear correct)
+
+
+/* Return statement */
+
+return;
+return 1;
+return  // end statement
+    1;  // separate statement
+return (
+    1
+);
+{ return a }
+
+
+/* Switch statement */
+
+switch (foo) {
+case 1:
+    doIt();
+    break;
+case '2':
+    doSomethingElse();
+    break;
+default:
+    oops();
+}
+
+
+/* Throw statement */
+
+throw e;
+throw new Error();
+throw   // end statement (syntax error)
+    e;  // separate statement
+throw (
+    new Error()
+);
+{ throw new Error() }
+
+
+/* Try...catch statement */
+
+try {
+    somethingDangerous();
+}
+catch (e) {
+    didntWork(e);
+}
+catch { // ES2019
+    return false;
+}
+finally {
+    cleanup();
+}
+
+
+/* Variable declaration */
+
+// Declaration only
+const a;
+let a, b, c;
+var a
+    ,
+    b
+    ,
+    c
+    ;
+
+// With assignment
+const a = 1;
+let a = 1, b = [2, 3], c = 4;
+var a
+    =
+    1
+    ,
+    b
+    =
+    [
+    2
+    ,
+    3
+    ]
+    ,
+    c
+    =
+    4
+    ;
+
+// Array destructuring
+var [a, b] = [1, 2];
+var [
+    a
+    ,
+    b
+    ]
+    =
+    [
+    1
+    ,
+    2
+    ]
+    ;
+var [a = 5, b = 7] = [1]; // default values
+var [a, , b] = f(); // ignoring some returned values
+var [a, ...b] = [1, 2, 3]; // rest syntax
+
+// Object destructuring
+var { a, b } = { a: 1, b: 2 };
+var {
+    a
+    ,
+    b
+    }
+    =
+    {
+    a
+    :
+    1
+    ,
+    b
+    :
+    2
+    }
+    ;
+var { a: foo, b: bar } = { a: 1, b: 2 }; // assigning to new variable names
+var { a = 5, b = 7 } = { a: 1 }; // default values
+var { a: foo = 5, b: bar = 7 } = { a: 1 }; // assigning to new variable names and default values
+var { ['a']: foo, ['b']: bar } = { a: 1, b: 2 }; // computed property names
+var { a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 }; // rest properties (ES2018)
+
+
+/* While / do...while statement */
+
+while (true) something();
+while (1) {
+    something();
+}
+do something(); while (false);
+do {
+    something();
+} while (0);
+
+
+/* With statement */
+
+with (Math) {
+    a = PI * r * r;
+    x = r * cos(PI);
+    y = r * sin(PI / 2);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]