diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index 316770b6b131..6849d98f62d9 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -142,6 +142,16 @@ export default createRule({ return; } + function typeToString(type: ts.Type): string { + return checker.typeToString( + type, + undefined, + ts.TypeFormatFlags.AllowUniqueESSymbolType | + ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | + ts.TypeFormatFlags.UseFullyQualifiedType, + ); + } + function getSwitchMetadata(node: TSESTree.SwitchStatement): SwitchMetadata { const defaultCase = node.cases.find( switchCase => switchCase.test == null, @@ -230,7 +240,7 @@ export default createRule({ .map(missingType => tsutils.isTypeFlagSet(missingType, ts.TypeFlags.ESSymbolLike) ? `typeof ${missingType.getSymbol()?.escapedName as string}` - : checker.typeToString(missingType), + : typeToString(missingType), ) .join(' | '), }, @@ -282,7 +292,7 @@ export default createRule({ ) ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion missingBranchName! - : checker.typeToString(missingBranchType); + : typeToString(missingBranchType); if ( symbolName && diff --git a/packages/eslint-plugin/tests/fixtures/switch-exhaustiveness-check.ts b/packages/eslint-plugin/tests/fixtures/switch-exhaustiveness-check.ts new file mode 100644 index 000000000000..277dc2a7c28c --- /dev/null +++ b/packages/eslint-plugin/tests/fixtures/switch-exhaustiveness-check.ts @@ -0,0 +1,6 @@ +export namespace A { + export enum B { + C, + D, + } +} diff --git a/packages/eslint-plugin/tests/fixtures/tsconfig.json b/packages/eslint-plugin/tests/fixtures/tsconfig.json index d8141e1ddfa4..9fb244b4171e 100644 --- a/packages/eslint-plugin/tests/fixtures/tsconfig.json +++ b/packages/eslint-plugin/tests/fixtures/tsconfig.json @@ -15,6 +15,7 @@ "mixed-enums-decl.ts", "react.tsx", "var-declaration.ts", - "errors.ts" + "errors.ts", + "switch-exhaustiveness-check.ts" ] } diff --git a/packages/eslint-plugin/tests/rules/switch-exhaustiveness-check.test.ts b/packages/eslint-plugin/tests/rules/switch-exhaustiveness-check.test.ts index 263c9b81bb5c..5c8539dec279 100644 --- a/packages/eslint-plugin/tests/rules/switch-exhaustiveness-check.test.ts +++ b/packages/eslint-plugin/tests/rules/switch-exhaustiveness-check.test.ts @@ -2947,5 +2947,87 @@ switch (literal) { }, ], }, + { + code: ` + export namespace A { + export enum B { + C, + D, + } + } + declare const foo: A.B; + switch (foo) { + case A.B.C: { + break; + } + } + `, + errors: [ + { + column: 17, + data: { + missingBranches: 'A.B.D', + }, + line: 9, + messageId: 'switchIsNotExhaustive', + suggestions: [ + { + messageId: 'addMissingCases', + output: ` + export namespace A { + export enum B { + C, + D, + } + } + declare const foo: A.B; + switch (foo) { + case A.B.C: { + break; + } + case A.B.D: { throw new Error('Not implemented yet: A.B.D case') } + } + `, + }, + ], + }, + ], + }, + { + code: ` + import { A } from './switch-exhaustiveness-check'; + declare const foo: A.B; + switch (foo) { + case A.B.C: { + break; + } + } + `, + errors: [ + { + column: 17, + data: { + missingBranches: 'A.B.D', + }, + line: 4, + messageId: 'switchIsNotExhaustive', + suggestions: [ + { + messageId: 'addMissingCases', + output: ` + import { A } from './switch-exhaustiveness-check'; + declare const foo: A.B; + switch (foo) { + case A.B.C: { + break; + } + case A.B.D: { throw new Error('Not implemented yet: A.B.D case') } + } + `, + }, + ], + }, + ], + }, ], });