Skip to content

strictNullChecks mode - Object is possibly 'undefined'. #10642

Description

@aliai

In strictNullChecks mode only:

TypeScript Version: nightly (2.0.2)

Code

interface IRoute {
  children?: IRoute[];
}

function register(route: IRoute) {
  if (route.children) {                                   // <-- route.children is of type IRoute|undefined
    Object.keys(route.children).forEach(routeKey => {     // <-- route.children is of type IRoute
      register(route.children[routeKey]);  // <-- Error: Object 'route.children' is possibly 'undefined'.
    });
  }
}

Expected behavior:

There shouldn't be an error here, because route.children is being checked 2 lines above.

Actual behavior:

TypeScript fails to recognize route.children cannot be undefined anymore, because of the nested function. It is the same behavior with both function declaration and arrow functions.

Activity

  1. RyanCavanaugh commented on Aug 31, 2016

    @RyanCavanaugh
    Member

    This is the intended behavior because we don't know that route.children is still not-undefined at the point when the callback executes. It is the case that forEach executes its callback immediately, but this is not true of all functions and we don't know that someone isn't going to remove route.children after you leave the scope of register.

    A good solution is to capture the property in a const, which we can statically know will still be not-undefined

    function register(route: IRoute) {
      const children = route.children;
      if (children) {                                   // <-- children is of type IRoute|undefined
        Object.keys(children).forEach(routeKey => {     // <-- children is of type IRoute
          register(children[routeKey]);  // <-- OK
        });
      }
    }
  2. aliai commented on Aug 31, 2016

    @aliai
    Author

    Thanks Ryan Cavanaugh (@RyanCavanaugh) for the fast feedback :) That's true! I never thought of that possibility.

    I just enabled strictNullChecks for our project and found these 3 issues (2 I posted earlier) that I couldn't wrap my head around. Truly amazing work 👍

  3. unional commented on Nov 21, 2016

    @unional
    Contributor

    Ryan Cavanaugh (@RyanCavanaugh) for some reason this is not working for 2.0.10 and 2.1+ for me right now.

    There got to be something on my side as it was working....

      let deferred = defer()
      setTimeout(() => {
        if (deferred) {
          deferred.resolve(1) // <-- still error with Object is possibly 'undefined'
        }
      }, 1)

    Need some help. 🙇

  4. RyanCavanaugh commented on Nov 21, 2016

    @RyanCavanaugh
    Member

    Homa Wong (@unional) please post question on Stack Overflow and/or provide a self-contained example

  5. unional commented on Nov 21, 2016

    @unional
    Contributor

    Yes. I can reproduce it:

    // index.ts
    export function defer() {
      let resolve
      let reject
      let promise = new Promise((r, j) => {
        resolve = r;
        reject = j;
      });
      return {
        resolve: resolve,
        reject: reject,
        promise: promise
      };
    }
    
    let deferred = defer()
    setTimeout(() => {
      if (deferred !== undefined) {
        deferred.reject(1)  // <-- in VSC there is no error, but compiles fail
      }
    }, 1)
    // tsconfig.json
    {
      "compilerOptions": {
        "lib": [
          "es2015",
          "dom"
        ],
        "strictNullChecks": true,
        "target": "es5"
      },
      "include": [
        "index.ts"
      ]
    }

    error:

    index.ts(18,5): error TS2532: Object is possibly 'undefined'.

    Tested with [email protected]

    And it turns out the issue is fixed in [email protected] and does not exist in 2.0.10

  6. syberkitten commented on Oct 31, 2017

    @syberkitten

    Have the same issue with typescript (tsc) version 2.3.4
    with the process module.

    process.on('message', (msg) => {
      console.log('Message from parent:', msg);
    });
    

    but doing:

    process.send()
    

    does not compile saying:
    error TS2532: Object is possibly 'undefined'.

  7. subins2000 commented on Jul 4, 2020

    @subins2000

    Happens to me too :

    Vue.directive('click-outside', {
      bind: (el, binding, vnode) => {
        const event = ..a function
        if (vnode) {
          vnode.context[binding.expression](event) // Object is possibly 'undefined'.ts(2532)
        }
      }
    }
    

    Both codium & compile shows the error. Issue being tracked at #10642

  8. locked as resolved and limited conversation to collaborators on Jul 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions