Suspicious type coercion should be avoided

  • BAD_TYPE_COERCION
  • Error
  • Medium
  • No tags

This rule applies when suspicious type coercion occurs.

JavaScript utilizes implicit type conversion widely, so a programmer needs to check type conversion with caution.

The following is suspicious implicit type conversion for X:

  1. X is converted to string

    • X + string (X is undefined or symbol)
  2. X is converted to number

    • X + undefined/null/boolean/number/symbol (X is undefined, null, or symbol)
    • X @ (X is undefined/null/non-numeric string/symbol. @ means -, *, /, %.)
    • X @ Y (X is undefined/null/boolean/non-numeric string/symbol/object except for the case where X and Y are both strings. @ means <, <=, >, >=.)
    • X & (X is undefined/null/boolean/non-numeric string/symbol/object)
    • X | boolean (X is boolean)
    • X | Y (X is symbol)
    • X @ Y (X is boolean and Y is number/string/object. Or X is non-numeric string and Y is boolean/number. Or X is object and Y is boolean/number. @ means ==, !=.)
  3. X is converted to boolean (X is a primitive wrapper object)

    • if (X) …
    • X && …
    • X || …
    • X ? … : …
    • !X

For your reference, JavaScript converts a type like the following:

  1. undefined is converted to string: "undefined"
  2. undefined is converted to number: NaN
  3. null is converted to string: "null"
  4. null is converted to number: 0
  5. boolean is converted to number: false is 0, true is 1
  6. Empty string is converted to number: 0
  7. Neither empty nor numeric string is converted to number: NaN
  8. symbol is converted to string or number: a TypeError exception is thrown
  9. Primitive wrapper object is converted to boolean: true

Noncompliant Code Example

// Example 1
var cssString = "";
var backPosition;
if (animatedBackground.length === 3) {
    cssString += "backgroundPosition: " + backPosition + "px; "; // BAD_TYPE_COERCION alarm: Expression 'backPosition' has an undefined value and type-coerced to string type.
}

// Example 2
var mod = $index & 1;
if (mod !== old$index & 1) { // BAD_TYPE_COERCION alarm: Expression 'mod !== old$index' has boolean type and type-coerced to number type.
    if (mod === selector) {
        addClass(scope.$eval(attr[name]));
    } else {
        removeClass(scope.$eval(attr[name]));
    }
}

Compliant Code Example

// Example 1
var cssString = "";
var backPosition;
if (animatedBackground.length === 3) {
    backPosition = 0; // Assign a valid value.
    cssString += "backgroundPosition: " + backPosition + "px; ";
}

// Example 2
var mod = $index & 1;
if (mod !== (old$index & 1)) { // Use parentheses.
    if (mod === selector) {
        addClass(scope.$eval(attr[name]));
    } else {
        removeClass(scope.$eval(attr[name]));
    }
}

Version

This rule was introduced in DeepScan 1.0.0-alpha.

See