diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index a490f335a8a..dfb37b2faf0 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -173,6 +173,7 @@ import { isJSDocEnumTag, isJSDocTemplateTag, isJSDocTypeAlias, + isJSDocTypeAssertion, isJsonSourceFile, isJsxNamespacedName, isLeftHandSideExpression, @@ -1223,6 +1224,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.CallExpression: return hasNarrowableArgument(expr as CallExpression); case SyntaxKind.ParenthesizedExpression: + if (isJSDocTypeAssertion(expr)) { + return false; + } + // fallthrough case SyntaxKind.NonNullExpression: return isNarrowingExpression((expr as ParenthesizedExpression | NonNullExpression).expression); case SyntaxKind.BinaryExpression: diff --git a/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.errors.txt b/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.errors.txt new file mode 100644 index 00000000000..d002eb65ae0 --- /dev/null +++ b/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.errors.txt @@ -0,0 +1,22 @@ +index.js(12,8): error TS2678: Type '"invalid"' is not comparable to type '"foo" | "bar"'. + + +==== index.js (1 errors) ==== + let value = ""; + + switch (/** @type {"foo" | "bar"} */ (value)) { + case "bar": + value; + break; + + case "foo": + value; + break; + + case "invalid": + ~~~~~~~~~ +!!! error TS2678: Type '"invalid"' is not comparable to type '"foo" | "bar"'. + value; + break; + } + \ No newline at end of file diff --git a/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.symbols b/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.symbols new file mode 100644 index 00000000000..42a9dd4c464 --- /dev/null +++ b/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.symbols @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/parenthesizedJSDocCastDoesNotNarrow.ts] //// + +=== index.js === +let value = ""; +>value : Symbol(value, Decl(index.js, 0, 3)) + +switch (/** @type {"foo" | "bar"} */ (value)) { +>value : Symbol(value, Decl(index.js, 0, 3)) + + case "bar": + value; +>value : Symbol(value, Decl(index.js, 0, 3)) + + break; + + case "foo": + value; +>value : Symbol(value, Decl(index.js, 0, 3)) + + break; + + case "invalid": + value; +>value : Symbol(value, Decl(index.js, 0, 3)) + + break; +} + diff --git a/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.types b/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.types new file mode 100644 index 00000000000..a39ab487cce --- /dev/null +++ b/tests/baselines/reference/parenthesizedJSDocCastDoesNotNarrow.types @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/parenthesizedJSDocCastDoesNotNarrow.ts] //// + +=== index.js === +let value = ""; +>value : string +>"" : "" + +switch (/** @type {"foo" | "bar"} */ (value)) { +>(value) : "foo" | "bar" +>value : string + + case "bar": +>"bar" : "bar" + + value; +>value : string + + break; + + case "foo": +>"foo" : "foo" + + value; +>value : string + + break; + + case "invalid": +>"invalid" : "invalid" + + value; +>value : string + + break; +} + diff --git a/tests/cases/compiler/parenthesizedJSDocCastDoesNotNarrow.ts b/tests/cases/compiler/parenthesizedJSDocCastDoesNotNarrow.ts new file mode 100644 index 00000000000..69490613e1f --- /dev/null +++ b/tests/cases/compiler/parenthesizedJSDocCastDoesNotNarrow.ts @@ -0,0 +1,22 @@ +// @strict: true +// @noEmit: true +// @checkJs: true +// @allowJs: true + +// @filename: index.js + +let value = ""; + +switch (/** @type {"foo" | "bar"} */ (value)) { + case "bar": + value; + break; + + case "foo": + value; + break; + + case "invalid": + value; + break; +}