Skip to content

TypeScript ignore expression if (object instanceof SomeClass) inside for(){} and inside ()=>{}. #13180

Description

TypeScript Version: 2.1.4

Code

class ClassA
{
  propA: any;
}

class ClassB
{
  propB: any;
}

function fn( arr: Array<ClassA | ClassB> )
{
  for( let element of arr )
  {
    if( element instanceof ClassA )
    {
      element.propA = true; // Work as expected

      () =>
      {
        element.propA; // Unexpected error
      }
    }
  }
}

Expected behavior:

Works without error

Actual behavior:

Throw error:

Property 'propA' does not exist on type 'ClassA | ClassB'.
Property 'propA' does not exist on type 'ClassB'.

When I remove the loop for(){}. Works as expected:

class ClassA
{
  propA: any;
}

class ClassB
{
  propB: any;
}

function fn( element: ClassA | ClassB )
{
  if( element instanceof ClassA )
  {
    element.propA = true; // Work as expected

    () =>
    {
      element.propA; // Work as expected
    }
  }
}

Activity

  1. aluanhaddad commented on Dec 27, 2016

    @aluanhaddad
    Contributor
    for (let element of arr) {
      if (element instanceof ClassA) {
        element.propA = true;
    
       () => {
          element.propA;
        }
      }
    }

    Your inner function is closing over a mutable binding that is scoped outside the if block and is thus not always going to be an instance of ClassA.

    To make this work, use a const binding:

    function fn(arr: (ClassA | ClassB)[]) {
      for(const element of arr) {
  2. KostyaTretyak commented on Dec 27, 2016

    @KostyaTretyak
    Author

    Aluan Haddad (@aluanhaddad), thanks for the answer.

    Mutable - possible, but in fact this code is no mutation. TypeScript checks so deeply?

  3. aluanhaddad commented on Dec 27, 2016

    @aluanhaddad
    Contributor

    I think the question comes down to scope of the variable. A constant binding could not be scoped to the for of declarator.

  4. aluanhaddad commented on Dec 27, 2016

    @aluanhaddad
    Contributor

    Also, CFA doesn't track what happens inside of closures to make inferences about types in the outer scope.

    My recommendation, and this is just my personal opinion, is that all bindings should be const unless they need to be let or var. I think it makes code a lot easier to read and is real boon to the maintenance programmer.

  5. KostyaTretyak commented on Dec 27, 2016

    @KostyaTretyak
    Author
  6. locked and limited conversation to collaborators on Jun 19, 2018
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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions