question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Noncrashing property access through non-null assertion operator should narrow that property to NonNullable

See original GitHub issue

TypeScript Version: 2.3 (Playground)

Code

Using strictNullChecks.

interface Foo {
    optional?: number;
}

interface Bar {
    foo?: Foo;
}

function test(bar: Bar) {
    if (bar.foo!.optional) {
        let num: number = bar.foo.optional;
    }

    if (bar.foo && bar.foo.optional) {
        let num: number = bar.foo.optional;
    }
}

Expected behavior: No errors or warnings.

Actual behavior:

  • num in first if block is number | undefined
  • bar.foo in first if block can be undefined

skarmavbild 2017-05-08 kl 12 58 06

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:1
  • Comments:11 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
Jessidhiacommented, Oct 11, 2017

If the ! operator is used before a . or (), it could be considered a narrowing operator.

For example, this:

function test (a: { b?: { c: string } }) {
  console.log(a.b!.c)
  console.log(a.b.c)
}

could be considered as being more-or-less equivalent to:

function test (a: { b?: { c: string } }) {
  if (a.b == null) throw new TypeError()
  console.log(a.b.c)
  console.log(a.b.c)
}

as the second a.b.c is not reachable if a.b!.c’s erasure of null|undefined does not happen to be proved true at runtime.

But the throw itself is done by the engine… and is an expression throw…

1reaction
RyanCavanaughcommented, May 9, 2017

This isn’t about applying the ! operator to the rest of the block. It’s about this:

function test(bar: Bar) {
    if (bar.foo!.optional) {
        let num: number = bar.foo.optional; // Should not error!
    }

The dotted property access on bar.foo should act as an equivalent type guard to if (bar.foo) {, because the fact we got inside the if block without crashing means it’s not null/undefined

Read more comments on GitHub >

github_iconTop Results From Across the Web

Noncrashing property access through non-null assertion ...
Noncrashing property access through non-null assertion operator should narrow that property to NonNullable #15655.
Read more >
TypeScript non-null assertion operator does not work
I have a type with a conditional property (in this case 'b') type tp1 = {a: string, b?: Array<number>};. I create an object...
Read more >
Using the non-null assertion operator - Learn TypeScript
Using the non-null assertion operator. In this lesson, we will learn how the non-null assertion operator can narrow a type.
Read more >
A note on TypeScript non-null assertion operator - Medium
It lets you deliberately ignore an expression's possible null -ness on a case-by-case basis.
Read more >
Documentation - TypeScript 2.0
A property access or a function call produces a compile-time error if the object or ... the ! non-null assertion operator is simply...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found