Repository: prettier/prettier (JavaScript)

Issue:
Missing `readonly` and `declare` in `ClassMethod` and `TSMethodSignature`
**Prettier 2.2.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAucAbAhgZ0wAgMI7AA6UOOATnOgCbSoCeOAVHABQCUhAviWdXGAyVmAMw7cSPKCQCWsOORHowcHADEIEQrxz9B6YW3YBuHegBGmGOWUwcYk5JAAaEBAAOMGdEzJQB8ggAdwAFAwRfFHRUIPR6X1dzGzAAazgYAGV3ZTkAc2RrAFc4VzgAW3M4an5qABl0KFzC9Fy4DXIy9BgvRuQQdEKYCBcQAAsYMtQAdVGZeExslQyIuZkANzn6PrBsEblMBRgQm1zO5CVUA9cAK0wADwAhZLTM9DK4Wrk4c+irkFu7hk8qg4ABFQoQeA-S4lEDZcgHch9GD0dxwTBgcgyTwjdxY2BTGTUGCjZAADgADK48RADlMbO4+nj0Qo1t9XABHCHwY4eSL9TAAWigcCqVRGlC5MkoxxaZyQFz+BzKMgK5GKrkwwLB3O+Ct+sJgFkJxNJSAATK5rOgZKg8ngIGV5SB0QBWEaFA4AFQskUVsLWxQAklB+LAMpjsTAAIKhjIokHQg5cLhAA)
<!-- prettier-ignore -->
```sh
--parser typescript
```

**Input:**
<!-- prettier-ignore -->
```tsx
class C {
  readonly *e() {}
  declare *f() {}
}

interface Foo {
  declare e();
  abstract f();
}
```

**Output:**
<!-- prettier-ignore -->
```tsx
class C {
  *e() {}
  *f() {}
}

interface Foo {
  e();
  f();
}

```

**Expected behavior:**
```tsx
class C {
  readonly *e() {}
  declare *f() {}
}

interface Foo {
  declare e();
  abstract f();
}
```


---

Update 

**Expected behavior:**

Throw SyntaxError.



Hints:
> [Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAucAbAhgZ0wAgMI7AA6UOOATnOgCbSoCeOAVHABQCUhAviWdXGAyVmAMw7cSXEABoQEAA4wAltEzJQ6cuQgB3AAqaEalOlQ709NbIBG5dGADWcGAGV59pVADmyGOQCucLJwALbWcNT81AAy6N7+6F5wAGIQ5CHoMMreyCDo-jAQMiAAFjAhqADqJUrwmO5gcC5GtUoAbrX0uWDYxZ6YcOQwenZeGcgipgOyAFaYAB4AQnaOzi7oIXDRnnATU0Egc-Munl6ocACK-hDwe6jTIO7kA+S5MPTycJhg5EqKxfJfrBKkpqDASsgABwABlkgIgA0qdnkuUBX0GbV2sgAjtd4CMFMY8pgALRQOARCLFSi4pSUEaJcZISb3A4DEJKXwBNmnc5XG67Zn7WQwdDWEFgiFIABMIrsSlQpzwEBCTJAXwArMV-AMACpi4wsh5tQIASSg-FgLh+fxgAEELS53uc7gMuFwgA)

Same output comes from both `typescript` and `babel-ts` parsers (other JavaScript parsers signal a syntax error).

Background is in PR #9748 & <https://github.com/typescript-eslint/typescript-eslint/issues/2908>.

I gather that the testing with AST_COMPARE=1 does not show an issue because the attributes are not present in the AST coming either from` babel-ts` or `typescript` parser.
> I gather that the testing with AST_COMPARE=1 does not show an issue because the attributes are not present in the AST 

 https://github.com/prettier/prettier/pull/9768
Invalid `declare` on accessors not throwing, should be the same problem. `babel-ts` fixed this in #10750.

**Prettier 2.2.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAucAbAhgZ0wAgGIQQ7AA6UOOAJnGBgE5w4DmcMOAZoQBQCUZF1WugY5MrDtwBufKAF8QAGhAQADjACW0TMlDC6EAO4AFYQm0p0qA+gCe2pQCM66MAGtWAZRUv1UJshg6AFc4JTgAWwc4SmpKABl0PyD0FgI6cPQYDT9kEHQgmAhFEAALGHDUAHUS9XhMbzA4DzNa9Ulam1ywbGLfMToYI2cmDOR2SzElACtMAA8AIWc3T3RwuDjfODGJ0JAZ2Y9fJlQ4AEUgiHht1EmQbzp+3JgbFThMMDp1NWKVT9hK9SUGAlZAADgADEpfhAxJVnCpcr83nA6JItkoAI4XeBDVTmPKYAC0UDg0WixQYWPUDCGKVGSHGN12YnC6gCwWZRxO50uWwZOyUMHQDgBQJBSAATILnOpUEcAMIQcL0kBvACsxSCYgAKsLzIzbpIQgBJKDUWAeD5fGAAQTNHmeJ2uYlksiAA)
<!-- prettier-ignore -->
```sh
--parser typescript
```

**Input:**
<!-- prettier-ignore -->
```tsx
class Foo {
  declare get foo()
  declare set foo(v)
}
```

**Output:**
<!-- prettier-ignore -->
```tsx
class Foo {
  get foo();
  set foo(v);
}

```

