diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index 62fbfcbd3c6f..4b5b178068cd 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -155,6 +155,15 @@ export default createRule({ continue; } + // "missing", "optional" and "undefined" types are different runtime objects, + // but all of them have TypeFlags.Undefined type flag + if ( + [...caseTypes].some(tsutils.isIntrinsicUndefinedType) && + tsutils.isIntrinsicUndefinedType(intersectionPart) + ) { + continue; + } + missingLiteralBranchTypes.push(intersectionPart); } } 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 a3e9dd90cdd0..c7b9b62e9ea4 100644 --- a/packages/eslint-plugin/tests/rules/switch-exhaustiveness-check.test.ts +++ b/packages/eslint-plugin/tests/rules/switch-exhaustiveness-check.test.ts @@ -912,6 +912,48 @@ switch (value) { }, ], }, + { + code: ` +function foo(x: string[]) { + switch (x[0]) { + case 'hi': + break; + case undefined: + break; + } +} + `, + languageOptions: { + parserOptions: { + project: './tsconfig.noUncheckedIndexedAccess.json', + projectService: false, + tsconfigRootDir: rootPath, + }, + }, + }, + { + code: ` +function foo(x: string[], y: string | undefined) { + const a = x[0]; + if (typeof a === 'string') { + return; + } + switch (y) { + case 'hi': + break; + case a: + break; + } +} + `, + languageOptions: { + parserOptions: { + project: './tsconfig.noUncheckedIndexedAccess.json', + projectService: false, + tsconfigRootDir: rootPath, + }, + }, + }, ], invalid: [ { @@ -2717,5 +2759,43 @@ switch (value) { }, ], }, + { + code: ` +function foo(x: string[]) { + switch (x[0]) { + case 'hi': + break; + } +} + `, + errors: [ + { + column: 11, + line: 3, + messageId: 'switchIsNotExhaustive', + suggestions: [ + { + messageId: 'addMissingCases', + output: ` +function foo(x: string[]) { + switch (x[0]) { + case 'hi': + break; + case undefined: { throw new Error('Not implemented yet: undefined case') } + } +} + `, + }, + ], + }, + ], + languageOptions: { + parserOptions: { + project: './tsconfig.noUncheckedIndexedAccess.json', + projectService: false, + tsconfigRootDir: rootPath, + }, + }, + }, ], });