Skip to content

Implicitly typed type guard does not guardΒ #63715

Description

@OldStarchy

πŸ”Ž Search Terms

"never type guard", "never returning function does not guard", "type guard parameter"

πŸ•— Version & Regression Information

Tested in the playground on major versions 4.0.5 to 6.0.3, same for all.

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=6.0.3#code/GYVwdgxgLglg9mABAcwKZQOIgIYCcAmAPACoB8AFMGAFyLkBG2MANreQJSIC8piYqAN1S5OPRMXa1iiAN4AoRIlzoQuJFXIduvGYigALXHADuiAXBj5EABgDciAL7tbch3LmhIsBIhgBbAAdmGAgYKHIBbFZZPWxkWgBybAT7bFoAZyhcGDBkR0QAHxioOMT6BIAaRHpaMBA-emFHTnlFZShVJDRMHAJNRhZRHQVFX2A6SOYAOhK8ri5EJITOAeYOFxG2lTUzKKn6ewB6Q8RwVAAPANRoVCthI1wRp1d3T2h4JAugkLCIqNpdLNEslUhksjk8g5CsVSotylUanx6o1cM1ZCN2p0UOgsHh8P0mNEtGJ+EIRNp0aMxhM9rNuAslitCet3FTMTtJvsjic4ABrJ7sF5yCAITK7aKA2FLUGITLZXL5IqS+JwyrVWrIppQhbKspqxEAFkcwtFUEQ2G4vkCwVC4UmzkQx3NYAAniawGL6JavjbfvbuUiGsIgA

πŸ’» Code

A parameter explicitly typed as () => never can be used as a type guard, but one with an implicit type () => void does not.

function getGuard<T>(fn: (bail: () => never) => T): T {
  return fn(() => { throw void 0; });
}

function implicit(val: { tag: 'a'; a: string } | { tag: 'b', b: number }) {
  return getGuard((bail) => {
    if (val.tag == 'a') bail();

    return val.b; // unexpected error
  })
}

function explicit(val: { tag: 'a'; a: string } | { tag: 'b', b: number }) {
  return getGuard((bail: () => never) => {
    if (val.tag == 'a') bail();

    return val.b; // ok
  })
}

const val: { tag: 'a'; a: string } | { tag: 'b', b: number } = { tag: 'b', b: 4 }
const a = implicit(val); // any
const b = explicit(val); // number

πŸ™ Actual behavior

The type is not narrowed after invoking a never-returning function in an if block

πŸ™‚ Expected behavior

The type is narrowed the same way that it does for an explicitly typed guard, a throw, or a return etc..

Additional information about the issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions