UNPKG

2.75 kBJavaScriptView Raw
1/**
2 * @fileoverview Ensures that the results of typeof are compared against a valid string
3 * @author Ian Christian Myers
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Rule Definition
9//------------------------------------------------------------------------------
10
11module.exports = {
12 meta: {
13 docs: {
14 description: "enforce comparing `typeof` expressions against valid strings",
15 category: "Possible Errors",
16 recommended: true
17 },
18
19 schema: [
20 {
21 type: "object",
22 properties: {
23 requireStringLiterals: {
24 type: "boolean"
25 }
26 },
27 additionalProperties: false
28 }
29 ]
30 },
31
32 create(context) {
33
34 const VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"],
35 OPERATORS = ["==", "===", "!=", "!=="];
36
37 const requireStringLiterals = context.options[0] && context.options[0].requireStringLiterals;
38
39 /**
40 * Determines whether a node is a typeof expression.
41 * @param {ASTNode} node The node
42 * @returns {boolean} `true` if the node is a typeof expression
43 */
44 function isTypeofExpression(node) {
45 return node.type === "UnaryExpression" && node.operator === "typeof";
46 }
47
48 //--------------------------------------------------------------------------
49 // Public
50 //--------------------------------------------------------------------------
51
52 return {
53
54 UnaryExpression(node) {
55 if (isTypeofExpression(node)) {
56 const parent = context.getAncestors().pop();
57
58 if (parent.type === "BinaryExpression" && OPERATORS.indexOf(parent.operator) !== -1) {
59 const sibling = parent.left === node ? parent.right : parent.left;
60
61 if (sibling.type === "Literal" || sibling.type === "TemplateLiteral" && !sibling.expressions.length) {
62 const value = sibling.type === "Literal" ? sibling.value : sibling.quasis[0].value.cooked;
63
64 if (VALID_TYPES.indexOf(value) === -1) {
65 context.report(sibling, "Invalid typeof comparison value.");
66 }
67 } else if (requireStringLiterals && !isTypeofExpression(sibling)) {
68 context.report(sibling, "Typeof comparisons should be to string literals.");
69 }
70 }
71 }
72 }
73
74 };
75
76 }
77};