Skip to content

More optional chaining control flow analysis - #34597

Merged
Anders Hejlsberg (ahejlsberg) merged 5 commits into
masterfrom
optionalChainControlFlow
Oct 21, 2019
Merged

Anders Hejlsberg (ahejlsberg) merged 5 commits into
masterfrom
optionalChainControlFlow

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented Oct 19, 2019 •

Copy link
Copy Markdown
Member

With this PR we expand on #33821 to reflect more effects of optional chaining in control flow analysis. Some examples:

declare function assert(x: unknown): asserts x;
declare function assertNonNull<T>(x: T): asserts x is NonNullable<T>;

type Thing = { foo?: string | number, bar(): number };

function foo(o: Thing | undefined, value: number) {
    if (o?.foo === value) {
        o;  // Thing
        o.foo;  // number
    }
    if (typeof o?.foo === "string") {
        o;  // Thing
        o.foo;  // string
    }
    switch (o?.foo) {
        case value:
            o;  // Thing
            o.foo;  // number
    }
    switch (typeof o?.foo) {
        case "string":
            o;  // Thing
            o.foo;  // string
    }
    if (!!true) {
        assert(typeof o?.foo === "string");
        o;  // Thing
        o.foo;  // string
    }
    if (!!true) {
        assertNonNull(o?.foo);
        o;  // Thing
        o.foo;  // string | number
    }
}

The complete list of optional chaining constructs with control flow effects in --strictNullChecks mode is now:

  • in code guarded by o?.foo === value, where the type of value doesn't include undefined, we remove undefined and null from the type of o in the true branch, and
  • in code guarded by o?.foo !== value, where the type of value doesn't include undefined, we remove undefined and null from the type of o in the false branch, and
  • in code guarded by o?.foo == value, where the type of value doesn't include undefined or null, we remove undefined and null from the type of o in the true branch, and
  • in code guarded by o?.foo != value, where the type of value doesn't include undefined or null, we remove undefined and null from the type of o in the false branch, and
  • in code guarded by o?.foo === undefined, o?.foo == undefined or o?.foo == null we remove undefined and null from the type of o in the false branch, and
  • in code guarded by o?.foo !== undefined, o?.foo != undefined or o?.foo != null we remove undefined and null from the type of o in the true branch, and
  • in code guarded by typeof o?.foo === "xxx" or typeof o?.foo == "xxx", where "xxx" is not "undefined", we remove undefined and null from the type of o in the true branch, and
  • in code guarded by typeof o?.foo !== "xxx" or typeof o?.foo != "xxx", where "xxx" is not "undefined", we remove undefined and null from the type of o in the false branch, and
  • in code guarded by typeof o?.foo === "undefined" or typeof o?.foo == "undefined" we remove undefined and null from the type of o in the false branch, and
  • in code guarded by typeof o?.foo !== "undefined" or typeof o?.foo != "undefined" we remove undefined and null from the type of o in the true branch, and
  • in code guarded by o?.foo instanceof xxx we remove undefined and null from the type of o in the true branch, and
  • in a case xxx block of a switch (o?.foo) statement we remove undefined and null from the type of o provided the type of xxx doesn't include undefined, and
  • in a case xxx block of a switch (typeof o?.foo) statement we remove undefined and null from the type of o provided xxx isn't "undefined", and
  • in code following a top-level call expression assertIsXXX(o?.foo), where assertIsXXX is declared with an asserts x is XXX type predicate and type XXX doesn't include undefined, we remove undefined and null from the type of o, and
  • in code following a top-level call expression assert(xxx), where assert is declared with an asserts x type predicate, we reflect the false branch effects of the logical expression xxx, including effects from optional property access chains.

Fixes #34570.

@ahejlsberg Anders Hejlsberg (ahejlsberg) changed the title More optional control flow analysis More optional chaining control flow analysis Oct 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optional chaining control flow refinements missing

2 participants