Suspicious type coercion should be avoided

  • BAD_TYPE_COERCION
  • Error
  • Medium
  • cwe

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 @ <All types> (X is undefined/null/non-numeric string/symbol/object. @ means -, *, /, %, **.)
    • X @ Y (X is undefined/null/boolean/non-numeric string/symbol except for the case where X and Y are both strings. @ means <, <=, >, >=.)
    • X @ number (X is object. @ means <, <=, >, >=.)
    • X & <All types> (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 ==, !=.)
    • @ X (X is non-numeric string. @ 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

View with compliant examples side by side
function example1() {
    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.
    }
    return cssString;
}

function example2() {
    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

View with noncompliant examples side by side
function example1() {
    var cssString = "";
    var backPosition;
    if (animatedBackground.length === 3) {
        backPosition = 0; // Assign a valid value.
        cssString += "backgroundPosition: " + backPosition + "px; ";
    }
    return cssString;
}

function example2() {
    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

Was this documentation helpful?