Skip to content

Type narrowing/guard together with nullish coalescing/optional chainingΒ #38136

Closed
@LinusU

Description

@LinusU

TypeScript Version: 3.9.0-dev.20200422

Search Terms: type narrowing guard nullish coalescing switch exhaustive optional chaining

Code

enum MenuType { EatIn, TakeAway }

declare function unreachable (value: never): never
declare let menuTypeFilter: MenuType | null | undefined

// Works :)
switch (menuTypeFilter) {
    case MenuType.EatIn: console.log(1); break
    case MenuType.TakeAway: console.log(2); break
    case null: console.log(3); break
    case undefined: console.log(3); break
    default: unreachable(menuTypeFilter)
}

// Doesn't work :(
switch (menuTypeFilter ?? null) {
    case MenuType.EatIn: console.log(1); break
    case MenuType.TakeAway: console.log(2); break
    case null: console.log(3); break
    default: unreachable(menuTypeFilter)
}

declare let filter: { menuType: MenuType | null | undefined } | null | undefined

// Works :)
if (filter?.menuType != null) {
    switch (filter.menuType) {
        case MenuType.EatIn: console.log(1); break
        case MenuType.TakeAway: console.log(2); break
        default: unreachable(filter.menuType)
    }
}

// Doesn't work :(
switch (filter?.menuType) {
    case MenuType.EatIn: console.log(1); break
    case MenuType.TakeAway: console.log(2); break
    case null: console.log(3); break
    case undefined: console.log(3); break
    default: unreachable(filter.menuType)
}

Expected behavior:

I expected TypeScript to figure out that I have covered all possible values of menuTypeFilter, and thus let me have an unreachable default case.

Actual behavior:

Argument of type 'MenuType | null | undefined' is not assignable to parameter of type 'never'.

Playground Link: Playground Link

Related Issues: (I thought this would have come up but didn't manage to find another issue)


Motivation: I would like to both 1) get an error if the enum ever expands in the future, and 2) handle null and undefined in the same way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions