UNPKG

2.85 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 url: "https://eslint.org/docs/rules/valid-typeof"
18 },
19
20 schema: [
21 {
22 type: "object",
23 properties: {
24 requireStringLiterals: {
25 type: "boolean"
26 }
27 },
28 additionalProperties: false
29 }
30 ]
31 },
32
33 create(context) {
34
35 const VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"],
36 OPERATORS = ["==", "===", "!=", "!=="];
37
38 const requireStringLiterals = context.options[0] && context.options[0].requireStringLiterals;
39
40 /**
41 * Determines whether a node is a typeof expression.
42 * @param {ASTNode} node The node
43 * @returns {boolean} `true` if the node is a typeof expression
44 */
45 function isTypeofExpression(node) {
46 return node.type === "UnaryExpression" && node.operator === "typeof";
47 }
48
49 //--------------------------------------------------------------------------
50 // Public
51 //--------------------------------------------------------------------------
52
53 return {
54
55 UnaryExpression(node) {
56 if (isTypeofExpression(node)) {
57 const parent = context.getAncestors().pop();
58
59 if (parent.type === "BinaryExpression" && OPERATORS.indexOf(parent.operator) !== -1) {
60 const sibling = parent.left === node ? parent.right : parent.left;
61
62 if (sibling.type === "Literal" || sibling.type === "TemplateLiteral" && !sibling.expressions.length) {
63 const value = sibling.type === "Literal" ? sibling.value : sibling.quasis[0].value.cooked;
64
65 if (VALID_TYPES.indexOf(value) === -1) {
66 context.report({ node: sibling, message: "Invalid typeof comparison value." });
67 }
68 } else if (requireStringLiterals && !isTypeofExpression(sibling)) {
69 context.report({ node: sibling, message: "Typeof comparisons should be to string literals." });
70 }
71 }
72 }
73 }
74
75 };
76
77 }
78};