Patch:
diff --git a/src/language-js/parse/babel.js b/src/language-js/parse/babel.js
--- a/src/language-js/parse/babel.js
+++ b/src/language-js/parse/babel.js
@@ -207,8 +207,6 @@ const allowedMessageCodes = new Set([
   "InvalidTupleMemberLabel",
 
   "NonClassMethodPropertyHasAbstractModifer",
-  "ClassMethodHasDeclare",
-  "ClassMethodHasReadonly",
   "DuplicateAccessibilityModifier",
   "IndexSignatureHasDeclare",
 
diff --git a/src/language-js/parse/postprocess/ts-syntax-kind.evaluate.js b/src/language-js/parse/postprocess/ts-syntax-kind.evaluate.js
deleted file mode 100644
--- a/src/language-js/parse/postprocess/ts-syntax-kind.evaluate.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import ts from "typescript";
-
-export const {
-  AbstractKeyword,
-  SourceFile,
-  DeclareKeyword,
-  PropertyDeclaration,
-  InKeyword,
-  OutKeyword,
-  MethodSignature,
-} = ts.SyntaxKind;
diff --git a/src/language-js/parse/postprocess/typescript.js b/src/language-js/parse/postprocess/typescript.js
--- a/src/language-js/parse/postprocess/typescript.js
+++ b/src/language-js/parse/postprocess/typescript.js
@@ -1,10 +1,11 @@
 import isNonEmptyArray from "../../../utils/is-non-empty-array.js";
 import visitNode from "./visit-node.js";
 import throwTsSyntaxError from "./throw-ts-syntax-error.js";
-import * as SyntaxKind from "./ts-syntax-kind.evaluate.js";
+
+let ts;
 
 function getTsNodeLocation(nodeOrToken) {
-  const sourceFile = getSourceFileOfNode(nodeOrToken);
+  const sourceFile = ts.getSourceFileOfNode(nodeOrToken);
   const [start, end] = [nodeOrToken.pos, nodeOrToken.end].map((position) => {
     const { line, character: column } =
       sourceFile.getLineAndCharacterOfPosition(position);
@@ -14,12 +15,8 @@ function getTsNodeLocation(nodeOrToken) {
   return { start, end };
 }
 
-// Copied from https://unpkg.com/typescript@4.8.2/lib/typescript.js
-function getSourceFileOfNode(node) {
-  while (node && node.kind !== SyntaxKind.SourceFile) {
-    node = node.parent;
-  }
-  return node;
+function throwErrorOnTsNode(node, message) {
+  throwTsSyntaxError({ loc: getTsNodeLocation(node) }, message);
 }
 
 // Invalid decorators are removed since `@typescript-eslint/typescript-estree` v4
@@ -33,10 +30,7 @@ function throwErrorForInvalidDecorator(tsNode) {
 
   const [{ expression }] = illegalDecorators;
 
-  throwTsSyntaxError(
-    { loc: getTsNodeLocation(expression) },
-    "Decorators are not valid here."
-  );
+  throwErrorOnTsNode(expression, "Decorators are not valid here.");
 }
 
 // Values of abstract property is removed since `@typescript-eslint/typescript-estree` v5
@@ -44,11 +38,11 @@ function throwErrorForInvalidDecorator(tsNode) {
 function throwErrorForInvalidAbstractProperty(tsNode, esTreeNode) {
   if (
     !(
-      tsNode.kind === SyntaxKind.PropertyDeclaration &&
+      tsNode.kind === ts.SyntaxKind.PropertyDeclaration &&
       tsNode.initializer &&
       esTreeNode.value === null &&
       tsNode.modifiers?.some(
-        (modifier) => modifier.kind === SyntaxKind.AbstractKeyword
+        (modifier) => modifier.kind === ts.SyntaxKind.AbstractKeyword
       )
     )
   ) {
@@ -61,55 +55,86 @@ function throwErrorForInvalidAbstractProperty(tsNode, esTreeNode) {
   );
 }
 
-function throwErrorForInvalidDeclare(tsNode, esTreeNode) {
-  if (
-    !(
-      esTreeNode.type === "MethodDefinition" &&
-      (esTreeNode.kind === "get" || esTreeNode.kind === "set")
-    )
-  ) {
+// Based on `checkGrammarModifiers` function in `typescript`
+function throwErrorForInvalidModifier(node) {
+  const { modifiers } = node;
+  if (!isNonEmptyArray(modifiers)) {
     return;
   }
 
-  const declareKeyword = tsNode.modifiers?.find(
-    (modifier) => modifier.kind === SyntaxKind.DeclareKeyword
-  );
+  const { SyntaxKind } = ts;
 
-  if (!declareKeyword) {
-    return;
-  }
+  for (const modifier of modifiers) {
+    if (ts.isDecorator(modifier)) {
+      continue;
+    }
 
-  throwTsSyntaxError(
-    { loc: getTsNodeLocation(declareKeyword) },
-    /* cspell:disable-next-line */
-    `'declare' is not allowed in ${esTreeNode.kind}ters.`
-  );
-}
+    if (modifier.kind !== SyntaxKind.ReadonlyKeyword) {
+      if (
+        node.kind === SyntaxKind.PropertySignature ||
+        node.kind === SyntaxKind.MethodSignature
+      ) {
+        throwErrorOnTsNode(
+          modifier,
+          `'${ts.tokenToString(
+            modifier.kind
+          )}' modifier cannot appear on a type member`
+        );
+      }
+
+      if (
+        node.kind === SyntaxKind.IndexSignature &&
+        (modifier.kind !== SyntaxKind.StaticKeyword ||
+          !ts.isClassLike(node.parent))
+      ) {
+        throwErrorOnTsNode(
+          modifier,
+          `'${ts.tokenToString(
+            modifier.kind
+          )}' modifier cannot appear on an index signature`
+        );
+      }
+    }
 
-function throwErrorForInvalidModifierOnTypeParameter(tsNode, esTreeNode) {
-  if (
-    esTreeNode.type !== "TSMethodSignature" ||
-    tsNode.kind !== SyntaxKind.MethodSignature
-  ) {
-    return;
-  }
+    if (
+      modifier.kind !== SyntaxKind.InKeyword &&
+      modifier.kind !== SyntaxKind.OutKeyword &&
+      node.kind === SyntaxKind.TypeParameter
+    ) {
+      throwErrorOnTsNode(
+        modifier,
+        `'${ts.tokenToString(
+          modifier.kind
+        )}' modifier cannot appear on a type parameter`
+      );
+    }
 
-  const invalidModifier = tsNode.modifiers?.find(
-    (modifier) =>
-      !(
-        modifier.kind === SyntaxKind.InKeyword ||
-        modifier.kind === SyntaxKind.OutKeyword
-      )
-  );
+    if (
+      modifier.kind === SyntaxKind.ReadonlyKeyword &&
+      node.kind !== SyntaxKind.PropertyDeclaration &&
+      node.kind !== SyntaxKind.PropertySignature &&
+      node.kind !== SyntaxKind.IndexSignature &&
+      node.kind !== SyntaxKind.Parameter
+    ) {
+      throwErrorOnTsNode(
+        modifier,
+        "'readonly' modifier can only appear on a property declaration or index signature."
+      );
+    }
 
-  if (!invalidModifier) {
-    return;
+    if (
+      modifier.kind === SyntaxKind.DeclareKeyword &&
+      ts.isClassLike(node.parent) &&
+      !ts.isPropertyDeclaration(node)
+    ) {
+      throwErrorOnTsNode(
+        modifier,
+        `'${ts.tokenToString(
+          modifier.kind
+        )}' modifier cannot appear on class elements of this kind.`
+      );
+    }
   }
-
-  throwTsSyntaxError(
-    { loc: getTsNodeLocation(invalidModifier) },
-    "This modifier cannot appear on a type member"
-  );
 }
 
 function getTsNode(node, tsParseResult) {
@@ -127,27 +152,46 @@ function getTsNode(node, tsParseResult) {
   return tsNode;
 }
 
-function throwErrorForInvalidNodes(tsParseResult, options) {
+async function throwErrorForInvalidNodes(tsParseResult, options) {
   if (
-    // decorators
-    // abstract properties
-    // declare in accessor
-    // modifiers on type parameter
-    !/@|abstract|declare|interface/.test(options.originalText)
+    // decorators and modifiers
+    !new RegExp(
+      [
+        "@",
+        "abstract",
+        "accessor",
+        "async",
+        "const",
+        "declare",
+        "default",
+        "export",
+        "static",
+        "in",
+        "out",
+        "override",
+        "public",
+        "private",
+        "protected",
+        "readonly",
+      ].join("|")
+    ).test(options.originalText)
   ) {
     return;
   }
 
+  if (!ts) {
+    ({ default: ts } = await import("typescript"));
+  }
+
   visitNode(tsParseResult.ast, (esTreeNode) => {
     const tsNode = getTsNode(esTreeNode, tsParseResult);
     if (!tsNode) {
       return;
     }
 
-    throwErrorForInvalidDeclare(tsNode, esTreeNode);
     throwErrorForInvalidDecorator(tsNode);
     throwErrorForInvalidAbstractProperty(tsNode, esTreeNode);
-    throwErrorForInvalidModifierOnTypeParameter(tsNode, esTreeNode);
+    throwErrorForInvalidModifier(tsNode);
   });
 }
 
diff --git a/src/language-js/parse/typescript.js b/src/language-js/parse/typescript.js
--- a/src/language-js/parse/typescript.js
+++ b/src/language-js/parse/typescript.js
@@ -57,7 +57,7 @@ async function parse(text, options = {}) {
 
   options.originalText = text;
 
-  throwErrorForInvalidNodes(result, options);
+  await throwErrorForInvalidNodes(result, options);
 
   return postprocess(result.ast, options);
 }
diff --git a/src/language-js/print/class.js b/src/language-js/print/class.js
--- a/src/language-js/print/class.js
+++ b/src/language-js/print/class.js
@@ -165,14 +165,6 @@ function printClassMethod(path, options, print) {
   if (node.accessibility) {
     parts.push(node.accessibility + " ");
   }
-  // "readonly" and "declare" are supported by only "babel-ts"
-  // https://github.com/prettier/prettier/issues/9760
-  if (node.readonly) {
-    parts.push("readonly ");
-  }
-  if (node.declare) {
-    parts.push("declare ");
-  }
 
   if (node.static) {
     parts.push("static ");


Test patch:
diff --git a/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap
@@ -1,7 +1,7 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`declare-getter.ts [typescript] format 1`] = `
-"'declare' is not allowed in getters. (1:12)
+"'declare' modifier cannot appear on class elements of this kind. (1:12)
 > 1 | class Foo {
     |            ^
 > 2 |   declare get foo()
@@ -11,7 +11,7 @@ exports[`declare-getter.ts [typescript] format 1`] = `
 `;
 
 exports[`declare-setter.ts [typescript] format 1`] = `
-"'declare' is not allowed in setters. (1:12)
+"'declare' modifier cannot appear on class elements of this kind. (1:12)
 > 1 | class Foo {
     |            ^
 > 2 |   declare set foo(v)
@@ -94,78 +94,6 @@ exports[`snippet: #5 [typescript] format 1`] = `
     |               ^"
 `;
 
-exports[`snippet: #6 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   abstract e();
-    | ^^^^^^^^^^^
-  3 | }"
-`;
-
-exports[`snippet: #7 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   declare e();
-    | ^^^^^^^^^^
-  3 | }"
-`;
-
-exports[`snippet: #8 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   export e();
-    | ^^^^^^^^^
-  3 | }"
-`;
-
-exports[`snippet: #9 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   static e();
-    | ^^^^^^^^^
-  3 | }"
-`;
-
-exports[`snippet: #10 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   private e();
-    | ^^^^^^^^^^
-  3 | }"
-`;
-
-exports[`snippet: #11 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   protected e();
-    | ^^^^^^^^^^^^
-  3 | }"
-`;
-
-exports[`snippet: #12 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   public e();
-    | ^^^^^^^^^
-  3 | }"
-`;
-
-exports[`snippet: #13 [typescript] format 1`] = `
-"This modifier cannot appear on a type member (1:16)
-> 1 | interface Foo {
-    |                ^
-> 2 |   readonly e();
-    | ^^^^^^^^^^^
-  3 | }"
-`;
-
 exports[`value-of-abstract-property.ts [typescript] format 1`] = `
 "Abstract property cannot have an initializer (2:3)
   1 | abstract class Foo {
diff --git a/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap
@@ -43,67 +43,3 @@ exports[`snippet: #2 [babel-ts] format 1`] = `
 > 1 | <string>foo = '100';
     |         ^"
 `;
-
-exports[`snippet: #3 [babel-ts] format 1`] = `
-"'abstract' modifier cannot appear on a type member. (2:3)
-  1 | interface Foo {
-> 2 |   abstract e();
-    |   ^
-  3 | }"
-`;
-
-exports[`snippet: #4 [babel-ts] format 1`] = `
-"'declare' modifier cannot appear on a type member. (2:3)
-  1 | interface Foo {
-> 2 |   declare e();
-    |   ^
-  3 | }"
-`;
-
-exports[`snippet: #5 [babel-ts] format 1`] = `
-"Unexpected token, expected ";" (2:10)
-  1 | interface Foo {
-> 2 |   export e();
-    |          ^
-  3 | }"
-`;
-
-exports[`snippet: #6 [babel-ts] format 1`] = `
-"'static' modifier cannot appear on a type member. (2:3)
-  1 | interface Foo {
-> 2 |   static e();
-    |   ^
-  3 | }"
-`;
-
-exports[`snippet: #7 [babel-ts] format 1`] = `
-"'private' modifier cannot appear on a type member. (2:3)
-  1 | interface Foo {
-> 2 |   private e();
-    |   ^
-  3 | }"
-`;
-
-exports[`snippet: #8 [babel-ts] format 1`] = `
-"'protected' modifier cannot appear on a type member. (2:3)
-  1 | interface Foo {
-> 2 |   protected e();
-    |   ^
-  3 | }"
-`;
-
-exports[`snippet: #9 [babel-ts] format 1`] = `
-"'public' modifier cannot appear on a type member. (2:3)
-  1 | interface Foo {
-> 2 |   public e();
-    |   ^
-  3 | }"
-`;
-
-exports[`snippet: #10 [babel-ts] format 1`] = `
-"'readonly' modifier can only appear on a property declaration or index signature. (2:3)
-  1 | interface Foo {
-> 2 |   readonly e();
-    |   ^
-  3 | }"
-`;
diff --git a/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js b/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js
--- a/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js
+++ b/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js
@@ -1,5 +1,3 @@
-import { outdent } from "outdent";
-
 run_spec(
   {
     importMeta: import.meta,
@@ -7,22 +5,6 @@ run_spec(
       "foo as any = 10;",
       "({ a: b as any = 2000 } = x);",
       "<string>foo = '100';",
-      ...[
-        "abstract",
-        "declare",
-        "export",
-        "static",
-        "private",
-        "protected",
-        "public",
-        "readonly",
-      ].map(
-        (modifier) => outdent`
-          interface Foo {
-            ${modifier} e();
-          }
-        `
-      ),
     ],
   },
   ["babel-ts"]
diff --git a/tests/format/misc/errors/typescript/jsfmt.spec.js b/tests/format/misc/errors/typescript/jsfmt.spec.js
--- a/tests/format/misc/errors/typescript/jsfmt.spec.js
+++ b/tests/format/misc/errors/typescript/jsfmt.spec.js
@@ -1,5 +1,3 @@
-import { outdent } from "outdent";
-
 run_spec(
   {
     importMeta: import.meta,
@@ -10,22 +8,6 @@ run_spec(
       'let x4 = <div>{"foo"}></div>;',
       'let x5 = <div>}{"foo"}</div>;',
       'let x6 = <div>>{"foo"}</div>;',
-      ...[
-        "abstract",
-        "declare",
-        "export",
-        "static",
-        "private",
-        "protected",
-        "public",
-        "readonly",
-      ].map(
-        (modifier) => outdent`
-          interface Foo {
-            ${modifier} e();
-          }
-        `
-      ),
     ],
   },
   ["typescript"]
diff --git a/tests/format/misc/errors/typescript/modifiers/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/modifiers/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
--- /dev/null
+++ b/tests/format/misc/errors/typescript/modifiers/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,1186 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`snippet: #0 [babel-ts] format 1`] = `
+"'abstract' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   abstract method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #0 [typescript] format 1`] = `
+"'abstract' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   abstract method();
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #1 [babel-ts] format 1`] = `
+"'abstract' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   abstract property;
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #1 [typescript] format 1`] = `
+"'abstract' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   abstract property;
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #2 [babel-ts] format 1`] = `
+"'abstract' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   abstract [index: string]: number
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #2 [typescript] format 1`] = `
+"'abstract' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   abstract [index: string]: number
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #3 [babel-ts] format 1`] = `
+"'abstract' modifier cannot appear on a type member. (2:3)
+  1 | const foo: {
+> 2 |   abstract [index: string] : string
+    |   ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #3 [typescript] format 1`] = `
+"'abstract' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   abstract [index: string] : string
+    | ^^^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #4 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:12)
+  1 | interface Foo {
+> 2 |   accessor method();
+    |            ^
+  3 | }"
+`;
+
+exports[`snippet: #4 [typescript] format 1`] = `
+"'accessor' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   accessor method();
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #5 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:12)
+  1 | interface Foo {
+> 2 |   accessor property;
+    |            ^
+  3 | }"
+`;
+
+exports[`snippet: #5 [typescript] format 1`] = `
+"'accessor' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   accessor property;
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #6 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:12)
+  1 | interface Foo {
+> 2 |   accessor [index: string]: number
+    |            ^
+  3 | }"
+`;
+
+exports[`snippet: #6 [typescript] format 1`] = `
+"'accessor' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   accessor [index: string]: number
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #7 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:12)
+  1 | const foo: {
+> 2 |   accessor [index: string] : string
+    |            ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #7 [typescript] format 1`] = `
+"'accessor' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   accessor [index: string] : string
+    | ^^^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #8 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | interface Foo {
+> 2 |   async method();
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #8 [typescript] format 1`] = `
+"'async' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   async method();
+    | ^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #9 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | interface Foo {
+> 2 |   async property;
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #9 [typescript] format 1`] = `
+"'async' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   async property;
+    | ^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #10 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | interface Foo {
+> 2 |   async [index: string]: number
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #10 [typescript] format 1`] = `
+"'async' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   async [index: string]: number
+    | ^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #11 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | const foo: {
+> 2 |   async [index: string] : string
+    |         ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #11 [typescript] format 1`] = `
+"'async' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   async [index: string] : string
+    | ^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #12 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | interface Foo {
+> 2 |   const method();
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #12 [typescript] format 1`] = `
+"';' expected. (2:9)
+  1 | interface Foo {
+> 2 |   const method();
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #13 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | interface Foo {
+> 2 |   const property;
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #13 [typescript] format 1`] = `
+"';' expected. (2:9)
+  1 | interface Foo {
+> 2 |   const property;
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #14 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | interface Foo {
+> 2 |   const [index: string]: number
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #14 [typescript] format 1`] = `
+"';' expected. (2:9)
+  1 | interface Foo {
+> 2 |   const [index: string]: number
+    |         ^
+  3 | }"
+`;
+
+exports[`snippet: #15 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:9)
+  1 | const foo: {
+> 2 |   const [index: string] : string
+    |         ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #15 [typescript] format 1`] = `
+"';' expected. (2:9)
+  1 | const foo: {
+> 2 |   const [index: string] : string
+    |         ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #16 [babel-ts] format 1`] = `
+"'declare' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   declare method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #16 [typescript] format 1`] = `
+"'declare' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   declare method();
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #17 [babel-ts] format 1`] = `
+"'declare' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   declare property;
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #17 [typescript] format 1`] = `
+"'declare' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   declare property;
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #18 [babel-ts] format 1`] = `
+"'declare' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   declare [index: string]: number
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #18 [typescript] format 1`] = `
+"'declare' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   declare [index: string]: number
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #19 [babel-ts] format 1`] = `
+"'declare' modifier cannot appear on a type member. (2:3)
+  1 | const foo: {
+> 2 |   declare [index: string] : string
+    |   ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #19 [typescript] format 1`] = `
+"'declare' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   declare [index: string] : string
+    | ^^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #20 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:11)
+  1 | interface Foo {
+> 2 |   default method();
+    |           ^
+  3 | }"
+`;
+
+exports[`snippet: #20 [typescript] format 1`] = `
+"';' expected. (2:11)
+  1 | interface Foo {
+> 2 |   default method();
+    |           ^
+  3 | }"
+`;
+
+exports[`snippet: #21 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:11)
+  1 | interface Foo {
+> 2 |   default property;
+    |           ^
+  3 | }"
+`;
+
+exports[`snippet: #21 [typescript] format 1`] = `
+"';' expected. (2:11)
+  1 | interface Foo {
+> 2 |   default property;
+    |           ^
+  3 | }"
+`;
+
+exports[`snippet: #22 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:11)
+  1 | interface Foo {
+> 2 |   default [index: string]: number
+    |           ^
+  3 | }"
+`;
+
+exports[`snippet: #22 [typescript] format 1`] = `
+"';' expected. (2:11)
+  1 | interface Foo {
+> 2 |   default [index: string]: number
+    |           ^
+  3 | }"
+`;
+
+exports[`snippet: #23 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:11)
+  1 | const foo: {
+> 2 |   default [index: string] : string
+    |           ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #23 [typescript] format 1`] = `
+"';' expected. (2:11)
+  1 | const foo: {
+> 2 |   default [index: string] : string
+    |           ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #24 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:10)
+  1 | interface Foo {
+> 2 |   export method();
+    |          ^
+  3 | }"
+`;
+
+exports[`snippet: #24 [typescript] format 1`] = `
+"'export' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   export method();
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #25 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:10)
+  1 | interface Foo {
+> 2 |   export property;
+    |          ^
+  3 | }"
+`;
+
+exports[`snippet: #25 [typescript] format 1`] = `
+"'export' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   export property;
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #26 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:10)
+  1 | interface Foo {
+> 2 |   export [index: string]: number
+    |          ^
+  3 | }"
+`;
+
+exports[`snippet: #26 [typescript] format 1`] = `
+"'export' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   export [index: string]: number
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #27 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:10)
+  1 | const foo: {
+> 2 |   export [index: string] : string
+    |          ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #27 [typescript] format 1`] = `
+"'export' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   export [index: string] : string
+    | ^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #28 [babel-ts] format 1`] = `
+"'static' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   static method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #28 [typescript] format 1`] = `
+"'static' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   static method();
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #29 [babel-ts] format 1`] = `
+"'static' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   static property;
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #29 [typescript] format 1`] = `
+"'static' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   static property;
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #30 [babel-ts] format 1`] = `
+"'static' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   static [index: string]: number
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #30 [typescript] format 1`] = `
+"'static' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   static [index: string]: number
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #31 [babel-ts] format 1`] = `
+"'static' modifier cannot appear on a type member. (2:3)
+  1 | const foo: {
+> 2 |   static [index: string] : string
+    |   ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #31 [typescript] format 1`] = `
+"'static' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   static [index: string] : string
+    | ^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #32 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:6)
+  1 | interface Foo {
+> 2 |   in method();
+    |      ^
+  3 | }"
+`;
+
+exports[`snippet: #32 [typescript] format 1`] = `
+"'in' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   in method();
+    | ^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #33 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:6)
+  1 | interface Foo {
+> 2 |   in property;
+    |      ^
+  3 | }"
+`;
+
+exports[`snippet: #33 [typescript] format 1`] = `
+"'in' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   in property;
+    | ^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #34 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:6)
+  1 | interface Foo {
+> 2 |   in [index: string]: number
+    |      ^
+  3 | }"
+`;
+
+exports[`snippet: #34 [typescript] format 1`] = `
+"'in' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   in [index: string]: number
+    | ^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #35 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:6)
+  1 | const foo: {
+> 2 |   in [index: string] : string
+    |      ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #35 [typescript] format 1`] = `
+"'in' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   in [index: string] : string
+    | ^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #36 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:7)
+  1 | interface Foo {
+> 2 |   out method();
+    |       ^
+  3 | }"
+`;
+
+exports[`snippet: #36 [typescript] format 1`] = `
+"'out' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   out method();
+    | ^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #37 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:7)
+  1 | interface Foo {
+> 2 |   out property;
+    |       ^
+  3 | }"
+`;
+
+exports[`snippet: #37 [typescript] format 1`] = `
+"'out' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   out property;
+    | ^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #38 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:7)
+  1 | interface Foo {
+> 2 |   out [index: string]: number
+    |       ^
+  3 | }"
+`;
+
+exports[`snippet: #38 [typescript] format 1`] = `
+"'out' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   out [index: string]: number
+    | ^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #39 [babel-ts] format 1`] = `
+"Unexpected token, expected ";" (2:7)
+  1 | const foo: {
+> 2 |   out [index: string] : string
+    |       ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #39 [typescript] format 1`] = `
+"'out' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   out [index: string] : string
+    | ^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #40 [babel-ts] format 1`] = `
+"'override' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   override method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #40 [typescript] format 1`] = `
+"'override' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   override method();
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #41 [babel-ts] format 1`] = `
+"'override' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   override property;
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #41 [typescript] format 1`] = `
+"'override' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   override property;
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #42 [babel-ts] format 1`] = `
+"'override' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   override [index: string]: number
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #42 [typescript] format 1`] = `
+"'override' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   override [index: string]: number
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #43 [babel-ts] format 1`] = `
+"'override' modifier cannot appear on a type member. (2:3)
+  1 | const foo: {
+> 2 |   override [index: string] : string
+    |   ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #43 [typescript] format 1`] = `
+"'override' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   override [index: string] : string
+    | ^^^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #44 [babel-ts] format 1`] = `
+"'public' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   public method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #44 [typescript] format 1`] = `
+"'public' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   public method();
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #45 [babel-ts] format 1`] = `
+"'public' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   public property;
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #45 [typescript] format 1`] = `
+"'public' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   public property;
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #46 [babel-ts] format 1`] = `
+"'public' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   public [index: string]: number
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #46 [typescript] format 1`] = `
+"'public' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   public [index: string]: number
+    | ^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #47 [babel-ts] format 1`] = `
+"'public' modifier cannot appear on a type member. (2:3)
+  1 | const foo: {
+> 2 |   public [index: string] : string
+    |   ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #47 [typescript] format 1`] = `
+"'public' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   public [index: string] : string
+    | ^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #48 [babel-ts] format 1`] = `
+"'private' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   private method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #48 [typescript] format 1`] = `
+"'private' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   private method();
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #49 [babel-ts] format 1`] = `
+"'private' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   private property;
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #49 [typescript] format 1`] = `
+"'private' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   private property;
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #50 [babel-ts] format 1`] = `
+"'private' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   private [index: string]: number
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #50 [typescript] format 1`] = `
+"'private' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   private [index: string]: number
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #51 [babel-ts] format 1`] = `
+"'private' modifier cannot appear on a type member. (2:3)
+  1 | const foo: {
+> 2 |   private [index: string] : string
+    |   ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #51 [typescript] format 1`] = `
+"'private' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   private [index: string] : string
+    | ^^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #52 [babel-ts] format 1`] = `
+"'protected' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   protected method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #52 [typescript] format 1`] = `
+"'protected' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   protected method();
+    | ^^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #53 [babel-ts] format 1`] = `
+"'protected' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   protected property;
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #53 [typescript] format 1`] = `
+"'protected' modifier cannot appear on a type member (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   protected property;
+    | ^^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #54 [babel-ts] format 1`] = `
+"'protected' modifier cannot appear on a type member. (2:3)
+  1 | interface Foo {
+> 2 |   protected [index: string]: number
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #54 [typescript] format 1`] = `
+"'protected' modifier cannot appear on an index signature (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   protected [index: string]: number
+    | ^^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #55 [babel-ts] format 1`] = `
+"'protected' modifier cannot appear on a type member. (2:3)
+  1 | const foo: {
+> 2 |   protected [index: string] : string
+    |   ^
+  3 | } = {};"
+`;
+
+exports[`snippet: #55 [typescript] format 1`] = `
+"'protected' modifier cannot appear on an index signature (1:13)
+> 1 | const foo: {
+    |             ^
+> 2 |   protected [index: string] : string
+    | ^^^^^^^^^^^^
+  3 | } = {};"
+`;
+
+exports[`snippet: #56 [babel-ts] format 1`] = `
+"'readonly' modifier can only appear on a property declaration or index signature. (2:3)
+  1 | interface Foo {
+> 2 |   readonly method();
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #56 [typescript] format 1`] = `
+"'readonly' modifier can only appear on a property declaration or index signature. (1:16)
+> 1 | interface Foo {
+    |                ^
+> 2 |   readonly method();
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #57 [babel-ts] format 1`] = `
+"'abstract' modifier cannot appear on a type parameter. (1:15)
+> 1 | interface Foo<abstract T> {}
+    |               ^"
+`;
+
+exports[`snippet: #57 [typescript] format 1`] = `
+"'abstract' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<abstract T> {}
+    |               ^^^^^^^^"
+`;
+
+exports[`snippet: #58 [babel-ts] format 1`] = `
+"Unexpected token, expected "," (1:24)
+> 1 | interface Foo<accessor T> {}
+    |                        ^"
+`;
+
+exports[`snippet: #58 [typescript] format 1`] = `
+"'accessor' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<accessor T> {}
+    |               ^^^^^^^^"
+`;
+
+exports[`snippet: #59 [babel-ts] format 1`] = `
+"Unexpected token, expected "," (1:21)
+> 1 | interface Foo<async T> {}
+    |                     ^"
+`;
+
+exports[`snippet: #59 [typescript] format 1`] = `
+"'async' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<async T> {}
+    |               ^^^^^"
+`;
+
+exports[`snippet: #60 [babel-ts] format 1`] = `
+"Unexpected token, expected "," (1:21)
+> 1 | interface Foo<const T> {}
+    |                     ^"
+`;
+
+exports[`snippet: #60 [typescript] format 1`] = `
+"Type parameter declaration expected. (1:15)
+> 1 | interface Foo<const T> {}
+    |               ^"
+`;
+
+exports[`snippet: #61 [babel-ts] format 1`] = `
+"'declare' modifier cannot appear on a type parameter. (1:15)
+> 1 | interface Foo<declare T> {}
+    |               ^"
+`;
+
+exports[`snippet: #61 [typescript] format 1`] = `
+"'declare' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<declare T> {}
+    |               ^^^^^^^"
+`;
+
+exports[`snippet: #62 [babel-ts] format 1`] = `
+"Unexpected token, expected "," (1:23)
+> 1 | interface Foo<default T> {}
+    |                       ^"
+`;
+
+exports[`snippet: #62 [typescript] format 1`] = `
+"Type parameter declaration expected. (1:15)
+> 1 | interface Foo<default T> {}
+    |               ^"
+`;
+
+exports[`snippet: #63 [babel-ts] format 1`] = `
+"Unexpected token, expected "," (1:22)
+> 1 | interface Foo<export T> {}
+    |                      ^"
+`;
+
+exports[`snippet: #63 [typescript] format 1`] = `
+"Type parameter declaration expected. (1:15)
+> 1 | interface Foo<export T> {}
+    |               ^"
+`;
+
+exports[`snippet: #64 [babel-ts] format 1`] = `
+"Unexpected token, expected "," (1:22)
+> 1 | interface Foo<static T> {}
+    |                      ^"
+`;
+
+exports[`snippet: #64 [typescript] format 1`] = `
+"'static' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<static T> {}
+    |               ^^^^^^"
+`;
+
+exports[`snippet: #65 [babel-ts] format 1`] = `
+"'override' modifier cannot appear on a type parameter. (1:15)
+> 1 | interface Foo<override T> {}
+    |               ^"
+`;
+
+exports[`snippet: #65 [typescript] format 1`] = `
+"'override' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<override T> {}
+    |               ^^^^^^^^"
+`;
+
+exports[`snippet: #66 [babel-ts] format 1`] = `
+"'public' modifier cannot appear on a type parameter. (1:15)
+> 1 | interface Foo<public T> {}
+    |               ^"
+`;
+
+exports[`snippet: #66 [typescript] format 1`] = `
+"'public' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<public T> {}
+    |               ^^^^^^"
+`;
+
+exports[`snippet: #67 [babel-ts] format 1`] = `
+"'private' modifier cannot appear on a type parameter. (1:15)
+> 1 | interface Foo<private T> {}
+    |               ^"
+`;
+
+exports[`snippet: #67 [typescript] format 1`] = `
+"'private' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<private T> {}
+    |               ^^^^^^^"
+`;
+
+exports[`snippet: #68 [babel-ts] format 1`] = `
+"'protected' modifier cannot appear on a type parameter. (1:15)
+> 1 | interface Foo<protected T> {}
+    |               ^"
+`;
+
+exports[`snippet: #68 [typescript] format 1`] = `
+"'protected' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<protected T> {}
+    |               ^^^^^^^^^"
+`;
+
+exports[`snippet: #69 [babel-ts] format 1`] = `
+"'readonly' modifier cannot appear on a type parameter. (1:15)
+> 1 | interface Foo<readonly T> {}
+    |               ^"
+`;
+
+exports[`snippet: #69 [typescript] format 1`] = `
+"'readonly' modifier cannot appear on a type parameter (1:15)
+> 1 | interface Foo<readonly T> {}
+    |               ^^^^^^^^"
+`;
+
+exports[`snippet: #70 [babel-ts] format 1`] = `
+"Class methods cannot have the 'declare' modifier. (2:3)
+  1 | class Foo {
+> 2 |   declare method() {}
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #70 [typescript] format 1`] = `
+"'declare' modifier cannot appear on class elements of this kind. (1:12)
+> 1 | class Foo {
+    |            ^
+> 2 |   declare method() {}
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #71 [babel-ts] format 1`] = `
+"Class methods cannot have the 'readonly' modifier. (2:3)
+  1 | class Foo {
+> 2 |   readonly method() {}
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #71 [typescript] format 1`] = `
+"'readonly' modifier can only appear on a property declaration or index signature. (1:12)
+> 1 | class Foo {
+    |            ^
+> 2 |   readonly method() {}
+    | ^^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #72 [babel-ts] format 1`] = `
+"'declare' is not allowed in getters. (2:3)
+  1 | class Foo {
+> 2 |   declare get getter() {}
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #72 [typescript] format 1`] = `
+"'declare' modifier cannot appear on class elements of this kind. (1:12)
+> 1 | class Foo {
+    |            ^
+> 2 |   declare get getter() {}
+    | ^^^^^^^^^^
+  3 | }"
+`;
+
+exports[`snippet: #73 [babel-ts] format 1`] = `
+"'declare' is not allowed in setters. (2:3)
+  1 | class Foo {
+> 2 |   declare set setter(v) {}
+    |   ^
+  3 | }"
+`;
+
+exports[`snippet: #73 [typescript] format 1`] = `
+"'declare' modifier cannot appear on class elements of this kind. (1:12)
+> 1 | class Foo {
+    |            ^
+> 2 |   declare set setter(v) {}
+    | ^^^^^^^^^^
+  3 | }"
+`;
diff --git a/tests/format/misc/errors/typescript/modifiers/jsfmt.spec.js b/tests/format/misc/errors/typescript/modifiers/jsfmt.spec.js
new file mode 100644
--- /dev/null
+++ b/tests/format/misc/errors/typescript/modifiers/jsfmt.spec.js
@@ -0,0 +1,93 @@
+import { outdent } from "outdent";
+
+const POSSIBLE_MODIFIERS = [
+  "abstract",
+  "accessor",
+  "async",
+  "const",
+  "declare",
+  "default",
+  "export",
+  "static",
+  "in",
+  "out",
+  "override",
+  "public",
+  "private",
+  "protected",
+  "readonly",
+];
+
+run_spec(
+  {
+    importMeta: import.meta,
+    snippets: [
+      // Only `readonly` allowed in some places
+      ...POSSIBLE_MODIFIERS.filter(
+        (modifier) => modifier !== "readonly"
+      ).flatMap((modifier) => [
+        outdent`
+          interface Foo {
+            ${modifier} method();
+          }
+        `,
+        outdent`
+          interface Foo {
+            ${modifier} property;
+          }
+        `,
+        // index signature
+        outdent`
+          interface Foo {
+            ${modifier} [index: string]: number
+          }
+        `,
+        outdent`
+          const foo: {
+            ${modifier} [index: string] : string
+          } = {};
+        `,
+      ]),
+      outdent`
+        interface Foo {
+          readonly method();
+        }
+      `,
+
+      // TODO[@fisker]: Fix these tests
+      // ...["abstract", "static", "private", "protected", "public"].map(
+      //   (modifier) =>
+      //     outdent`
+      //       module Foo {
+      //         ${modifier} module Bar {}
+      //       }
+      //     `
+      // ),
+
+      // Only `in` and `out` allowed in type parameter
+      ...POSSIBLE_MODIFIERS.filter(
+        (modifier) => modifier !== "in" && modifier !== "out"
+      ).map((modifier) => `interface Foo<${modifier} T> {}`),
+
+      ...["declare", "readonly"].map(
+        (modifier) =>
+          outdent`
+            class Foo {
+              ${modifier} method() {}
+            }
+          `
+      ),
+      outdent`
+        class Foo {
+          declare get getter() {}
+        }
+      `,
+      outdent`
+        class Foo {
+          declare set setter(v) {}
+        }
+      `,
+    ],
+  },
+  ["babel-ts", "typescript"]
+);
diff --git a/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap
@@ -20,26 +20,6 @@ class C {
 ================================================================================
 `;
 
-exports[`invalid-modifiers.ts format 1`] = `
-====================================options=====================================
-parsers: ["babel-ts"]
-printWidth: 80
-                                                                                | printWidth
-=====================================input======================================
-class Bar {
-  declare e() {};
-  readonly g() {};
-}
-
-=====================================output=====================================
-class Bar {
-  declare e() {}
-  readonly g() {}
-}
-
-================================================================================
-`;
-
 exports[`parenthesized-decorators-call-expression.ts format 1`] = `
 ====================================options=====================================
 parsers: ["babel-ts"]
diff --git a/tests/format/misc/typescript-babel-only/invalid-modifiers.ts b/tests/format/misc/typescript-babel-only/invalid-modifiers.ts
deleted file mode 100644
--- a/tests/format/misc/typescript-babel-only/invalid-modifiers.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-class Bar {
-  declare e() {};
-  readonly g() {};
-}
diff --git a/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap
@@ -51,28 +51,6 @@ await 0;
 ================================================================================
 `;
 
-exports[`invalid-modifiers.ts format 1`] = `
-====================================options=====================================
-parsers: ["typescript"]
-printWidth: 80
-                                                                                | printWidth
-=====================================input======================================
-class Bar {
-  declare e() {};
-  abstract f() {};
-  readonly g() {};
-}
-
-=====================================output=====================================
-class Bar {
-  e() {}
-  abstract f() {}
-  g() {}
-}
-
-================================================================================
-`;
-
 exports[`parenthesized-decorators-call-expression.ts format 1`] = `
 ====================================options=====================================
 parsers: ["typescript"]
diff --git a/tests/format/misc/typescript-only/invalid-modifiers.ts b/tests/format/misc/typescript-only/invalid-modifiers.ts
deleted file mode 100644
--- a/tests/format/misc/typescript-only/invalid-modifiers.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-class Bar {
-  declare e() {};
-  abstract f() {};
-  readonly g() {};
-}
diff --git a/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap
@@ -1,14 +1,14 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`keywords.ts [babel-ts] format 1`] = `
-"Unexpected token, expected "{" (9:12)
-   7 |
-   8 |     // Apparently this parses :P
->  9 |     export private public protected static readonly abstract async enum X { }
-     |            ^
-  10 |
-  11 |     interface x {
-  12 |         export private static readonly [x: any]: any;"
+"Missing semicolon. (4:11)
+  2 |
+  3 | module Y4 {
+> 4 |     public enum Color { Blue, Red }
+    |           ^
+  5 | }
+  6 |
+  7 | module YY3 {"
 `;
 
 exports[`keywords.ts format 1`] = `
@@ -19,19 +19,6 @@ printWidth: 80
 =====================================input======================================
 // All of these should be an error
 
-module Y3 {
-    public module Module {
-        class A { s: string }
-    }
-
-    // Apparently this parses :P
-    export private public protected static readonly abstract async enum X { }
-
-    interface x {
-        export private static readonly [x: any]: any;
-    }
-}
-
 module Y4 {
     public enum Color { Blue, Red }
 }
@@ -59,21 +46,6 @@ module YYY4 {
 =====================================output=====================================
 // All of these should be an error
 
-module Y3 {
-  public module Module {
-    class A {
-      s: string;
-    }
-  }
-
-  // Apparently this parses :P
-  export private public protected static readonly abstract async enum X {}
-
-  interface x {
-    export private static readonly [x: any]: any;
-  }
-}
-
 module Y4 {
   public enum Color {
     Blue,
@@ -195,17 +167,6 @@ class G {
 ================================================================================
 `;
 
-exports[`module.ts [babel-ts] format 1`] = `
-"Unexpected token, expected "{" (7:10)
-   5 |
-   6 |   // Apparently this parses :P
->  7 |   export private public protected static readonly abstract async enum X { }
-     |          ^
-   8 |
-   9 |   interface x {
-  10 |       export private static readonly [x: any]: any;"
-`;
-
 exports[`module.ts format 1`] = `
 ====================================options=====================================
 parsers: ["typescript"]
@@ -213,31 +174,29 @@ printWidth: 80
                                                                                 | printWidth
 =====================================input======================================
 module Y3 {
-  public module Module {
+  module Module {
       class A { s: string }
   }
 
-  // Apparently this parses :P
-  export private public protected static readonly abstract async enum X { }
+  export enum X { }
 
   interface x {
-      export private static readonly [x: any]: any;
+      readonly [x: any]: any;
   }
 }
 
 =====================================output=====================================
 module Y3 {
-  public module Module {
+  module Module {
     class A {
       s: string;
     }
   }
 
-  // Apparently this parses :P
-  export private public protected static readonly abstract async enum X {}
+  export enum X {}
 
   interface x {
-    export private static readonly [x: any]: any;
+    readonly [x: any]: any;
   }
 }
 
diff --git a/tests/format/typescript/keywords/jsfmt.spec.js b/tests/format/typescript/keywords/jsfmt.spec.js
--- a/tests/format/typescript/keywords/jsfmt.spec.js
+++ b/tests/format/typescript/keywords/jsfmt.spec.js
@@ -1,3 +1,3 @@
 run_spec(import.meta, ["typescript"], {
-  errors: { "babel-ts": ["module.ts", "keywords.ts"] },
+  errors: { "babel-ts": ["keywords.ts"] },
 });
diff --git a/tests/format/typescript/keywords/keywords.ts b/tests/format/typescript/keywords/keywords.ts
--- a/tests/format/typescript/keywords/keywords.ts
+++ b/tests/format/typescript/keywords/keywords.ts
@@ -1,18 +1,5 @@
 // All of these should be an error
 
-module Y3 {
-    public module Module {
-        class A { s: string }
-    }
-
-    // Apparently this parses :P
-    export private public protected static readonly abstract async enum X { }
-
-    interface x {
-        export private static readonly [x: any]: any;
-    }
-}
-
 module Y4 {
     public enum Color { Blue, Red }
 }
diff --git a/tests/format/typescript/keywords/module.ts b/tests/format/typescript/keywords/module.ts
--- a/tests/format/typescript/keywords/module.ts
+++ b/tests/format/typescript/keywords/module.ts
@@ -1,12 +1,11 @@
 module Y3 {
-  public module Module {
+  module Module {
       class A { s: string }
   }
 
-  // Apparently this parses :P
-  export private public protected static readonly abstract async enum X { }
+  export enum X { }
 
   interface x {
-      export private static readonly [x: any]: any;
+      readonly [x: any]: any;
   }
 }