javascript:S3403 does not recognize derived classes with double inheritance and type annotations

Please provide

  • Operating system: Ubuntu 22.04.1 LTS
  • SonarLint plugin version: v3.14.0
  • Programming language you’re coding in: JavaScript
  • Is connected mode used: no

And a thorough description of the problem / question:

class FileBase {
  /**
   * @type {'f'|'d'|'g'|'l'}
   */
  type
}

class Container extends FileBase {
  /**
   * @type {{[fileName: string]: FileBase}}
   */
  children = {}
}

class Folder extends Container {
  type = 'd'
}

/**
 * @param {FileBase} a
 * @param {Folder} b
 */
function f(a, b) {
  if (a === b) {               // Remove this "===" check; it will always be false. Did you mean to use "=="? sonarlint(javascript:S3403)
    return a
  }
  return b
}

In this code, SonarLint does not recognize correctly that a of type FileBase can in fact also be of the derived type Folder, and hence a and b could be the same object.

This seems to be a rather subtle error as making small changes removes the error:

Removing @type {'f'|'d'|'g'|'l'} from FileBase.type will remove the error:

class FileBase {
  type
}

class Container extends FileBase {
  /**
   * @type {{[fileName: string]: FileBase}}
   */
  children = {}
}

class Folder extends Container {
  type = 'd'
}

/**
 * @param {FileBase} a
 * @param {Folder} b
 */
function f(a, b) {
  if (a === b) {               // No error
    return a
  }
  return b
}

Making Folder extending FileBase directly will also remove this error:

class FileBase {
  /**
   * @type {'f'|'d'|'g'|'l'}
   */
  type
}

class Container extends FileBase {
  /**
   * @type {{[fileName: string]: FileBase}}
   */
  children = {}
}

class Folder extends FileBase {
  type = 'd'
}

/**
 * @param {FileBase} a
 * @param {Folder} b
 */
function f(a, b) {
  if (a === b) {               // No error
    return a
  }
  return b
}

Hi @vincesp,

I cannot reproduce locally. Are you using latest version of the SonarLint plugin? What IDE are you using?

Cheers,
Victor

Hi @vincesp,

I’m finally able to reproduce. We are investigating the issue and will come back to you.

Cheers,
Victor

2 Likes

Hi victor.diez,
Thanks for looking into this. I use:
SonarLint plugin v3.15.1
VS Code v1.75.1

1 Like

Hello @vincesp,

after some investigation, it seems the best way to solve this issue would be to redeclare the type of type in Folder class:


class Folder extends Container {
  /**
   * @type {'f'|'d'|'g'|'l'}
   */
  type = 'd'
}

Transforming your code to Typescript helped us understand the problem in more detail, as we could see the following error:

As you are redeclaring a field, it will infer the type from its value (‘string’ in this case), so the Typechecker will consider parent and child classes type field types incompatible. By assigning explicitly the type as you do with parent class, it’s now able to consider both types are equal.

Cheers,
Victor

I fixed it by setting the type to

  /**
   * @type {'d'}
   */

Which makes it even more explicit that for a folder, the type is always 'd'.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.