Skip to content

Assigning assertion or never breaks nullability control flow analysis #55749

@mqudsi

Description

@mqudsi

🔎 Search Terms

"assigning never, undefined", "assertion control flow", "never control flow", #32695

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about distributive conditional types, never types

⏯ Playground Link

https://www.typescriptlang.org/play?#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXygGdCQYMAKEADwAcYAuJKCEgGngFsRioBzERoQwwsqXgEpGqEADdSAbgBQoSLAQp02PAWKkK1Oo2HIQ7Lj36DhoiYxk4swJSuhwkaTLnxESZADwAKgB8lLQM8AFm3IR8AvBCImKSOr4YhPAGMPBY6QByeLnIENAARhAggUFKiqIYpIhQYAgAYjg48ADeivDwOCUAVgD8jADyA+AYrIoAvoqKGp7aND7kiG2MrTjind3ZiPDkAIRrOAB0ff3bXT09PnqrzGzwAER0ODR6AJ7wqDgY8SAMIdnuIlD1Zj0TucBqcMDgAMrWMTkUEzOYLLT4ZbEABMq3W8E2V12dzI+LOF3Yrxg7y+Pz+AKBILBSDa0P6sIRSN4KKUs3mHkxTCwEHJGzaxJ6YDwQngVHgAF4UvcoZSXm8PmRvr9-iQMMzdqqYXDEYkeajpkA

💻 Code

declare function assert(expr: false, message: string): never;
declare function assert(expr: true, message: string): void;
declare function assert<T>(expr: T, message: string): asserts expr is NonNullable<T>;

interface Foo {
  obj?: Object,
}

function pass(foo: Foo) {
  if (!foo.obj) {
    assert(false, "property not set!");
  }
  foo.obj.toString();
}

function pass2(foo: Foo) {
  assert(foo.obj, "property not set!");
  foo.obj.toString();
}

function fail(foo: Foo) {
  const x = assert(foo.obj, "property not set");
  foo.obj.toString(); // Error: foo.obj may be undefined or null
}

🙁 Actual behavior

Compiler is unable to infer that execution aborts with the assert() call if the resulting never is captured/assigned to a variable.

🙂 Expected behavior

(Nullability/never) control flow analysis should flow past the assignment and continue to subsequent code. If assert() returns never, regardless of whether that never is assigned to a variable or not, the execution cannot flow and the code in question cannot be reached.

Additional information about the issue

Forgive me if this is a known issue; I looked at #32695 and the issues mentioning it, but couldn't find an example that I considered to be a narrow enough match for this one instead of an overlapping or adjacent issue.

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