Repository: swc-project/swc (rust)

Issue:
Compile error `in`/`out` modifier already seen
### Describe the bug

Referring to an unexported type that uses the recent TS variance notation breaks on version 1.3.50.

Same code below but with `export` in front of `type SubtypeGuard` compiles correctly.

### Input code

```typescript
type SubtypeGuard<in P, out C extends P> = (object: P) => object is C;

export type IdTypeGuard<out T extends string> = SubtypeGuard<string, T>;
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false
    },
    "target": "es2022",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

https://play.swc.rs/?version=1.3.50&code=H4sIAAAAAAAAA1XNPQqAMBQD4L2nyKjgCfzp4iBuBXsBtQ%2BpQyvtK%2BjttQiCU0iGL3wdhCkt%2FOSQ5mBa66Aq%2BMToQSeTMxFKokPhl51WrqFKdBJvg43oGyHoPHxgZAaj0Z%2BWHf05kYN1W8Z%2Bl%2B9cQctG3GDLLi6RAAAA&config=H4sIAAAAAAAAA1VPOw7DIAzdOQXy3KFi6NA79BCIOhERAYQdqSjK3QsJpM1mv4%2Ff8yqkhIkMPOVaxrJEnQjTuReEsmf9KQhwjkgm2chw6yxTpQbtCHdoOxhgnUbk6kJSd6WaA1wIhN3RsNl6O%2BT%2FTBPmmJDoKqxS7UeH10TRUmEO72Un2y%2B179HgAT9RDzsPg6VXd3JaUGxfBMLf3xcBAAA%3D

### Expected behavior

The code is valid and should compile as it did on version 1.3.49

### Actual behavior

Fail with:

```
  x 'in' modifier already seen.
   ,-[input.ts:1:1]
 1 | type SubtypeGuard<in P, out C extends P> = (object: P) => object is C;
   :                   ^^
 2 | 
 3 | export type IdTypeGuard<out T extends string> = SubtypeGuard<string, T>;
   `----

  x 'out' modifier already seen.
   ,-[input.ts:1:1]
 1 | type SubtypeGuard<in P, out C extends P> = (object: P) => object is C;
   :                         ^^^
 2 | 
 3 | export type IdTypeGuard<out T extends string> = SubtypeGuard<string, T>;
   `----


Caused by:
    0: failed to process js file
    1: Syntax Error
```

### Version

Workin on 1.3.49, broken on 1.3.50 and above

### Additional context

_No response_

Pull request:
fix(es/parser): Fix handling of `in` and `out` of typescript
**Description:**


**Related issue:**

 - Closes #7305.

Patch:
diff --git a/crates/swc_ecma_parser/src/parser/typescript.rs b/crates/swc_ecma_parser/src/parser/typescript.rs
index f64d7d4ea9..baa370010d 100644
--- a/crates/swc_ecma_parser/src/parser/typescript.rs
+++ b/crates/swc_ecma_parser/src/parser/typescript.rs
@@ -407,7 +407,6 @@ impl<I: Tokens> Parser<I> {
                     }
                 }
                 "in" => {
-                    is_in = true;
                     if !permit_in_out {
                         self.emit_err(self.input.prev_span(), SyntaxError::TS1274(js_word!("in")));
                     } else if is_in {
@@ -418,14 +417,15 @@ impl<I: Tokens> Parser<I> {
                             SyntaxError::TS1029(js_word!("in"), js_word!("out")),
                         );
                     }
+                    is_in = true;
                 }
                 "out" => {
-                    is_out = true;
                     if !permit_in_out {
                         self.emit_err(self.input.prev_span(), SyntaxError::TS1274(js_word!("out")));
                     } else if is_out {
                         self.emit_err(self.input.prev_span(), SyntaxError::TS1030(js_word!("out")));
                     }
+                    is_out = true;
                 }
                 other => self.emit_err(self.input.prev_span(), SyntaxError::TS1273(other.into())),
             };


Test patch:
diff --git a/crates/swc/tests/fixture/issues-7xxx/7305/1/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7305/1/input/.swcrc
new file mode 100644
index 0000000000..3dc717ffb5
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7305/1/input/.swcrc
@@ -0,0 +1,19 @@
+{
+    "jsc": {
+        "parser": {
+            "syntax": "typescript",
+            "tsx": false
+        },
+        "target": "es2022",
+        "loose": false,
+        "minify": {
+            "compress": false,
+            "mangle": false
+        }
+    },
+    "module": {
+        "type": "es6"
+    },
+    "minify": false,
+    "isModule": true
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-7xxx/7305/1/input/index.ts b/crates/swc/tests/fixture/issues-7xxx/7305/1/input/index.ts
new file mode 100644
index 0000000000..8e87e01d48
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7305/1/input/index.ts
@@ -0,0 +1,3 @@
+type SubtypeGuard<in P, out C extends P> = (object: P) => object is C;
+
+export type IdTypeGuard<out T extends string> = SubtypeGuard<string, T>;
diff --git a/crates/swc/tests/fixture/issues-7xxx/7305/1/output/index.ts b/crates/swc/tests/fixture/issues-7xxx/7305/1/output/index.ts
new file mode 100644
index 0000000000..2234b9cae1
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-7xxx/7305/1/output/index.ts
@@ -0,0 +1,1 @@
+export { };
diff --git a/crates/swc_ecma_parser/tests/typescript-errors/variance-annotations/1/input.ts.swc-stderr b/crates/swc_ecma_parser/tests/typescript-errors/variance-annotations/1/input.ts.swc-stderr
index 93cf16a030..1420b07e51 100644
--- a/crates/swc_ecma_parser/tests/typescript-errors/variance-annotations/1/input.ts.swc-stderr
+++ b/crates/swc_ecma_parser/tests/typescript-errors/variance-annotations/1/input.ts.swc-stderr
@@ -1,152 +1,4 @@
 
-  x 'out' modifier already seen.
-   ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:1:1]
- 1 | type Covariant<out T> = {
-   :                ^^^
- 2 |     x: T;
-   `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:10:1]
- 10 | 
- 11 | type Contravariant<in T> = {
-    :                    ^^
- 12 |     f: (x: T) => void;
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:20:1]
- 20 | 
- 21 | type Invariant<in out T> = {
-    :                ^^
- 22 |     f: (x: T) => T;
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:20:1]
- 20 | 
- 21 | type Invariant<in out T> = {
-    :                   ^^^
- 22 |     f: (x: T) => T;
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:32:1]
- 32 | 
- 33 | type T10<out T> = T;
-    :          ^^^
- 34 | type T11<in T> = keyof T;
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:33:1]
- 33 | type T10<out T> = T;
- 34 | type T11<in T> = keyof T;
-    :          ^^
- 35 | type T12<out T, out K extends keyof T> = T[K];
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:34:1]
- 34 | type T11<in T> = keyof T;
- 35 | type T12<out T, out K extends keyof T> = T[K];
-    :          ^^^
- 36 | type T13<in out T> = T[keyof T];
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:34:1]
- 34 | type T11<in T> = keyof T;
- 35 | type T12<out T, out K extends keyof T> = T[K];
-    :                 ^^^
- 36 | type T13<in out T> = T[keyof T];
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:35:1]
- 35 | type T12<out T, out K extends keyof T> = T[K];
- 36 | type T13<in out T> = T[keyof T];
-    :          ^^
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:35:1]
- 35 | type T12<out T, out K extends keyof T> = T[K];
- 36 | type T13<in out T> = T[keyof T];
-    :             ^^^
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:39:1]
- 39 | 
- 40 | type Covariant1<in T> = {  // Error
-    :                 ^^
- 41 |     x: T;
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:43:1]
- 43 | 
- 44 | type Contravariant1<out T> = keyof T;  // Error
-    :                     ^^^
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:45:1]
- 45 | 
- 46 | type Contravariant2<out T> = {  // Error
-    :                     ^^^
- 47 |     f: (x: T) => void;
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:49:1]
- 49 | 
- 50 | type Invariant1<in T> = {  // Error
-    :                 ^^
- 51 |     f: (x: T) => T;
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:53:1]
- 53 | 
- 54 | type Invariant2<out T> = {  // Error
-    :                 ^^^
- 55 |     f: (x: T) => T;
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:59:1]
- 59 | 
- 60 | type Foo1<in T> = {  // Error
-    :           ^^
- 61 |     x: T;
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:70:1]
- 70 | 
- 71 | type Foo2<out T> = {  // Error
-    :           ^^^
- 72 |     x: T;
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:81:1]
- 81 | 
- 82 | type Foo3<in out T> = {
-    :           ^^
- 83 |     x: T;
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:81:1]
- 81 | 
- 82 | type Foo3<in out T> = {
-    :              ^^^
- 83 |     x: T;
-    `----
-
   x 'public' modifier cannot appear on a type parameter
     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:94:1]
  94 | 
@@ -158,43 +10,11 @@
   x 'in' modifier already seen.
     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:95:1]
  95 | type T20<public T> = T;  // Error
- 96 | type T21<in out in T> = T;  // Error
-    :          ^^
- 97 | type T22<in out out T> = T;  // Error
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:95:1]
- 95 | type T20<public T> = T;  // Error
- 96 | type T21<in out in T> = T;  // Error
-    :             ^^^
- 97 | type T22<in out out T> = T;  // Error
-    `----
-
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:95:1]
- 95 | type T20<public T> = T;  // Error
  96 | type T21<in out in T> = T;  // Error
     :                 ^^
  97 | type T22<in out out T> = T;  // Error
     `----
 
-  x 'in' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:96:1]
- 96 | type T21<in out in T> = T;  // Error
- 97 | type T22<in out out T> = T;  // Error
-    :          ^^
- 98 | type T23<out in T> = T;  // Error
-    `----
-
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:96:1]
- 96 | type T21<in out in T> = T;  // Error
- 97 | type T22<in out out T> = T;  // Error
-    :             ^^^
- 98 | type T23<out in T> = T;  // Error
-    `----
-
   x 'out' modifier already seen.
     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:96:1]
  96 | type T21<in out in T> = T;  // Error
@@ -203,14 +23,7 @@
  98 | type T23<out in T> = T;  // Error
     `----
 
-  x 'out' modifier already seen.
-    ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:97:1]
- 97 | type T22<in out out T> = T;  // Error
- 98 | type T23<out in T> = T;  // Error
-    :          ^^^
-    `----
-
-  x 'in' modifier already seen.
+  x 'in' modifier must precede 'out' modifier.
     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:97:1]
  97 | type T22<in out out T> = T;  // Error
  98 | type T23<out in T> = T;  // Error
@@ -247,42 +60,3 @@
      :     ^^^
  106 | }
      `----
-
-  x 'out' modifier already seen.
-     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:109:1]
- 109 | 
- 110 | interface Baz<out T> {}
-     :               ^^^
- 111 | interface Baz<in T> {}
-     `----
-
-  x 'in' modifier already seen.
-     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:110:1]
- 110 | interface Baz<out T> {}
- 111 | interface Baz<in T> {}
-     :               ^^
-     `----
-
-  x 'out' modifier already seen.
-     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:120:1]
- 120 | 
- 121 | interface Parent<out A> {
-     :                  ^^^
- 122 |     child: Child<A> | null;
-     `----
-
-  x 'in' modifier already seen.
-     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:139:1]
- 139 | 
- 140 | declare class StateNode<TContext, in out TEvent extends { type: string }> {
-     :                                   ^^
- 141 |     _storedEvent: TEvent;
-     `----
-
-  x 'out' modifier already seen.
-     ,-[$DIR/tests/typescript-errors/variance-annotations/1/input.ts:139:1]
- 139 | 
- 140 | declare class StateNode<TContext, in out TEvent extends { type: string }> {
-     :                                      ^^^
- 141 |     _storedEvent: TEvent;
-     `----
diff --git a/crates/swc_ecma_parser/tests/typescript/issue-7305/input.ts b/crates/swc_ecma_parser/tests/typescript/issue-7305/input.ts
new file mode 100644
index 0000000000..8e87e01d48
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/typescript/issue-7305/input.ts
@@ -0,0 +1,3 @@
+type SubtypeGuard<in P, out C extends P> = (object: P) => object is C;
+
+export type IdTypeGuard<out T extends string> = SubtypeGuard<string, T>;
diff --git a/crates/swc_ecma_parser/tests/typescript/issue-7305/input.ts.json b/crates/swc_ecma_parser/tests/typescript/issue-7305/input.ts.json
new file mode 100644
index 0000000000..fd2fa053ce
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/typescript/issue-7305/input.ts.json
@@ -0,0 +1,330 @@
+{
+  "type": "Module",
+  "span": {
+    "start": 1,
+    "end": 145,
+    "ctxt": 0
+  },
+  "body": [
+    {
+      "type": "TsTypeAliasDeclaration",
+      "span": {
+        "start": 1,
+        "end": 71,
+        "ctxt": 0
+      },
+      "declare": false,
+      "id": {
+        "type": "Identifier",
+        "span": {
+          "start": 6,
+          "end": 18,
+          "ctxt": 0
+        },
+        "value": "SubtypeGuard",
+        "optional": false
+      },
+      "typeParams": {
+        "type": "TsTypeParameterDeclaration",
+        "span": {
+          "start": 18,
+          "end": 41,
+          "ctxt": 0
+        },
+        "parameters": [
+          {
+            "type": "TsTypeParameter",
+            "span": {
+              "start": 19,
+              "end": 23,
+              "ctxt": 0
+            },
+            "name": {
+              "type": "Identifier",
+              "span": {
+                "start": 22,
+                "end": 23,
+                "ctxt": 0
+              },
+              "value": "P",
+              "optional": false
+            },
+            "in": true,
+            "out": false,
+            "const": false,
+            "constraint": null,
+            "default": null
+          },
+          {
+            "type": "TsTypeParameter",
+            "span": {
+              "start": 25,
+              "end": 40,
+              "ctxt": 0
+            },
+            "name": {
+              "type": "Identifier",
+              "span": {
+                "start": 29,
+                "end": 30,
+                "ctxt": 0
+              },
+              "value": "C",
+              "optional": false
+            },
+            "in": false,
+            "out": true,
+            "const": false,
+            "constraint": {
+              "type": "TsTypeReference",
+              "span": {
+                "start": 39,
+                "end": 40,
+                "ctxt": 0
+              },
+              "typeName": {
+                "type": "Identifier",
+                "span": {
+                  "start": 39,
+                  "end": 40,
+                  "ctxt": 0
+                },
+                "value": "P",
+                "optional": false
+              },
+              "typeParams": null
+            },
+            "default": null
+          }
+        ]
+      },
+      "typeAnnotation": {
+        "type": "TsFunctionType",
+        "span": {
+          "start": 44,
+          "end": 70,
+          "ctxt": 0
+        },
+        "params": [
+          {
+            "type": "Identifier",
+            "span": {
+              "start": 45,
+              "end": 54,
+              "ctxt": 0
+            },
+            "value": "object",
+            "optional": false,
+            "typeAnnotation": {
+              "type": "TsTypeAnnotation",
+              "span": {
+                "start": 51,
+                "end": 54,
+                "ctxt": 0
+              },
+              "typeAnnotation": {
+                "type": "TsTypeReference",
+                "span": {
+                  "start": 53,
+                  "end": 54,
+                  "ctxt": 0
+                },
+                "typeName": {
+                  "type": "Identifier",
+                  "span": {
+                    "start": 53,
+                    "end": 54,
+                    "ctxt": 0
+                  },
+                  "value": "P",
+                  "optional": false
+                },
+                "typeParams": null
+              }
+            }
+          }
+        ],
+        "typeParams": null,
+        "typeAnnotation": {
+          "type": "TsTypeAnnotation",
+          "span": {
+            "start": 56,
+            "end": 70,
+            "ctxt": 0
+          },
+          "typeAnnotation": {
+            "type": "TsTypePredicate",
+            "span": {
+              "start": 59,
+              "end": 70,
+              "ctxt": 0
+            },
+            "asserts": false,
+            "paramName": {
+              "type": "Identifier",
+              "span": {
+                "start": 59,
+                "end": 65,
+                "ctxt": 0
+              },
+              "value": "object",
+              "optional": false
+            },
+            "typeAnnotation": {
+              "type": "TsTypeAnnotation",
+              "span": {
+                "start": 69,
+                "end": 70,
+                "ctxt": 0
+              },
+              "typeAnnotation": {
+                "type": "TsTypeReference",
+                "span": {
+                  "start": 69,
+                  "end": 70,
+                  "ctxt": 0
+                },
+                "typeName": {
+                  "type": "Identifier",
+                  "span": {
+                    "start": 69,
+                    "end": 70,
+                    "ctxt": 0
+                  },
+                  "value": "C",
+                  "optional": false
+                },
+                "typeParams": null
+              }
+            }
+          }
+        }
+      }
+    },
+    {
+      "type": "ExportDeclaration",
+      "span": {
+        "start": 73,
+        "end": 145,
+        "ctxt": 0
+      },
+      "declaration": {
+        "type": "TsTypeAliasDeclaration",
+        "span": {
+          "start": 80,
+          "end": 145,
+          "ctxt": 0
+        },
+        "declare": false,
+        "id": {
+          "type": "Identifier",
+          "span": {
+            "start": 85,
+            "end": 96,
+            "ctxt": 0
+          },
+          "value": "IdTypeGuard",
+          "optional": false
+        },
+        "typeParams": {
+          "type": "TsTypeParameterDeclaration",
+          "span": {
+            "start": 96,
+            "end": 118,
+            "ctxt": 0
+          },
+          "parameters": [
+            {
+              "type": "TsTypeParameter",
+              "span": {
+                "start": 97,
+                "end": 117,
+                "ctxt": 0
+              },
+              "name": {
+                "type": "Identifier",
+                "span": {
+                  "start": 101,
+                  "end": 102,
+                  "ctxt": 0
+                },
+                "value": "T",
+                "optional": false
+              },
+              "in": false,
+              "out": true,
+              "const": false,
+              "constraint": {
+                "type": "TsKeywordType",
+                "span": {
+                  "start": 111,
+                  "end": 117,
+                  "ctxt": 0
+                },
+                "kind": "string"
+              },
+              "default": null
+            }
+          ]
+        },
+        "typeAnnotation": {
+          "type": "TsTypeReference",
+          "span": {
+            "start": 121,
+            "end": 144,
+            "ctxt": 0
+          },
+          "typeName": {
+            "type": "Identifier",
+            "span": {
+              "start": 121,
+              "end": 133,
+              "ctxt": 0
+            },
+            "value": "SubtypeGuard",
+            "optional": false
+          },
+          "typeParams": {
+            "type": "TsTypeParameterInstantiation",
+            "span": {
+              "start": 133,
+              "end": 144,
+              "ctxt": 0
+            },
+            "params": [
+              {
+                "type": "TsKeywordType",
+                "span": {
+                  "start": 134,
+                  "end": 140,
+                  "ctxt": 0
+                },
+                "kind": "string"
+              },
+              {
+                "type": "TsTypeReference",
+                "span": {
+                  "start": 142,
+                  "end": 143,
+                  "ctxt": 0
+                },
+                "typeName": {
+                  "type": "Identifier",
+                  "span": {
+                    "start": 142,
+                    "end": 143,
+                    "ctxt": 0
+                  },
+                  "value": "T",
+                  "optional": false
+                },
+                "typeParams": null
+              }
+            ]
+          }
+        }
+      }
+    }
+  ],
+  "interpreter": null
+}