denoland / deno_lint

Blazing fast linter for JavaScript and TypeScript written in Rust
https://lint.deno.land/
MIT License
1.53k stars 172 forks source link

Rule suggestion: `switch-exhaustiveness-check` #1160

Open lionel-rowe opened 1 year ago

lionel-rowe commented 1 year ago

Disallow non-exhaustive switch statements. Especially useful when expanding an enum/string union/numeric union type to allow new options.

See https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md

Wrong ❌

type X = 'A' | 'B'

declare const x: X

switch (x) {
    case 'A':
        break
}

OK ✅

switch (x) {
    case 'A':
        break
    case 'B':
        break
}

OK ✅

switch (x) {
    case 'A':
        break
    default:
        break
}
magurotuna commented 1 year ago

I would love this lint rule, but unfortunately this would require access to type information that TypeScript provides but deno_lint cannot access.

lionel-rowe commented 1 year ago

For anyone else that stumbles on this issue, I figured out a workaround via adding a dummy default clause. The non-exhaustive switch statement fails type checking with Type 'string' is not assignable to type 'never'. Playground

type X = 'A' | 'B'
declare const x: X

// `Type 'string' is not assignable to type 'never'.`
switch (x) {
    case 'A':
        break
    default: void ((): never => x)
}

// OK
switch (x) {
    case 'A':
        break
    case 'B':
        break
    default: void ((): never => x)
}

// OK
switch (x) {
    case 'A':
        break
    default:
        break
}